summaryrefslogtreecommitdiff
path: root/apt-pkg/solver3.cc
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2025-03-10 22:09:31 +0000
committerJulian Andres Klode <jak@debian.org>2025-03-10 22:09:31 +0000
commite7a777ce61efa97f90595be418d757a83483002b (patch)
tree177f7294dc1a2f1426bf7cbfe9e87a970c476cf4 /apt-pkg/solver3.cc
parent57ed577700784b2f8ed4c2cd52a90ae8ab636677 (diff)
parent8a6b694108f41afd1e6cdba4c91481697f9b3004 (diff)
Merge branch 'solver3' into 'main'
solver3: Various bug fixes See merge request apt-team/apt!459
Diffstat (limited to 'apt-pkg/solver3.cc')
-rw-r--r--apt-pkg/solver3.cc43
1 files changed, 31 insertions, 12 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index c993c1096..739309c59 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -634,6 +634,23 @@ bool APT::Solver::Propagate()
return true;
}
+static bool SameOrGroup(pkgCache::DepIterator a, pkgCache::DepIterator b)
+{
+ while (1)
+ {
+ if (a->DependencyData != b->DependencyData)
+ return false;
+
+ // At least one has reached the end, break
+ if (not(a->CompareOp & pkgCache::Dep::Or) || not(b->CompareOp & pkgCache::Dep::Or))
+ break;
+
+ ++a, ++b;
+ }
+ // Fully iterated over a and b
+ return not(a->CompareOp & pkgCache::Dep::Or) && not(b->CompareOp & pkgCache::Dep::Or);
+}
+
const APT::Solver::Clause *APT::Solver::RegisterClause(Clause &&clause)
{
auto &clauses = (*this)[clause.reason].clauses;
@@ -701,8 +718,8 @@ void APT::Solver::Discover(Var var)
// This dependency is shared across all versions, skip it.
if (auto &pkgClauses = (*this)[Ver.ParentPkg()].clauses;
- std::any_of(pkgClauses.begin(), pkgClauses.end(), [start](auto &c)
- { return c->dep && c->dep->DependencyData == start->DependencyData; }))
+ std::any_of(pkgClauses.begin(), pkgClauses.end(), [this, start](auto &c)
+ { return c->dep && SameOrGroup(start, pkgCache::DepIterator(cache, c->dep)); }))
continue;
auto clause = TranslateOrGroup(start, end, Var(Ver));
@@ -723,18 +740,21 @@ void APT::Solver::RegisterCommonDependencies(pkgCache::PkgIterator Pkg)
{
for (auto dep = Pkg.VersionList().DependsList(); not dep.end();)
{
- pkgCache::DepIterator start;
- pkgCache::DepIterator end;
+ pkgCache::DepIterator start, end;
dep.GlobOr(start, end); // advances dep
bool allHaveDep = true;
- for (auto ver = Pkg.VersionList()++; not ver.end(); ver++)
+ for (auto ver = Pkg.VersionList()++; allHaveDep && not ver.end(); ver++)
{
bool haveDep = false;
- for (auto otherDep = ver.DependsList(); not haveDep && not otherDep.end(); otherDep++)
- haveDep = otherDep->DependencyData == start->DependencyData;
- if (!haveDep)
- allHaveDep = haveDep;
+ for (auto otherDep = ver.DependsList(); not haveDep && not otherDep.end();)
+ {
+ pkgCache::DepIterator otherStart, otherEnd;
+ otherDep.GlobOr(otherStart, otherEnd); // advances other dep
+ haveDep = SameOrGroup(start, otherStart);
+ }
+ if (not haveDep)
+ allHaveDep = false;
}
if (not allHaveDep)
continue;
@@ -746,7 +766,6 @@ void APT::Solver::RegisterCommonDependencies(pkgCache::PkgIterator Pkg)
APT::Solver::Clause APT::Solver::TranslateOrGroup(pkgCache::DepIterator start, pkgCache::DepIterator end, Var reason)
{
auto TgtPkg = start.TargetPkg();
- auto Ver = start.ParentVer();
// Non-important dependencies can only be installed if they are currently satisfied, see the check further
// below once we have calculated all possible solutions.
@@ -756,7 +775,7 @@ APT::Solver::Clause APT::Solver::TranslateOrGroup(pkgCache::DepIterator start, p
if (start->Type == pkgCache::Dep::Replaces || start->Type == pkgCache::Dep::Enhances)
return Clause{reason, Group::Satisfy, true};
if (unlikely(debug >= 3))
- std::cerr << "Found dependency critical " << Ver.ParentPkg().FullName() << "=" << Ver.VerStr() << " -> " << start.TargetPkg().FullName() << "\n";
+ std::cerr << "Found dependency critical " << reason.toString(cache) << " -> " << start.TargetPkg().FullName() << "\n";
Clause clause{reason, Group::Satisfy, not start.IsCritical() /* optional */, start.IsNegative()};
@@ -819,7 +838,7 @@ APT::Solver::Clause APT::Solver::TranslateOrGroup(pkgCache::DepIterator start, p
newOptional = false, wasImportant = policy.IsImportantDep(D);
bool satisfied = std::any_of(clause.solutions.begin(), clause.solutions.end(), [this](auto var)
- { return Var(var.CastPkg(cache).CurrentVer()) == var; });
+ { return var.Pkg(cache) ? var.Pkg(cache)->CurrentVer != nullptr : Var(var.CastPkg(cache).CurrentVer()) == var; });
if (important && wasImportant && not newOptional && not satisfied)
{