From e1f332324f81b589561a9d9bce8a55d4895f26ec Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 2 Sep 2022 11:07:58 +0200 Subject: Respect users pkg order on `apt install` for resolving The command line is evaluated in two steps: First all packages given are marked for install and as a second step the resolver is started on all of them in turn to get their dependencies installed. This is done so a user can provide a non-default choice on the command line and have it respected regardless of where on the command line it appears. On the other hand, the order in which dependencies are resolved can matter, so instead of using a "random" order, we now do this in the order given on the command line, so if you e.g. have a meta package pulling in non-default choices and mention it first the choices are respected predictably instead of depending on first appearance of the package name while creating the binary cache. I might have "broken" this more than a decade ago while introducing the reworked command line parsing for Multi-Arch, which also brought in the split into the two steps mentioned above which was the far more impactful 'respect user choice' change. This one should hardly matter in practice, but as the tests show, order can have surprising side effects. --- apt-private/private-install.cc | 19 ++++++++++++------- apt-private/private-install.h | 4 ++-- apt-private/private-upgrade.cc | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'apt-private') diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 34cc69805..08d58a53c 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -593,12 +593,12 @@ static const unsigned short MOD_INSTALL = 2; bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector &VolatileCmdL, CacheFile &Cache, int UpgradeMode, APT::PackageVector &HeldBackPackages) { - std::map verset; + std::map verset; std::set UnknownPackages; return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode, UnknownPackages, HeldBackPackages); } bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector &VolatileCmdL, CacheFile &Cache, - std::map &verset, int UpgradeMode, + std::map &verset, int UpgradeMode, std::set &UnknownPackages, APT::PackageVector &HeldBackPackages) { // Enter the special broken fixing mode if the user specified arguments @@ -639,8 +639,13 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector seen; + vs.second.erase(std::remove_if(vs.second.begin(), vs.second.end(), [&](auto const &p) { return not seen.insert(p->ID).second; }), vs.second.end()); + } for (auto const &I: VolatileCmdL) { @@ -834,14 +839,14 @@ std::vector GetPseudoPackages(pkgSourceList *const SL, CommandLine &C /* Install named packages */ struct PkgIsExtraInstalled { pkgCacheFile * const Cache; - APT::VersionSet const * const verset; - PkgIsExtraInstalled(pkgCacheFile * const Cache, APT::VersionSet const * const Container) : Cache(Cache), verset(Container) {} + APT::VersionVector const * const verset; + PkgIsExtraInstalled(pkgCacheFile * const Cache, APT::VersionVector const * const Container) : Cache(Cache), verset(Container) {} bool operator() (pkgCache::PkgIterator const &Pkg) { if ((*Cache)[Pkg].Install() == false) return false; pkgCache::VerIterator const Cand = (*Cache)[Pkg].CandidateVerIter(*Cache); - return verset->find(Cand) == verset->end(); + return std::find(verset->begin(), verset->end(), Cand) == verset->end(); } }; bool DoInstall(CommandLine &CmdL) @@ -857,7 +862,7 @@ bool DoInstall(CommandLine &CmdL) Cache.CheckDeps(CmdL.FileSize() != 1) == false) return false; - std::map verset; + std::map verset; std::set UnknownPackages; APT::PackageVector HeldBackPackages; diff --git a/apt-private/private-install.h b/apt-private/private-install.h index e3df9ac89..0f6d048fc 100644 --- a/apt-private/private-install.h +++ b/apt-private/private-install.h @@ -33,7 +33,7 @@ bool AddVolatileBinaryFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector bool AddVolatileSourceFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector &VolatileCmdL); bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector &VolatileCmdL, CacheFile &Cache, - std::map &verset, int UpgradeMode, + std::map &verset, int UpgradeMode, std::set &UnknownPackages, APT::PackageVector &HeldBackPackages); bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector &VolatileCmdL, CacheFile &Cache, int UpgradeMode, APT::PackageVector &HeldBackPackages); @@ -54,7 +54,7 @@ struct TryToInstall { pkgProblemResolver* Fix; bool FixBroken; unsigned long AutoMarkChanged; - APT::PackageSet doAutoInstallLater; + APT::PackageVector doAutoInstallLater; TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM), FixBroken(FixBroken), AutoMarkChanged(0) {}; diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc index 3423db525..97603dc16 100644 --- a/apt-private/private-upgrade.cc +++ b/apt-private/private-upgrade.cc @@ -27,7 +27,7 @@ static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags) if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false) return false; - std::map verset; + std::map verset; std::set UnknownPackages; APT::PackageVector HeldBackPackages; if (not DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeFlags, UnknownPackages, HeldBackPackages)) -- cgit v1.2.3-70-g09d2