diff options
| author | Julian Andres Klode <jak@debian.org> | 2025-05-26 11:19:11 +0200 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2025-05-26 12:45:12 +0200 |
| commit | 717ca7922be8a025b8034dc840b2ad9befc3b171 (patch) | |
| tree | fbca1f0044f1f8f40235b18fa1e9a971861403d7 /apt-pkg | |
| parent | 6c3196950acb6a1351c221c74edd9c3ba691b7e5 (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.cc | 17 |
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 |
