X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b49068c566d749130e023536d54588c948c16edf..422a2eba84361a8dfd84b549c13037512779c572:/apt-pkg/statechanges.cc diff --git a/apt-pkg/statechanges.cc b/apt-pkg/statechanges.cc index a20319d2d..35af45538 100644 --- a/apt-pkg/statechanges.cc +++ b/apt-pkg/statechanges.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -14,46 +15,64 @@ class StateChanges::Private { public: APT::VersionVector hold; + APT::VersionVector unhold; APT::VersionVector install; + APT::VersionVector deinstall; + APT::VersionVector purge; APT::VersionVector error; }; -void StateChanges::Hold(pkgCache::VerIterator const &Ver) -{ - d->hold.push_back(Ver); -} -APT::VersionVector& StateChanges::Hold() -{ - return d->hold; -} -void StateChanges::Unhold(pkgCache::VerIterator const &Ver) -{ - d->install.push_back(Ver); -} -APT::VersionVector& StateChanges::Unhold() -{ - return d->install; +#define APT_GETTERSETTER(Name, Container) \ +void StateChanges::Name(pkgCache::VerIterator const &Ver) \ +{ \ + if (Ver.end() == false) \ + Container.push_back(Ver); \ +}\ +APT::VersionVector& StateChanges::Name() \ +{ \ + return Container; \ } +APT_GETTERSETTER(Hold, d->hold) +APT_GETTERSETTER(Unhold, d->unhold) +APT_GETTERSETTER(Install, d->install) +APT_GETTERSETTER(Remove, d->deinstall) +APT_GETTERSETTER(Purge, d->purge) +#undef APT_GETTERSETTER APT::VersionVector& StateChanges::Error() { return d->error; } -void StateChanges::Discard() +void StateChanges::clear() { d->hold.clear(); + d->unhold.clear(); d->install.clear(); + d->deinstall.clear(); + d->purge.clear(); d->error.clear(); } +bool StateChanges::empty() const +{ + return d->hold.empty() && + d->unhold.empty() && + d->install.empty() && + d->deinstall.empty() && + d->purge.empty() && + d->error.empty(); +} + bool StateChanges::Save(bool const DiscardOutput) { + bool const Debug = _config->FindB("Debug::pkgDpkgPm", false); d->error.clear(); - if (d->hold.empty() && d->install.empty()) + if (d->hold.empty() && d->unhold.empty() && d->install.empty() && d->deinstall.empty() && d->purge.empty()) return true; std::vector Args = debSystem::GetDpkgBaseCommand(); // ensure dpkg knows about the package so that it keeps the status we set + if (d->hold.empty() == false || d->install.empty() == false) { APT::VersionVector makeDpkgAvailable; auto const notInstalled = [](pkgCache::VerIterator const &V) { return V.ParentPkg()->CurrentVer == 0; }; @@ -67,54 +86,132 @@ bool StateChanges::Save(bool const DiscardOutput) // FIXME: supported only since 1.17.7 in dpkg Args.push_back("-"); int dummyAvail = -1; - pid_t const dpkgMergeAvail = debSystem::ExecDpkg(Args, &dummyAvail, nullptr, true); + if (Debug) + { + for (auto const &V: makeDpkgAvailable) + { + std::clog << "echo 'Dummy record for " << V.ParentPkg().FullName(false) << "' | "; + std::copy(Args.begin(), Args.end(), std::ostream_iterator(std::clog, " ")); + std::clog << std::endl; + } + } + else + { + pid_t const dpkgMergeAvail = debSystem::ExecDpkg(Args, &dummyAvail, nullptr, true); - FILE* dpkg = fdopen(dummyAvail, "w"); - for (auto const &V: makeDpkgAvailable) - fprintf(dpkg, "Package: %s\nVersion: 0~\nArchitecture: %s\nMaintainer: Dummy Example \n" - "Description: dummy package record\n A record is needed to put a package on hold, so here it is.\n\n", V.ParentPkg().Name(), V.Arch()); - fclose(dpkg); + FILE* dpkg = fdopen(dummyAvail, "w"); + for (auto const &V: makeDpkgAvailable) + fprintf(dpkg, "Package: %s\nVersion: 0~\nArchitecture: %s\nMaintainer: Dummy Example \n" + "Description: dummy package record\n A record is needed to put a package on hold, so here it is.\n\n", V.ParentPkg().Name(), V.Arch()); + fclose(dpkg); - ExecWait(dpkgMergeAvail, "dpkg --merge-avail", true); + ExecWait(dpkgMergeAvail, "dpkg --merge-avail", true); + } Args.erase(Args.begin() + BaseArgs, Args.end()); } } bool const dpkgMultiArch = _system->MultiArchSupported(); Args.push_back("--set-selections"); - int selections = -1; - pid_t const dpkgSelections = debSystem::ExecDpkg(Args, &selections, nullptr, DiscardOutput); - - FILE* dpkg = fdopen(selections, "w"); - std::string state; - auto const dpkgName = [&](pkgCache::VerIterator const &V) { - pkgCache::PkgIterator P = V.ParentPkg(); - if (dpkgMultiArch == false) - fprintf(dpkg, "%s %s\n", P.FullName(true).c_str(), state.c_str()); - else - fprintf(dpkg, "%s:%s %s\n", P.Name(), V.Arch(), state.c_str()); - }; - if (d->hold.empty() == false) + if (Debug) { - state = "hold"; - std::for_each(d->hold.begin(), d->hold.end(), dpkgName); + std::string state; + auto const dpkgName = [&](pkgCache::VerIterator const &V) { + pkgCache::PkgIterator P = V.ParentPkg(); + if (strcmp(V.Arch(), "none") == 0) + ioprintf(std::clog, "echo '%s %s' | ", P.Name(), state.c_str()); + else if (dpkgMultiArch == false) + ioprintf(std::clog, "echo '%s %s' | ", P.FullName(true).c_str(), state.c_str()); + else + ioprintf(std::clog, "echo '%s:%s %s' | ", P.Name(), V.Arch(), state.c_str()); + std::copy(Args.begin(), Args.end(), std::ostream_iterator(std::clog, " ")); + std::clog << std::endl; + }; + for (auto const &V: d->unhold) + { + if (V.ParentPkg()->CurrentVer != 0) + state = "install"; + else + state = "deinstall"; + dpkgName(V); + } + if (d->purge.empty() == false) + { + state = "purge"; + std::for_each(d->purge.begin(), d->purge.end(), dpkgName); + } + if (d->deinstall.empty() == false) + { + state = "deinstall"; + std::for_each(d->deinstall.begin(), d->deinstall.end(), dpkgName); + } + if (d->hold.empty() == false) + { + state = "hold"; + std::for_each(d->hold.begin(), d->hold.end(), dpkgName); + } + if (d->install.empty() == false) + { + state = "install"; + std::for_each(d->install.begin(), d->install.end(), dpkgName); + } } - if (d->install.empty() == false) + else { - state = "install"; - std::for_each(d->install.begin(), d->install.end(), dpkgName); - } - fclose(dpkg); + int selections = -1; + pid_t const dpkgSelections = debSystem::ExecDpkg(Args, &selections, nullptr, DiscardOutput); - if (ExecWait(dpkgSelections, "dpkg --set-selections") == false) - { - if (d->hold.empty()) - std::swap(d->install, d->error); - else if (d->install.empty()) - std::swap(d->hold, d->error); - else + FILE* dpkg = fdopen(selections, "w"); + std::string state; + auto const dpkgName = [&](pkgCache::VerIterator const &V) { + pkgCache::PkgIterator P = V.ParentPkg(); + if (strcmp(V.Arch(), "none") == 0) + fprintf(dpkg, "%s %s\n", P.Name(), state.c_str()); + else if (dpkgMultiArch == false) + fprintf(dpkg, "%s %s\n", P.FullName(true).c_str(), state.c_str()); + else + fprintf(dpkg, "%s:%s %s\n", P.Name(), V.Arch(), state.c_str()); + }; + for (auto const &V: d->unhold) + { + if (V.ParentPkg()->CurrentVer != 0) + state = "install"; + else + state = "deinstall"; + dpkgName(V); + } + if (d->purge.empty() == false) + { + state = "purge"; + std::for_each(d->purge.begin(), d->purge.end(), dpkgName); + } + if (d->deinstall.empty() == false) + { + state = "deinstall"; + std::for_each(d->deinstall.begin(), d->deinstall.end(), dpkgName); + } + if (d->hold.empty() == false) + { + state = "hold"; + std::for_each(d->hold.begin(), d->hold.end(), dpkgName); + } + if (d->install.empty() == false) + { + state = "install"; + std::for_each(d->install.begin(), d->install.end(), dpkgName); + } + fclose(dpkg); + + if (ExecWait(dpkgSelections, "dpkg --set-selections") == false) { - std::swap(d->hold, d->error); + std::move(d->purge.begin(), d->purge.end(), std::back_inserter(d->error)); + d->purge.clear(); + std::move(d->deinstall.begin(), d->deinstall.end(), std::back_inserter(d->error)); + d->deinstall.clear(); + std::move(d->hold.begin(), d->hold.end(), std::back_inserter(d->error)); + d->hold.clear(); + std::move(d->unhold.begin(), d->unhold.end(), std::back_inserter(d->error)); + d->unhold.clear(); std::move(d->install.begin(), d->install.end(), std::back_inserter(d->error)); d->install.clear(); }