diff options
author | David Kalnischkies <david@kalnischkies.de> | 2020-04-27 13:51:46 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2020-04-27 13:51:46 +0200 |
commit | ae23e53f99ea0b7920744a7303fdee64796b7cce (patch) | |
tree | 6201c01507e3db1e897918f3b8a03701bbca708f | |
parent | ca14e1e2c3f3c9782f374757ca4605ce7e5670ad (diff) |
Protect a package while resolving in MarkInstall
Strange things happen if while resolving the dependencies of a package
said dependencies want to remove the package. The allow-scores test e.g.
removed the preferred alternative in favor of the last one now that they
were exclusive. In our or-group for Recommends we would "just" not
statisfy the Recommends and for Depends we engage the ProblemResolver…
-rw-r--r-- | apt-pkg/depcache.cc | 35 | ||||
-rw-r--r-- | apt-pkg/depcache.h | 4 | ||||
-rwxr-xr-x | test/integration/test-allow-scores-for-all-dependency-types | 34 | ||||
-rwxr-xr-x | test/integration/test-explore-or-groups-in-markinstall | 14 |
4 files changed, 48 insertions, 39 deletions
diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 2254a9b5d..7730aaf5b 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1180,7 +1180,7 @@ bool pkgDepCache::MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerItera return true; } /*}}}*/ -bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/ +bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(bool const propagateProctected, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade) /*{{{*/ { for (auto const &InstPkg : toUpgrade) if (not MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps)) @@ -1189,14 +1189,14 @@ bool pkgDepCache::MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, u std::clog << OutputInDepth(Depth) << " Removing: " << InstPkg.FullName() << " as upgrade is not possible\n"; if (not MarkDelete(InstPkg, false, Depth + 1, false)) return false; - if (PkgState[Pkg->ID].Protect()) + if (propagateProctected) MarkProtected(InstPkg); } toUpgrade.clear(); return true; } /*}}}*/ -bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto) /*{{{*/ +bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProctected) /*{{{*/ { auto const IsSatisfiedByInstalled = [&](auto const D) { return (DepState[D.ID] & DepInstall) == DepInstall; }; for (auto &&Dep : toInstall) @@ -1286,7 +1286,7 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign if (DebugAutoInstall) std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.FullName() << " as " << End.DepType() << " of " << Pkg.FullName() << '\n'; - if (IsCriticalDep && toUpgrade.size() == 1 && PkgState[Pkg->ID].Protect()) + if (propagateProctected && IsCriticalDep && toUpgrade.size() == 1) { if (not MarkInstall(InstPkg, false, Depth + 1, false, ForceImportantDeps)) continue; @@ -1303,9 +1303,9 @@ bool pkgDepCache::MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsign } if (not foundSolution && IsCriticalDep) { - StateCache &State = PkgState[Pkg->ID]; - if (not State.Protect()) + if (not propagateProctected) { + StateCache &State = PkgState[Pkg->ID]; RemoveSizes(Pkg); RemoveStates(Pkg); if (Pkg->CurrentVer != 0) @@ -1380,7 +1380,26 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, if (DebugMarker) std::clog << OutputInDepth(Depth) << "MarkInstall " << APT::PrettyPkg(this, Pkg) << " FU=" << FromUser << '\n'; - if (not MarkInstall_UpgradeOrRemoveConflicts(Pkg, Depth, ForceImportantDeps, toUpgrade)) + class ScopedProtected + { + pkgDepCache::StateCache &P; + bool const already; + + public: + ScopedProtected(pkgDepCache::StateCache &p) : P{p}, already{P.Protect()} + { + if (not already) + P.iFlags |= Protected; + } + ~ScopedProtected() + { + if (not already) + P.iFlags &= (~Protected); + } + operator bool() noexcept { return already; } + } propagateProctected{PkgState[Pkg->ID]}; + + if (not MarkInstall_UpgradeOrRemoveConflicts(propagateProctected, Depth, ForceImportantDeps, toUpgrade)) return false; bool const MoveAutoBitToDependencies = [&]() { @@ -1400,7 +1419,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, }(); APT::PackageVector toMoveAuto; - if (not MarkInstall_InstallDependencies(Pkg, Depth, ForceImportantDeps, toInstall, MoveAutoBitToDependencies ? &toMoveAuto : nullptr)) + if (not MarkInstall_InstallDependencies(Pkg, Depth, ForceImportantDeps, toInstall, MoveAutoBitToDependencies ? &toMoveAuto : nullptr, propagateProctected)) return false; if (MoveAutoBitToDependencies) diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 339686b95..1579fedbe 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -521,8 +521,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace APT_HIDDEN bool MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, bool FromUser); APT_HIDDEN bool MarkInstall_CollectDependencies(pkgCache::VerIterator const &PV, std::vector<pkgCache::DepIterator> &toInstall, std::vector<pkgCache::DepIterator> &toRemove); APT_HIDDEN bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgCache::VerIterator const &PV, unsigned long Depth, std::vector<pkgCache::DepIterator> &toRemove, APT::PackageVector &toUpgrade); - APT_HIDDEN bool MarkInstall_UpgradeOrRemoveConflicts(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade); - APT_HIDDEN bool MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto); + APT_HIDDEN bool MarkInstall_UpgradeOrRemoveConflicts(bool const propagateProtected, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade); + APT_HIDDEN bool MarkInstall_InstallDependencies(PkgIterator const &Pkg, unsigned long Depth, bool const ForceImportantDeps, std::vector<pkgCache::DepIterator> &toInstall, APT::PackageVector *const toMoveAuto, bool const propagateProtected); }; #endif diff --git a/test/integration/test-allow-scores-for-all-dependency-types b/test/integration/test-allow-scores-for-all-dependency-types index 9b300b7a7..b8a9ed3ea 100755 --- a/test/integration/test-allow-scores-for-all-dependency-types +++ b/test/integration/test-allow-scores-for-all-dependency-types @@ -116,42 +116,18 @@ Conf baz (2 unversioned [amd64])' aptget install baz -st unversioned testsuccessequal 'Reading package lists... Building dependency tree... The following additional packages will be installed: - foo -The following packages will be REMOVED: bar -The following NEW packages will be installed: - baz -The following packages will be upgraded: - foo -1 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. -Remv bar [1] -Inst foo [1] (2 versioned [amd64]) -Inst baz (2 versioned [amd64]) -Conf foo (2 versioned [amd64]) -Conf baz (2 versioned [amd64])' aptget install baz -st versioned - -testsuccessequal 'Reading package lists... -Building dependency tree... -The following NEW packages will be installed: - baz -0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded. -Inst baz (2 unversioned [amd64]) -Conf baz (2 unversioned [amd64])' aptget install baz -st unversioned -testsuccessequal 'Reading package lists... -Building dependency tree... -The following additional packages will be installed: - foo The following packages will be REMOVED: - bar + foo The following NEW packages will be installed: baz The following packages will be upgraded: - foo + bar 1 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. -Remv bar [1] -Inst foo [1] (2 versioned [amd64]) +Remv foo [1] +Inst bar [1] (2 versioned [amd64]) Inst baz (2 versioned [amd64]) -Conf foo (2 versioned [amd64]) +Conf bar (2 versioned [amd64]) Conf baz (2 versioned [amd64])' aptget install baz -st versioned # recreating the exact situation is hard, so we pull tricks to get the score diff --git a/test/integration/test-explore-or-groups-in-markinstall b/test/integration/test-explore-or-groups-in-markinstall index 259155854..5669e47b3 100755 --- a/test/integration/test-explore-or-groups-in-markinstall +++ b/test/integration/test-explore-or-groups-in-markinstall @@ -15,6 +15,10 @@ insertpackage 'unstable' 'bad-level0' 'all' '1' 'Depends: unneeded, unknown' insertpackage 'unstable' 'bad-level1' 'all' '1' 'Depends: bad-level0' insertpackage 'unstable' 'bad-upgrade-level0' 'all' '2' 'Depends: unneeded, unknown' insertpackage 'unstable' 'bad-upgrade-level1' 'all' '2' 'Depends: bad-upgrade-level0 (>= 2)' +insertpackage 'unstable' 'bad-conflict-level0' 'all' '1' 'Depends: unneeded +Conflicts: bad-conflict-level2' +insertpackage 'unstable' 'bad-conflict-level1' 'all' '1' 'Depends: bad-conflict-level0' +insertpackage 'unstable' 'bad-conflict-level2' 'all' '1' 'Depends: bad-conflict-level1' insertinstalledpackage 'upgrade' 'all' '1' insertinstalledpackage 'bad-upgrade' 'all' '1' @@ -29,6 +33,8 @@ insertfoos() { insertpackage 'unstable' "foo-${1}-upgrade-level0" 'all' '1' "${2}: bad-upgrade (>= 2) | okay | upgrade (>= 2) | later" insertpackage 'unstable' "foo-${1}-upgrade-level1" 'all' '1' "${2}: bad-upgrade-level0 (>= 2) | bad-upgrade-level0 (>= 2) | bad-level0 | okay | upgrade (>= 2) | later" insertpackage 'unstable' "foo-${1}-upgrade-level2" 'all' '1' "${2}: bad-upgrade-level1 (>= 2) | bad-upgrade-level1 (>= 2) | bad-level1 | okay | upgrade (>= 2) | later" + + insertpackage 'unstable' "foo-${1}-conflict" 'all' '1' "${2}: unknown | bad-conflict-level2 | okay | later" } insertfoos 'd' 'Depends' insertfoos 'r' 'Recommends' @@ -65,6 +71,14 @@ The following packages will be upgraded: upgrade 1 upgraded, 1 newly installed, 0 to remove and $((2-${level})) not upgraded." apt install foo-${1}-upgrade-level${level} -s done + + testsuccessheadequal 7 "Reading package lists... +Building dependency tree... +The following additional packages will be installed: + okay +The following NEW packages will be installed: + foo-${1}-conflict okay +0 upgraded, 2 newly installed, 0 to remove and 3 not upgraded." apt install foo-${1}-conflict -s } checkfoos 'd' 'Depends' checkfoos 'r' 'Recommends' |