summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2025-05-26 11:19:11 +0200
committerJulian Andres Klode <jak@debian.org>2025-05-26 12:45:12 +0200
commit717ca7922be8a025b8034dc840b2ad9befc3b171 (patch)
treefbca1f0044f1f8f40235b18fa1e9a971861403d7 /apt-pkg
parent6c3196950acb6a1351c221c74edd9c3ba691b7e5 (diff)
solver3: Assume manual packages
If we have allowed the removal of manual packages, assume them all before starting the solver. This should ensure that as long as there is a solution that does not remove a manually installed package, it is found. This requires a sweeping set of changes in the test suite, but ensures that we get "safe" behavior from the solver. We have in particular seen that without asserting the installed packages, several people ended up with ubuntu-minimal and perl removed in a situation where that was not warranted, that is, they install winehq, and then pull in some new perl packages in a newer version than the installed one, and the solver chose to create a mismatched version set, which then caused the main perl package to not be installable. Oops: 1b55173a-3526-11f0-b7ac-fa163e171f02 Oops: dbd5149e-36b9-11f0-bb74-fa163ec44ecd
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/solver3.cc17
1 files changed, 16 insertions, 1 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index eeac6f177..be1576e98 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -1098,6 +1098,7 @@ bool APT::Solver::Solve()
bool APT::Solver::FromDepCache(pkgDepCache &depcache)
{
DefaultRootSetFunc2 rootSet(&cache);
+ std::vector<Var> manualPackages;
// Enforce strict pinning rules by rejecting all forbidden versions.
if (StrictPinning)
@@ -1175,6 +1176,9 @@ bool APT::Solver::FromDepCache(pkgDepCache &depcache)
if (not AddWork(Work{insertedW, depth()}))
return false;
+ if (not isAuto)
+ manualPackages.push_back(Var(P));
+
// Given A->A2|A1, B->B1|B2; Bn->An, if we select `not A1`, we
// should try to install A2 before trying B so we end up with
// A2, B2, instead of removing A1 to keep B1 installed. This
@@ -1209,7 +1213,18 @@ bool APT::Solver::FromDepCache(pkgDepCache &depcache)
}
}
- return Propagate();
+ if (not Propagate())
+ return false;
+
+ std::stable_sort(manualPackages.begin(), manualPackages.end(), CompareProviders3{cache, policy, {}, *this});
+ for (auto assumption : manualPackages)
+ {
+ if (not Assume(assumption, true, {}) || not Propagate())
+ if (not Pop())
+ abort();
+ }
+
+ return true;
}
bool APT::Solver::ToDepCache(pkgDepCache &depcache) const