summaryrefslogtreecommitdiff
path: root/apt-pkg/solver3.cc
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2025-05-28 13:57:17 +0200
committerJulian Andres Klode <jak@debian.org>2025-05-28 13:58:04 +0200
commit3f8162ea008b8a3330a1113a94bc654f05000660 (patch)
treeca4964720d28be2484cf4e962fa42c30a2a770d5 /apt-pkg/solver3.cc
parentadb67fa7abf9eb30d312fdd3284f9d86a2899cb2 (diff)
solver3: Only merge dependencies on the same package
Avoid or groups and dependencies on different (virtual) packages, to avoid some common pitfalls like the added xorg test case.
Diffstat (limited to 'apt-pkg/solver3.cc')
-rw-r--r--apt-pkg/solver3.cc20
1 files changed, 14 insertions, 6 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index 95cff96f3..a458acb0b 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -673,18 +673,26 @@ static bool SameOrGroup(pkgCache::DepIterator a, pkgCache::DepIterator b)
const APT::Solver::Clause *APT::Solver::RegisterClause(Clause &&clause)
{
auto &clauses = (*this)[clause.reason].clauses;
-
- if (not clause.negative)
+ pkgCache::DepIterator dep(cache, clause.dep);
+
+ // Merge dependencies on the same name into a single one, and restrict their solution space.
+ // For example, given dependencies on
+ // bar Depends: pkg (<< 3), pkg (>> 2)
+ // foo Provides: pkg (= 1)
+ // The solution must always be pkg (= 2) and not say pkg (= 3), foo.
+ // FIXME: This would be nice to merge across or groups too, but we can't do that yet.
+ if (not clause.negative && not dep.end() && not(dep->CompareOp & pkgCache::Dep::Or))
{
- // If we get multiple dependencies of the same class on related sets of packages,
- // intersect them. In particular this deals with dependencies of the form
- // Depends: pkg (>= 1-1), pkg (<= 1-1.1)
- // which is a common pattern used to express dependencies on the same source version.
bool merged = false;
for (auto const &earlierClause : clauses)
{
if (earlierClause->negative)
continue;
+ // Skip dependencies with or groups or dependencies on different names
+ if (pkgCache::DepIterator earlierDep(cache, earlierClause->dep);
+ earlierDep.end() || (earlierDep->CompareOp & pkgCache::Dep::Or) ||
+ earlierDep.TargetPkg() != dep.TargetPkg())
+ continue;
if (std::none_of(earlierClause->solutions.begin(), earlierClause->solutions.end(), [&clause](auto earlierSol)
{ return std::find(clause.solutions.begin(),
clause.solutions.end(),