Skip to content

Commit

Permalink
base: Enhance installed pkgs solver problems reporting
Browse files Browse the repository at this point in the history
Instead of cryptic "PkgA from @System" is used more user friendli
expression "installed package PkgA".
  • Loading branch information
m-blaha authored and j-mracek committed May 27, 2024
1 parent 8f3dbab commit 161e050
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 7 deletions.
2 changes: 2 additions & 0 deletions include/libdnf5/base/goal_elements.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
8 changes: 8 additions & 0 deletions libdnf5/base/solver_problems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ static const std::map<ProblemRules, BgettextMessage> 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,
Expand Down Expand Up @@ -223,6 +227,7 @@ std::string SolverProblems::problem_to_string(const std::pair<ProblemRules, std:
case ProblemRules::RULE_MODULE_PKG_REQUIRES:
case ProblemRules::RULE_MODULE_PKG_SELF_CONFLICT:
case ProblemRules::RULE_MODULE_PKG_SAME_NAME:
case ProblemRules::RULE_PKG_INSTALLED_REQUIRES:
if (raw.second.size() != 2) {
throw std::invalid_argument("Incorrect number of elements for a problem rule");
}
Expand All @@ -240,6 +245,7 @@ std::string SolverProblems::problem_to_string(const std::pair<ProblemRules, std:
}
return utils::sformat(TM_(PKG_PROBLEMS_DICT.at(raw.first), 1), raw.second[0], raw.second[1], raw.second[2]);
case ProblemRules::RULE_PKG_SAME_NAME:
case ProblemRules::RULE_PKG_INSTALLED_CONFLICTS:
case ProblemRules::RULE_PKG_INSTALLED_OBSOLETES:
if (raw.second.size() != 4) {
throw std::invalid_argument("Incorrect number of elements for a problem rule");
Expand Down Expand Up @@ -401,10 +407,12 @@ std::vector<std::vector<std::pair<libdnf5::ProblemRules, std::vector<std::string
case ProblemRules::RULE_PKG_NOTHING_PROVIDES_DEP:
case ProblemRules::RULE_PKG_SAME_NAME:
case ProblemRules::RULE_PKG_CONFLICTS:
case ProblemRules::RULE_PKG_INSTALLED_CONFLICTS:
case ProblemRules::RULE_PKG_OBSOLETES:
case ProblemRules::RULE_PKG_INSTALLED_OBSOLETES:
case ProblemRules::RULE_PKG_IMPLICIT_OBSOLETES:
case ProblemRules::RULE_PKG_REQUIRES:
case ProblemRules::RULE_PKG_INSTALLED_REQUIRES:
case ProblemRules::RULE_PKG_SELF_CONFLICT:
case ProblemRules::RULE_YUMOBS:
case ProblemRules::RULE_UNKNOWN:
Expand Down
20 changes: 19 additions & 1 deletion libdnf5/base/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ std::vector<std::string> 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);
Expand All @@ -464,6 +465,7 @@ void Transaction::Impl::process_solver_problems(rpm::solv::GoalPrivate & solved_
for (auto & [rule, source, dep, target, description] : problem) {
std::vector<std::string> elements;
ProblemRules tmp_rule = rule;
bool installed_conflicts = false;
switch (rule) {
case ProblemRules::RULE_INFARCH:
case ProblemRules::RULE_PKG_NOT_INSTALLABLE_2:
Expand Down Expand Up @@ -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)));
Expand All @@ -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<int, int>(target, source))) {
// do not add pkgA conflicts with pkgB rule if pkgB conflicts with PkgA rule is already present
Expand All @@ -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));
Expand Down
24 changes: 18 additions & 6 deletions libdnf5/rpm/solv/goal_private.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ void GoalPrivate::write_debugdata(const std::filesystem::path & abs_dest_dir) {

std::vector<std::vector<std::tuple<ProblemRules, Id, Id, Id, std::string>>> GoalPrivate::get_problems() {
auto & pool = get_rpm_pool();
auto * installed_repo = pool->installed;

libdnf_assert_goal_resolved();

Expand Down Expand Up @@ -564,9 +565,15 @@ std::vector<std::vector<std::tuple<ProblemRules, Id, Id, Id, std::string>>> 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;
Expand All @@ -576,9 +583,14 @@ std::vector<std::vector<std::tuple<ProblemRules, Id, Id, Id, std::string>>> 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;
Expand Down

0 comments on commit 161e050

Please sign in to comment.