From 161e0508ca012671fec3b63107da2ae57d389c5e Mon Sep 17 00:00:00 2001 From: Marek Blaha Date: Wed, 22 May 2024 15:26:16 +0200 Subject: [PATCH] base: Enhance installed pkgs solver problems reporting Instead of cryptic "PkgA from @System" is used more user friendli expression "installed package PkgA". --- include/libdnf5/base/goal_elements.hpp | 2 ++ libdnf5/base/solver_problems.cpp | 8 ++++++++ libdnf5/base/transaction.cpp | 20 +++++++++++++++++++- libdnf5/rpm/solv/goal_private.cpp | 24 ++++++++++++++++++------ 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/include/libdnf5/base/goal_elements.hpp b/include/libdnf5/base/goal_elements.hpp index 790ce18f2..4c65d0471 100644 --- a/include/libdnf5/base/goal_elements.hpp +++ b/include/libdnf5/base/goal_elements.hpp @@ -86,6 +86,8 @@ enum class ProblemRules { RULE_MODULE_PKG_SELF_CONFLICT, RULE_MODULE_YUMOBS, RULE_MODULE_UNKNOWN, + RULE_PKG_INSTALLED_CONFLICTS, + RULE_PKG_INSTALLED_REQUIRES, }; /// Define a type of information, hint, or problem gathered during libdnf5::Goal::resolve() diff --git a/libdnf5/base/solver_problems.cpp b/libdnf5/base/solver_problems.cpp index 078f13df1..8b0ee9b7d 100644 --- a/libdnf5/base/solver_problems.cpp +++ b/libdnf5/base/solver_problems.cpp @@ -56,12 +56,16 @@ static const std::map PKG_PROBLEMS_DICT = { {ProblemRules::RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides {0} needed by {1} from {2}")}, {ProblemRules::RULE_PKG_SAME_NAME, M_("cannot install both {0} from {1} and {2} from {3}")}, {ProblemRules::RULE_PKG_CONFLICTS, M_("package {0} from {1} conflicts with {2} provided by {3} from {4}")}, + {ProblemRules::RULE_PKG_INSTALLED_CONFLICTS, + M_("installed package {0} conflicts with {1} provided by {2} from {3}")}, {ProblemRules::RULE_PKG_OBSOLETES, M_("package {0} from {1} obsoletes {2} provided by {3} from {4}")}, {ProblemRules::RULE_PKG_INSTALLED_OBSOLETES, M_("installed package {0} obsoletes {1} provided by {2} from {3}")}, {ProblemRules::RULE_PKG_IMPLICIT_OBSOLETES, M_("package {0} from {1} implicitly obsoletes {2} provided by {3} from {4}")}, {ProblemRules::RULE_PKG_REQUIRES, M_("package {1} from {2} requires {0}, but none of the providers can be installed")}, + {ProblemRules::RULE_PKG_INSTALLED_REQUIRES, + M_("installed package {1} requires {0}, but none of the providers can be installed")}, {ProblemRules::RULE_PKG_SELF_CONFLICT, M_("package {0} from {1} conflicts with {2} provided by itself")}, {ProblemRules::RULE_YUMOBS, M_("both package {0} from {1} and {3} from {4} obsolete {2}")}, {ProblemRules::RULE_PKG_REMOVAL_OF_PROTECTED, @@ -223,6 +227,7 @@ std::string SolverProblems::problem_to_string(const std::pair Transaction::get_gpg_signature_problems() const noexcep void Transaction::Impl::process_solver_problems(rpm::solv::GoalPrivate & solved_goal) { auto & pool = get_rpm_pool(base); + auto * installed_repo = pool->installed; libdnf5::rpm::PackageQuery skip_broken(base, libdnf5::sack::ExcludeFlags::APPLY_EXCLUDES, true); libdnf5::rpm::PackageQuery skip_conflict(base, libdnf5::sack::ExcludeFlags::APPLY_EXCLUDES, true); @@ -464,6 +465,7 @@ void Transaction::Impl::process_solver_problems(rpm::solv::GoalPrivate & solved_ for (auto & [rule, source, dep, target, description] : problem) { std::vector elements; ProblemRules tmp_rule = rule; + bool installed_conflicts = false; switch (rule) { case ProblemRules::RULE_INFARCH: case ProblemRules::RULE_PKG_NOT_INSTALLABLE_2: @@ -508,6 +510,10 @@ void Transaction::Impl::process_solver_problems(rpm::solv::GoalPrivate & solved_ elements.push_back(pool.dep2str(dep)); break; } + case ProblemRules::RULE_PKG_INSTALLED_REQUIRES: + elements.push_back(pool.dep2str(dep)); + elements.push_back(pool.solvid2str(source)); + break; case ProblemRules::RULE_PKG_NOTHING_PROVIDES_DEP: case ProblemRules::RULE_PKG_REQUIRES: { skip_broken.add(libdnf5::rpm::Package(base, libdnf5::rpm::PackageId(source))); @@ -528,6 +534,9 @@ void Transaction::Impl::process_solver_problems(rpm::solv::GoalPrivate & solved_ elements.push_back(tgt_solvable->repo->name); break; } + case ProblemRules::RULE_PKG_INSTALLED_CONFLICTS: + installed_conflicts = true; + [[fallthrough]]; case ProblemRules::RULE_PKG_CONFLICTS: if (current_conflicting_rules.contains(std::pair(target, source))) { // do not add pkgA conflicts with pkgB rule if pkgB conflicts with PkgA rule is already present @@ -536,13 +545,22 @@ void Transaction::Impl::process_solver_problems(rpm::solv::GoalPrivate & solved_ skip_conflict.add(libdnf5::rpm::Package(base, libdnf5::rpm::PackageId(source))); skip_conflict.add(libdnf5::rpm::Package(base, libdnf5::rpm::PackageId(target))); current_conflicting_rules.emplace(source, target); + if (installed_conflicts) { + // RULE_PKG_INSTALLED_CONFLICTS expects the first(source) + // element to be an installed package + if (pool.id2solvable(source)->repo != installed_repo) { + std::swap(source, target); + } + } [[fallthrough]]; case ProblemRules::RULE_PKG_OBSOLETES: case ProblemRules::RULE_PKG_IMPLICIT_OBSOLETES: case ProblemRules::RULE_YUMOBS: { auto * src_solvable = pool.id2solvable(source); elements.push_back(pool.solvable2str(src_solvable)); - elements.push_back(src_solvable->repo->name); + if (!installed_conflicts) { + elements.push_back(src_solvable->repo->name); + } elements.push_back(pool.dep2str(dep)); auto * tgt_solvable = pool.id2solvable(target); elements.push_back(pool.solvable2str(tgt_solvable)); diff --git a/libdnf5/rpm/solv/goal_private.cpp b/libdnf5/rpm/solv/goal_private.cpp index 99ece390e..3a8c16fa5 100644 --- a/libdnf5/rpm/solv/goal_private.cpp +++ b/libdnf5/rpm/solv/goal_private.cpp @@ -484,6 +484,7 @@ void GoalPrivate::write_debugdata(const std::filesystem::path & abs_dest_dir) { std::vector>> GoalPrivate::get_problems() { auto & pool = get_rpm_pool(); + auto * installed_repo = pool->installed; libdnf_assert_goal_resolved(); @@ -564,9 +565,15 @@ std::vector>> Goal case SOLVER_RULE_PKG_SAME_NAME: rule = ProblemRules::RULE_PKG_SAME_NAME; break; - case SOLVER_RULE_PKG_CONFLICTS: - rule = ProblemRules::RULE_PKG_CONFLICTS; - break; + case SOLVER_RULE_PKG_CONFLICTS: { + Solvable * src_solvable = pool.id2solvable(source); + Solvable * tgt_solvable = pool.id2solvable(target); + if (src_solvable->repo == installed_repo || tgt_solvable->repo == installed_repo) { + rule = ProblemRules::RULE_PKG_INSTALLED_CONFLICTS; + } else { + rule = ProblemRules::RULE_PKG_CONFLICTS; + } + } break; case SOLVER_RULE_PKG_OBSOLETES: rule = ProblemRules::RULE_PKG_OBSOLETES; break; @@ -576,9 +583,14 @@ std::vector>> Goal case SOLVER_RULE_PKG_IMPLICIT_OBSOLETES: rule = ProblemRules::RULE_PKG_IMPLICIT_OBSOLETES; break; - case SOLVER_RULE_PKG_REQUIRES: - rule = ProblemRules::RULE_PKG_REQUIRES; - break; + case SOLVER_RULE_PKG_REQUIRES: { + Solvable * solvable = pool.id2solvable(source); + if (solvable->repo == installed_repo) { + rule = ProblemRules::RULE_PKG_INSTALLED_REQUIRES; + } else { + rule = ProblemRules::RULE_PKG_REQUIRES; + } + } break; case SOLVER_RULE_PKG_SELF_CONFLICT: rule = ProblemRules::RULE_PKG_SELF_CONFLICT; break;