summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2022-07-08 17:46:05 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2022-07-11 16:37:33 +0200
commite077370ffcb3669a50a600e80356c2002e6b176d (patch)
tree38b778bc3bf1ed8779e6e8a273cadba006a2eaec
parent01634926847e7c70ce51ea4592d8da0a25d9150d (diff)
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
-rw-r--r--apt-pkg/depcache.cc34
-rwxr-xr-xtest/integration/test-multiarch-allowed3
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: