summaryrefslogtreecommitdiff
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
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.
-rw-r--r--apt-pkg/solver3.cc20
-rwxr-xr-xtest/integration/test-ubuntu-bug-2111792-intersecting-dependencies53
2 files changed, 67 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(),
diff --git a/test/integration/test-ubuntu-bug-2111792-intersecting-dependencies b/test/integration/test-ubuntu-bug-2111792-intersecting-dependencies
index 86866b233..b63991aa4 100755
--- a/test/integration/test-ubuntu-bug-2111792-intersecting-dependencies
+++ b/test/integration/test-ubuntu-bug-2111792-intersecting-dependencies
@@ -24,6 +24,16 @@ insertpackage 'unstable' 'git-rec-ng' 'amd64,i386' '1:2.26.2-1' 'Recommends: git
Depends: git (<< 1:2.26.2-.)'
insertpackage 'unstable' 'chaos-actor' 'amd64,i386' '1' 'Provides: git (2:1)'
+# Another test case we don't want to merge
+insertpackage 'unstable' 'xserver-xorg' 'amd64,i386' '1' 'Depends: xserver-xorg-input-all | xorg-driver-input, xserver-xorg-video-all | xorg-driver-video, xorg-driver-input, xorg-driver-video'
+insertpackage 'unstable' 'xserver-xorg-noalt' 'amd64,i386' '1' 'Depends: xorg-driver-input, xorg-driver-video'
+
+
+insertpackage 'unstable' 'xserver-xorg-input-all' 'amd64,i386' '1' 'Provides: xorg-driver-input'
+insertpackage 'unstable' 'xserver-xorg-video-all' 'amd64,i386' '1' 'Provides: xorg-driver-video'
+insertpackage 'unstable' 'xorgxrdp' 'amd64,i386' '1' 'Provides: xorg-driver-input, xorg-driver-video
+Priority: extra'
+
setupaptarchive
msgmsg 'The setup is' 'fine'
@@ -178,3 +188,46 @@ The following NEW packages will be installed:
0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.
Inst git-rec-ng (1:2.26.2-1 unstable [amd64])
Conf git-rec-ng (1:2.26.2-1 unstable [amd64])' apt install git-rec-ng -s
+
+msgmsg 'Check that we do not merge unrelated things'
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Solving dependencies...
+The following additional packages will be installed:
+ xserver-xorg-input-all xserver-xorg-video-all
+The following NEW packages will be installed:
+ xserver-xorg xserver-xorg-input-all xserver-xorg-video-all
+0 upgraded, 3 newly installed, 0 to remove and 2 not upgraded.
+Inst xserver-xorg-input-all (1 unstable [amd64])
+Inst xserver-xorg-video-all (1 unstable [amd64])
+Inst xserver-xorg (1 unstable [amd64])
+Conf xserver-xorg-input-all (1 unstable [amd64])
+Conf xserver-xorg-video-all (1 unstable [amd64])
+Conf xserver-xorg (1 unstable [amd64])' apt install -s xserver-xorg
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Solving dependencies...
+The following additional packages will be installed:
+ xserver-xorg-input-all xserver-xorg-video-all
+The following NEW packages will be installed:
+ xserver-xorg-input-all xserver-xorg-noalt xserver-xorg-video-all
+0 upgraded, 3 newly installed, 0 to remove and 2 not upgraded.
+Inst xserver-xorg-input-all (1 unstable [amd64])
+Inst xserver-xorg-video-all (1 unstable [amd64])
+Inst xserver-xorg-noalt (1 unstable [amd64])
+Conf xserver-xorg-input-all (1 unstable [amd64])
+Conf xserver-xorg-video-all (1 unstable [amd64])
+Conf xserver-xorg-noalt (1 unstable [amd64])' apt install -s xserver-xorg-noalt
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Solving dependencies...
+The following NEW packages will be installed:
+ xorgxrdp xserver-xorg
+0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded.
+Inst xorgxrdp (1 unstable [amd64])
+Inst xserver-xorg (1 unstable [amd64])
+Conf xorgxrdp (1 unstable [amd64])
+Conf xserver-xorg (1 unstable [amd64])' apt install -s xserver-xorg xorgxrdp