summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2025-03-12 18:34:48 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2025-03-12 18:52:16 +0100
commita4ce187b40f3bbd110a7cc35f9a5af5a8b7b0c9e (patch)
tree6f6bb4d49d13323d30544df9d77fe01522615454
parent5c101b3d4651b2f181ac586b088894cce5008d3b (diff)
solver3: Fix Recommends/Suggests vs Enhances confusion
We accidentally considered an Enhances a reason to keep a package installed, which of course it is not, fix the determination of "existing soft dependency" to only include soft dependencies that should keep a package installed in the autoremover to solve the issue. This also fixes edsp/mantic-upgrade-rel-to-2024-05-29.edsp to not install llvm-13-dev for clang-13 which is an installed package with no upgrade. Also ensure we stop after the first match; the DependsList() is ordered by decreasing priority and we don't want to override Recommends by Suggests in case a package declares both... LP: #2101800
-rw-r--r--apt-pkg/solver3.cc10
-rw-r--r--apt-pkg/solver3.h5
-rwxr-xr-xtest/integration/test-solver-recommends-depends8
3 files changed, 22 insertions, 1 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index 739309c59..f992d55b4 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -833,9 +833,17 @@ APT::Solver::Clause APT::Solver::TranslateOrGroup(pkgCache::DepIterator start, p
bool important = policy.IsImportantDep(start);
bool newOptional = true;
bool wasImportant = false;
+ auto importantToKeep = [this](pkgCache::DepIterator d)
+ {
+ return policy.IsImportantDep(d) || (KeepRecommends && d->Type == pkgCache::Dep::Recommends) || (KeepSuggests && d->Type == pkgCache::Dep::Suggests);
+ };
+
for (auto D = start.ParentPkg().CurrentVer().DependsList(); not D.end(); D++)
- if (not D.IsCritical() && not D.IsNegative() && D.TargetPkg() == start.TargetPkg())
+ if (not D.IsCritical() && importantToKeep(D) && D.TargetPkg() == start.TargetPkg())
+ {
newOptional = false, wasImportant = policy.IsImportantDep(D);
+ break;
+ }
bool satisfied = std::any_of(clause.solutions.begin(), clause.solutions.end(), [this](auto var)
{ return var.Pkg(cache) ? var.Pkg(cache)->CurrentVer != nullptr : Var(var.CastPkg(cache).CurrentVer()) == var; });
diff --git a/apt-pkg/solver3.h b/apt-pkg/solver3.h
index b7000c52e..1bdc13559 100644
--- a/apt-pkg/solver3.h
+++ b/apt-pkg/solver3.h
@@ -243,6 +243,11 @@ class Solver
// \brief If set, we use strict pinning.
int Timeout{_config->FindI("APT::Solver::Timeout", 10)};
+ // \brief Keep recommends installed
+ bool KeepRecommends{_config->FindB("APT::AutoRemove::RecommendsImportant", true)};
+ // \brief Keep suggests installed
+ bool KeepSuggests{_config->FindB("APT::AutoRemove::SuggestsImportant", true)};
+
// \brief Discover a variable, translating the underlying dependencies to the SAT presentation
//
// This does a breadth-first search of the entire dependency tree of var,
diff --git a/test/integration/test-solver-recommends-depends b/test/integration/test-solver-recommends-depends
index 90c5050a7..4b2f91254 100755
--- a/test/integration/test-solver-recommends-depends
+++ b/test/integration/test-solver-recommends-depends
@@ -13,9 +13,17 @@ insertpackage 'unstable' 'x' 'all' '3' 'Depends: xx
Recommends: b'
insertpackage 'unstable' 'xx' 'all' '3' 'Depends: a | b
Recommends: b'
+insertpackage 'installed,unstable' 'recommends-and-enhances' 'all' '3' 'Recommends: b
+Enhances:b'
setupaptarchive
+msgmsg "Test that the Enhances does not confuse the Recommends algorithm"
+testsuccessequal "Reading package lists...
+Building dependency tree...
+Calculating upgrade...
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." apt full-upgrade -s
+
msgmsg "Test that the Recommends does not influence the Depends"
testsuccessequal "The following additional packages will be installed:
a b