summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2024-11-02 12:45:07 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2024-12-03 09:44:18 +0100
commit8f317d97c9fb821e839342ae445c824207678eb7 (patch)
tree17404bfe4fd59c7ee6c18b19e0ade8f42221ff68
parent3e5977ed7b4e6291fcd67df193a501754ec1de7f (diff)
solver3: Reject all non-candidates outright for strict pinning
Reimplement strict pinning by rejecting the non-candidates when translating the problem from the depcache to the solver. This is substantially better than restricting the list of alternatives for an or group to only include allowed ones for debugging purposes, albeit a bit slower.
-rw-r--r--apt-pkg/solver3.cc43
-rw-r--r--apt-pkg/solver3.h2
-rwxr-xr-xtest/integration/test-handling-broken-orgroups2
-rwxr-xr-xtest/integration/test-solver3-obsoleted-by7
4 files changed, 24 insertions, 30 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index 83f3359df..00663ddca 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -329,9 +329,6 @@ bool APT::Solver::Enqueue(Var var, bool decision, Var reason)
return true;
}
- if (auto Ver = var.Ver(cache); !Ver.end() && decision && unlikely(debug >= 1))
- assert(IsAllowedVersion(Ver));
-
state.decision = decisionCast;
state.depth = depth();
state.reason = reason;
@@ -369,12 +366,9 @@ bool APT::Solver::Install(pkgCache::PkgIterator Pkg, Var reason, Group group)
Work workItem{Var(Pkg), depth(), group};
for (auto ver = Pkg.VersionList(); not ver.end(); ver++)
{
- if (IsAllowedVersion(ver))
- {
- workItem.solutions.push_back(ver);
- if ((*this)[ver].decision != Decision::MUSTNOT)
- anyInstallable = true;
- }
+ workItem.solutions.push_back(ver);
+ if ((*this)[ver].decision != Decision::MUSTNOT)
+ anyInstallable = true;
}
if (not anyInstallable)
@@ -535,8 +529,7 @@ bool APT::Solver::EnqueueOrGroup(pkgCache::DepIterator start, pkgCache::DepItera
{
if (unlikely(debug >= 3))
std::cerr << "Adding work to item " << Ver.ParentPkg().FullName() << "=" << Ver.VerStr() << " -> " << tgti.ParentPkg().FullName() << "=" << tgti.VerStr() << "\n";
- if (IsAllowedVersion(*tgt))
- workItem.solutions.push_back(*tgt);
+ workItem.solutions.push_back(*tgt);
}
}
delete[] all;
@@ -572,7 +565,7 @@ bool APT::Solver::EnqueueOrGroup(pkgCache::DepIterator start, pkgCache::DepItera
newOptional = false, wasImportant = policy.IsImportantDep(D);
bool satisfied = std::any_of(workItem.solutions.begin(), workItem.solutions.end(), [this](auto ver)
- { return pkgCache::VerIterator(cache, ver).ParentPkg()->CurrentVer != 0; });
+ { return pkgCache::VerIterator(cache, ver).ParentPkg().CurrentVer() == ver; });
if (important && wasImportant && not newOptional && not satisfied)
{
@@ -696,17 +689,6 @@ bool APT::Solver::RejectReverseDependencies(pkgCache::VerIterator Ver)
return true;
}
-bool APT::Solver::IsAllowedVersion(pkgCache::Version *V)
-{
- pkgCache::VerIterator ver(cache, V);
- if (not StrictPinning || ver.ParentPkg().CurrentVer() == ver || policy.GetCandidateVer(ver.ParentPkg()) == ver || (*this)[V].decision == Decision::MUST)
- return true;
-
- if (unlikely(debug >= 3))
- std::cerr << "Ignoring: " << ver.ParentPkg().FullName() << "=" << ver.VerStr() << "(neither candidate nor installed)\n";
- return false;
-}
-
void APT::Solver::Push(Work work)
{
if (unlikely(debug >= 2))
@@ -943,6 +925,18 @@ bool APT::Solver::FromDepCache(pkgDepCache &depcache)
bool AllowRemoveManual = AllowRemove && _config->FindB("APT::Solver::RemoveManual", false);
DefaultRootSetFunc2 rootSet(&cache);
+ // Enforce strict pinning rules by rejecting all forbidden versions.
+ if (StrictPinning)
+ {
+ for (auto P = cache.PkgBegin(); not P.end(); P++)
+ {
+ for (auto V = P.VersionList(); not V.end(); ++V)
+ if (P.CurrentVer() != V && depcache.GetCandidateVersion(P) != V)
+ if (not Enqueue(Var(V), false, {}))
+ return false;
+ }
+ }
+
for (auto P = cache.PkgBegin(); not P.end(); P++)
{
if (P->VersionList == nullptr)
@@ -997,8 +991,7 @@ bool APT::Solver::FromDepCache(pkgDepCache &depcache)
{
Work w{Var(), depth(), Group, isOptional, Upgrade};
for (auto V = P.VersionList(); not V.end(); ++V)
- if (IsAllowedVersion(V))
- w.solutions.push_back(V);
+ w.solutions.push_back(V);
std::stable_sort(w.solutions.begin(), w.solutions.end(), CompareProviders3{cache, policy, P, *this});
AddWork(std::move(w));
}
diff --git a/apt-pkg/solver3.h b/apt-pkg/solver3.h
index 0e6d0e2f9..a643d5d07 100644
--- a/apt-pkg/solver3.h
+++ b/apt-pkg/solver3.h
@@ -157,8 +157,6 @@ class Solver
bool PropagateInstall(Var var);
// \brief Propagate a rejection of a variable
bool PropagateReject(Var var);
- // \brief Check if a version is allowed by policy.
- bool IsAllowedVersion(pkgCache::Version *V);
// \brief Return the current depth (choices.size() with casting)
depth_type depth()
diff --git a/test/integration/test-handling-broken-orgroups b/test/integration/test-handling-broken-orgroups
index 1c20ae4f1..50b158752 100755
--- a/test/integration/test-handling-broken-orgroups
+++ b/test/integration/test-handling-broken-orgroups
@@ -95,7 +95,7 @@ Inst coolstuff-provided (1.0-1 unstable [all])
Conf extrastuff (1.0-1 unstable [all])
Conf coolstuff-provided (1.0-1 unstable [all])' aptget install coolstuff-provided -s
-testfailuremsg 'E: Unsatisfiable dependency group coolstuff-provided-broken:i386=1.0-1 -> cool2:i386' aptget install coolstuff-provided-broken --solver 3.0 -s
+testfailuremsg 'E: Conflict: coolstuff-provided-broken:i386=1.0-1 -> extrastuff:i386=1.0-1 but not extrastuff:i386=1.0-1' aptget install coolstuff-provided-broken --solver 3.0 -s
testfailureequal 'Reading package lists...
Building dependency tree...
Some packages could not be installed. This may mean that you have
diff --git a/test/integration/test-solver3-obsoleted-by b/test/integration/test-solver3-obsoleted-by
index 031589bb4..486c55c58 100755
--- a/test/integration/test-solver3-obsoleted-by
+++ b/test/integration/test-solver3-obsoleted-by
@@ -66,9 +66,12 @@ testobsolete "Obsolete: not-yet-built:amd64 - not installable
Obsolete: good:amd64 - not installable
Obsolete: obsolete:amd64 - not installable
Obsolete: obsolete-in-experimental:amd64 - not installable
-Obsolete: current-version:amd64 - not installable
+Obsolete: obsolete-reason:amd64 - not installable
Obsolete: local-only:amd64 - not installable
-Obsolete: obsolete-in-downgrade:amd64 - not installable" aptget dist-upgrade
+Obsolete: obsolete-in-experimental-reason:amd64 - not installable
+Obsolete: current-version:amd64 - not installable
+Obsolete: obsolete-in-downgrade:amd64 - not installable
+Obsolete: obsolete-in-downgrade-reason:amd64 - not installable" aptget dist-upgrade
testobsolete "Obsolete: obsolete:amd64=1 due to obsolete-reason:amd64=2
Obsolete: obsolete-in-experimental:amd64=1 due to obsolete-in-experimental-reason:amd64=2