From e8b240eb3aab7e2584e245f03700ede30a3fc23a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 17 Feb 2025 21:33:30 +0100 Subject: refactor: Deduplicate and Move SectionInSubTree to Configuration Deduplicate the copies in a central one, mark it unavailable to external users. --- apt-pkg/contrib/configuration.cc | 33 +++++++++++++++++++++++++++++++ apt-pkg/contrib/configuration.h | 3 +++ apt-pkg/depcache.cc | 42 ++++------------------------------------ 3 files changed, 40 insertions(+), 38 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 28cf3e480..cf72aa3d7 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -1226,3 +1226,36 @@ bool Configuration::MatchAgainstConfig::Match(char const * str) const return false; } /*}}}*/ +// helper for Install-Recommends-Sections and Never-MarkAuto-Sections /*{{{*/ +static bool ConfigValueInSubTree(Configuration *config, const char *SubTree, std::string_view const needle) +{ + if (needle.empty()) + return false; + Configuration::Item const *Opts = config->Tree(SubTree); + if (Opts != nullptr && Opts->Child != nullptr) + { + Opts = Opts->Child; + for (; Opts != nullptr; Opts = Opts->Next) + { + if (Opts->Value.empty()) + continue; + if (needle == Opts->Value) + return true; + } + } + return false; +} +bool Configuration::SectionInSubTree(char const *const SubTree, std::string_view Needle) +{ + if (ConfigValueInSubTree(this, SubTree, Needle)) + return true; + auto const sub = Needle.rfind('/'); + if (sub == std::string_view::npos) + { + std::string special{"/"}; + special.append(Needle); + return ConfigValueInSubTree(this, SubTree, special); + } + return ConfigValueInSubTree(this, SubTree, Needle.substr(sub + 1)); +} + /*}}}*/ diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 4a21d977b..30a1cbf43 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -117,6 +117,9 @@ class APT_PUBLIC Configuration void Dump(std::ostream& str, char const * const root, char const * const format, bool const emptyValue); +#ifdef APT_COMPILING_APT + bool SectionInSubTree(char const *const SubTree, std::string_view Needle); +#endif explicit Configuration(const Item *Root); Configuration(); ~Configuration(); diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index b66f2bc66..970b4c01d 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -67,40 +67,6 @@ class DefaultRootSetFunc2 : public pkgDepCache::DefaultRootSetFunc bool InRootSet(const pkgCache::PkgIterator &pkg) override { return pkg.end() == false && ((*Kernels)(pkg) || DefaultRootSetFunc::InRootSet(pkg)); }; }; - /*}}}*/ -// helper for Install-Recommends-Sections and Never-MarkAuto-Sections /*{{{*/ -// FIXME: Has verbatim copy in cmdline/apt-mark.cc -static bool ConfigValueInSubTree(const char* SubTree, std::string_view const needle) -{ - if (needle.empty()) - return false; - Configuration::Item const *Opts = _config->Tree(SubTree); - if (Opts != nullptr && Opts->Child != nullptr) - { - Opts = Opts->Child; - for (; Opts != nullptr; Opts = Opts->Next) - { - if (Opts->Value.empty()) - continue; - if (needle == Opts->Value) - return true; - } - } - return false; -} -static bool SectionInSubTree(char const * const SubTree, std::string_view Needle) -{ - if (ConfigValueInSubTree(SubTree, Needle)) - return true; - auto const sub = Needle.rfind('/'); - if (sub == std::string_view::npos) - { - std::string special{"/"}; - special.append(Needle); - return ConfigValueInSubTree(SubTree, special); - } - return ConfigValueInSubTree(SubTree, Needle.substr(sub + 1)); -} /*}}}*/ pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) : /*{{{*/ d(NULL), cache(cache), released(false) @@ -1068,7 +1034,7 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, // We do not check for or-groups here as we don't know which package takes care of // providing the feature the user likes e.g.: browser1 | browser2 | browser3 // Temporary removals are effected by this as well, which is bad, but unlikely in practice - bool const PinNeverMarkAutoSection = (PV->Section != 0 && SectionInSubTree("APT::Never-MarkAuto-Sections", PV.Section())); + bool const PinNeverMarkAutoSection = (PV->Section != 0 && _config->SectionInSubTree("APT::Never-MarkAuto-Sections", PV.Section())); if (PinNeverMarkAutoSection) { for (DepIterator D = PV.DependsList(); D.end() != true; ++D) @@ -1782,8 +1748,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg, bool AutoInst, VerIterator const CurVer = Pkg.CurrentVer(); if (not CurVer.end() && CurVer->Section != 0 && strcmp(CurVer.Section(), PV.Section()) != 0) { - bool const CurVerInMoveSection = SectionInSubTree("APT::Move-Autobit-Sections", CurVer.Section()); - bool const InstVerInMoveSection = SectionInSubTree("APT::Move-Autobit-Sections", PV.Section()); + bool const CurVerInMoveSection = _config->SectionInSubTree("APT::Move-Autobit-Sections", CurVer.Section()); + bool const InstVerInMoveSection = _config->SectionInSubTree("APT::Move-Autobit-Sections", PV.Section()); return (not CurVerInMoveSection && InstVerInMoveSection); } return false; @@ -2275,7 +2241,7 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) const // FIXME: this is a meant as a temporary solution until the // recommends are cleaned up const char *sec = Dep.ParentVer().Section(); - if (sec && SectionInSubTree("APT::Install-Recommends-Sections", sec)) + if (sec && _config->SectionInSubTree("APT::Install-Recommends-Sections", sec)) return true; } else if(Dep->Type == pkgCache::Dep::Suggests) -- cgit v1.2.3-70-g09d2 From 4175a005f98dba139208035d820bcc14de711a5a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 17 Feb 2025 21:42:29 +0100 Subject: solver3: Fix test-apt-move-and-forget-manual-sections Implement the moving of the auto bit. The whole auto-bit management is not entirely optimal yet, but this works. --- apt-pkg/solver3.cc | 26 ++++++++++++++++++++++++-- test/integration/solver3.broken | 1 - 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc index c4fb567e1..233d7c712 100644 --- a/apt-pkg/solver3.cc +++ b/apt-pkg/solver3.cc @@ -975,6 +975,7 @@ bool APT::Solver::FromDepCache(pkgDepCache &depcache) bool APT::Solver::ToDepCache(pkgDepCache &depcache) const { + FastContiguousCacheMap movedManual(cache); pkgDepCache::ActionGroup group(depcache); for (auto P = cache.PkgBegin(); not P.end(); P++) { @@ -994,10 +995,31 @@ bool APT::Solver::ToDepCache(pkgDepCache &depcache) const if (cand != P.CurrentVer()) { + bool automatic = (not reason.empty() || (depcache[P].Flags & pkgCache::Flag::Auto)) && not movedManual[P]; depcache.SetCandidateVersion(cand); - depcache.MarkInstall(P, false, 0, reason.empty() && not(depcache[P].Flags & pkgCache::Flag::Auto)); + depcache.MarkInstall(P, false, 0, not automatic); + + // Set the automatic bit for new packages or move it on upgrades to oldlibs if (not P->CurrentVer) - depcache.MarkAuto(P, not reason.empty()); + depcache.MarkAuto(P, automatic); + else if (not(depcache[P].Flags & pkgCache::Flag::Auto) && P.CurrentVer()->Section && cand->Section && not _config->SectionInSubTree("APT::Move-Autobit-Sections", P.CurrentVer().Section()) && _config->SectionInSubTree("APT::Move-Autobit-Sections", cand.Section())) + { + bool moved = false; + for (auto const &clause : (*this)[cand].clauses) + for (auto sol : clause->solutions) + { + // New installs move the auto-bit. TODO: Should we look at whether clause is the reason for installing it? + if (sol.CastPkg(cache) == P || sol.CastPkg(cache)->CurrentVer) + continue; + std::cerr << "Move manual bit from " << P.FullName() << " to " << sol.CastPkg(cache).Name() << std::endl; + movedManual[sol.CastPkg(cache)] = true; + depcache.MarkAuto(sol.CastPkg(cache), false); + moved = true; + } + if (moved) + depcache.MarkAuto(P, true); + } + } else depcache.MarkKeep(P, false, reason.empty() && not(depcache[P].Flags & pkgCache::Flag::Auto)); diff --git a/test/integration/solver3.broken b/test/integration/solver3.broken index 2ad00555b..4a4e1532b 100644 --- a/test/integration/solver3.broken +++ b/test/integration/solver3.broken @@ -1,7 +1,6 @@ test-allow-scores-for-all-dependency-types # TBD: We are lacking single-sided conflicts preferences test-apt-get-upgrade-by-source # TBD: Upgrading by source is not supported yet, mostly same issue as above test-apt-install-order-matters-a-bit # Wontfix: Cannot fix, the order is not recorded in the depcache -test-apt-move-and-forget-manual-sections # TBD: Moving the auto bit is not implemented test-bug-470115-new-and-tighten-recommends # TBD: Calculation of what is already satisfied Recommends is broken test-prevent-markinstall-multiarch-same-versionscrew # TBD: We consider the skewed ones obsolete and remove them... test-resolve-by-keep-new-recommends # TBD: Fixing this seems to break test-bug-591882-conkeror, why? -- cgit v1.2.3-70-g09d2 From f331e31505ab78620de2670b19bdefaee395b4e8 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 18 Feb 2025 14:31:48 +0100 Subject: solver3: Fix error stack handling Pushing the stack in push and popping it in pop did not really work correctly and is more complex than needed. Instead, push the error stack at the start of the Solve() method and revert at the end, such that we leave exactly at the same error stack level we entered. To handle error clearing on backtracking, just discard any pending errors. --- apt-pkg/solver3.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/solver3.cc b/apt-pkg/solver3.cc index 233d7c712..7117296ab 100644 --- a/apt-pkg/solver3.cc +++ b/apt-pkg/solver3.cc @@ -673,8 +673,6 @@ void APT::Solver::Push(Work work) choices.push_back(solved.size()); solved.push_back(Solved{Var(), std::move(work)}); - // Pop() will call MergeWithStack() when reverting to level 0, or RevertToStack after dumping to the debug log. - _error->PushToStack(); } void APT::Solver::UndoOne() @@ -713,15 +711,15 @@ bool APT::Solver::Pop() if (depth() == 0) return false; - if (unlikely(debug >= 2)) - for (std::string msg; _error->PopMessage(msg);) - std::cerr << "Branch failed: " << msg << std::endl; - time_t now = time(nullptr); if (now - startTime >= Timeout) return _error->Error("Solver timed out."); - _error->RevertToStack(); + if (unlikely(debug >= 2)) + for (std::string msg; _error->PopMessage(msg);) + std::cerr << "Branch failed: " << msg << std::endl; + + _error->Discard(); assert(choices.back() < solved.size()); int itemsToUndo = solved.size() - choices.back(); @@ -781,6 +779,8 @@ bool APT::Solver::AddWork(Work &&w) bool APT::Solver::Solve() { + _error->PushToStack(); + DEFER([&]() { _error->MergeWithStack(); }); startTime = time(nullptr); while (true) { -- cgit v1.2.3-70-g09d2