summaryrefslogtreecommitdiff
path: root/apt-pkg/solver3.cc
diff options
context:
space:
mode:
Diffstat (limited to 'apt-pkg/solver3.cc')
-rw-r--r--apt-pkg/solver3.cc64
1 files changed, 41 insertions, 23 deletions
diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc
index 5065b9a87..a21af12f9 100644
--- a/apt-pkg/solver3.cc
+++ b/apt-pkg/solver3.cc
@@ -304,6 +304,35 @@ bool APT::Solver::Obsolete(pkgCache::PkgIterator pkg) const
pkgObsolete[pkg->ID] = 2;
return true;
}
+bool APT::Solver::Assume(Var var, bool decision, Var reason)
+{
+ choices.push_back(solved.size());
+ return Enqueue(var, decision, std::move(reason));
+}
+
+bool APT::Solver::Enqueue(Var var, bool decision, Var reason)
+{
+ auto &state = (*this)[var];
+ auto decisionCast = decision ? Decision::MUST : Decision::MUSTNOT;
+
+ if (state.decision != Decision::NONE)
+ {
+ if (state.decision != decisionCast)
+ return _error->Error("Conflict: %s -> %s%s but %s", WhyStr(reason).c_str(), decision ? "" : "not ", var.toString(cache).c_str(), WhyStr(var).c_str());
+ return true;
+ }
+
+ state.decision = decisionCast;
+ state.depth = depth();
+ state.reason = reason;
+
+ if (unlikely(debug >= 1))
+ std::cerr << "[" << depth() << "] " << (decision ? "Install" : "Reject") << ":" << var.toString(cache) << " (" << WhyStr(state.reason) << ")\n";
+
+ solved.push_back(Solved{var, std::nullopt});
+
+ return true;
+}
bool APT::Solver::Install(pkgCache::PkgIterator Pkg, Var reason, Group group)
{
@@ -329,10 +358,8 @@ bool APT::Solver::Install(pkgCache::PkgIterator Pkg, Var reason, Group group)
}
// Note decision
- if (unlikely(debug >= 1))
- std::cerr << "[" << depth() << "] Install:" << Pkg.FullName() << " (" << WhyStr(reason) << ")\n";
- (*this)[Pkg] = {reason, depth(), Decision::MUST};
- solved.push_back(Solved{Var(Pkg), std::nullopt});
+ if (not Enqueue(Var(Pkg), true, reason))
+ return false;
// Insert the work item.
Work workItem{Var(Pkg), depth(), group};
@@ -380,15 +407,10 @@ bool APT::Solver::Install(pkgCache::VerIterator Ver, Var reason, Group group)
WhyStr(Var(otherVer)).c_str());
// Note decision
- if (unlikely(debug >= 1))
- std::cerr << "[" << depth() << "] Install:" << Ver.ParentPkg().FullName() << "=" << Ver.VerStr() << " (" << WhyStr(reason) << ")\n";
- (*this)[Ver] = {reason, depth(), Decision::MUST};
- solved.push_back(Solved{Var(Ver), std::nullopt});
- if ((*this)[Ver.ParentPkg()].decision != Decision::MUST)
- {
- (*this)[Ver.ParentPkg()] = {Var(Ver), depth(), Decision::MUST};
- solved.push_back(Solved{Var(Ver.ParentPkg()), std::nullopt});
- }
+ if (not Enqueue(Var(Ver), true, reason))
+ return false;
+ if (not Enqueue(Var(Ver.ParentPkg()), true, Var(Ver)))
+ return false;
for (auto OV = Ver.ParentPkg().VersionList(); not OV.end(); ++OV)
{
@@ -423,10 +445,8 @@ bool APT::Solver::Reject(pkgCache::PkgIterator Pkg, Var reason, Group group)
return _error->Error("Conflict: %s -> not %s but %s", WhyStr(reason).c_str(), Pkg.FullName().c_str(), WhyStr(Var(Pkg)).c_str());
// Reject the package and its versions.
- if (unlikely(debug >= 1))
- std::cerr << "[" << depth() << "] Reject:" << Pkg.FullName() << " (" << WhyStr(reason) << ")\n";
- (*this)[Pkg] = {reason, depth(), Decision::MUSTNOT};
- solved.push_back(Solved{Var(Pkg), std::nullopt});
+ if (not Enqueue(Var(Pkg), false, reason))
+ return false;
for (auto ver = Pkg.VersionList(); not ver.end(); ver++)
if (not Reject(ver, Var(Pkg), group))
return false;
@@ -452,10 +472,8 @@ bool APT::Solver::Reject(pkgCache::VerIterator Ver, Var reason, Group group)
WhyStr(Var(Ver)).c_str());
// Mark the package as rejected and propagate up as needed.
- if (unlikely(debug >= 1))
- std::cerr << "[" << depth() << "] Reject:" << Ver.ParentPkg().FullName() << "=" << Ver.VerStr() << " (" << WhyStr(reason) << ")\n";
- (*this)[Ver] = {reason, depth(), Decision::MUSTNOT};
- solved.push_back(Solved{Var(Ver), std::nullopt});
+ if (not Enqueue(Var(Ver), false, reason))
+ return false;
if (auto pkg = Ver.ParentPkg(); (*this)[pkg].decision != Decision::MUSTNOT)
{
bool anyInstallable = false;
@@ -478,8 +496,8 @@ bool APT::Solver::Reject(pkgCache::VerIterator Ver, Var reason, Group group)
}
else if ((*this)[Ver.ParentPkg()].decision != Decision::MUSTNOT) // Last installable invalidated
{
- (*this)[Ver.ParentPkg()] = {Var(Ver), depth(), Decision::MUSTNOT};
- solved.push_back(Solved{Var(Ver), std::nullopt});
+ if (not Enqueue(Var(Ver.ParentPkg()), false, Var(Ver)))
+ return false;
}
}