From e077370ffcb3669a50a600e80356c2002e6b176d Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 8 Jul 2022 17:46:05 +0200 Subject: Mark broken reverse depends for upgrade Currently the solver handles cases where a Breaks b (<< 1) and if we install that a, upgrades b. However, where b Depends a (= 1), b was removed again. This addresses the problem by iterating over installed reverse dependencies of upgrades and upgrading them so that both cases work roughly similarly. LP: #1974196 --- apt-pkg/depcache.cc | 34 +++++++++++++++++++++++++++++++++ test/integration/test-multiarch-allowed | 3 +-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index a5b586f5b..82b2fda99 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1445,6 +1445,34 @@ static bool MarkInstall_RemoveConflictsIfNotUpgradeable(pkgDepCache &Cache, bool return not failedToRemoveSomething; } /*}}}*/ +static bool MarkInstall_CollectReverseDepends(pkgDepCache &Cache, bool const DebugAutoInstall, pkgCache::VerIterator const &PV, unsigned long Depth, APT::PackageVector &toUpgrade) /*{{{*/ +{ + auto CurrentVer = PV.ParentPkg().CurrentVer(); + if (CurrentVer.end()) + return true; + for (pkgCache::DepIterator D = PV.ParentPkg().RevDependsList(); D.end() == false; ++D) + { + auto ParentPkg = D.ParentPkg(); + // Skip non-installed versions and packages already marked for upgrade + if (ParentPkg.CurrentVer() != D.ParentVer() || Cache[ParentPkg].Install()) + continue; + // We only handle important positive dependencies, RemoveConflictsIfNotUpgradeable handles negative + if (not Cache.IsImportantDep(D) || D.IsNegative()) + continue; + // The dependency was previously not satisfied (e.g. part of an or group) or will be satisfied, so it's OK + if (not D.IsSatisfied(CurrentVer) || D.IsSatisfied(PV)) + continue; + if (std::find(toUpgrade.begin(), toUpgrade.end(), ParentPkg) != toUpgrade.end()) + continue; + + if (DebugAutoInstall) + std::clog << OutputInDepth(Depth) << " Upgrading: " << APT::PrettyPkg(&Cache, ParentPkg) << " due to " << APT::PrettyDep(&Cache, D) << "\n"; + + toUpgrade.push_back(ParentPkg); + } + return true; +} + /*}}}*/ static bool MarkInstall_UpgradeOrRemoveConflicts(pkgDepCache &Cache, bool const DebugAutoInstall, unsigned long Depth, bool const ForceImportantDeps, APT::PackageVector &toUpgrade, bool const propagateProtected, bool const FromUser) /*{{{*/ { bool failedToRemoveSomething = false; @@ -1641,6 +1669,12 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, return false; hasFailed = true; } + if (not MarkInstall_CollectReverseDepends(*this, DebugAutoInstall, PV, Depth, toUpgrade)) + { + if (failEarly) + return false; + hasFailed = true; + } } if (not FromUser && not MarkInstall_StateChange(Pkg, AutoInst, FromUser)) diff --git a/test/integration/test-multiarch-allowed b/test/integration/test-multiarch-allowed index 69d0bfa10..db7f37169 100755 --- a/test/integration/test-multiarch-allowed +++ b/test/integration/test-multiarch-allowed @@ -64,8 +64,7 @@ Conf foo:i386 (1 unstable [i386]) Conf needsfoo:i386 (1 unstable [i386])' aptget install needsfoo:i386 -s testfailureequal "$BADPREFIX The following packages have unmet dependencies: - foo : Conflicts: foo:i386 but 1 is to be installed - foo:i386 : Conflicts: foo but 1 is to be installed + needsfoo:i386 : Depends: foo:i386 but it is not installable E: Unable to correct problems, you have held broken packages." aptget install needsfoo:i386 foo:amd64 -s testfailureequal "$BADPREFIX The following packages have unmet dependencies: -- cgit v1.2.3-70-g09d2