From 09ff3cb9536c9ed1ef6d21f5c1d7f7983b46e017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= Date: Thu, 10 Nov 2022 12:08:00 +0100 Subject: [PATCH] Repoquery: Add --what* and --exactdeps options https://github.com/rpm-software-management/dnf5/issues/122 --- dnf5/commands/repoquery/repoquery.cpp | 212 ++++++++++++++++++++++++++ dnf5/commands/repoquery/repoquery.hpp | 12 ++ 2 files changed, 224 insertions(+) diff --git a/dnf5/commands/repoquery/repoquery.cpp b/dnf5/commands/repoquery/repoquery.cpp index f6f235adb..7ad0407fa 100644 --- a/dnf5/commands/repoquery/repoquery.cpp +++ b/dnf5/commands/repoquery/repoquery.cpp @@ -101,6 +101,84 @@ void RepoqueryCommand::set_argument_parser() { info->add_conflict_argument(*nevra); + whatdepends = std::make_unique( + *this, + "whatdepends", + '\0', + "Limit the resulting set only to packages that require, enhance, recommend, suggest or supplement any of " + ".", + "CAPABILITY,...", + ","); + whatconflicts = std::make_unique( + *this, + "whatconflicts", + '\0', + "Limit the resulting set only to packages that conflict with any of .", + "CAPABILITY,...", + ","); + whatprovides = std::make_unique( + *this, + "whatprovides", + '\0', + "Limit the resulting set only to packages that provide any of .", + "CAPABILITY,...", + ","); + whatrequires = std::make_unique( + *this, + "whatrequires", + '\0', + "Limit the resulting set only to packages that require any of . Use --whatdepends if you want to " + "list all depending packages.", + "CAPABILITY,...", + ","); + whatobsoletes = std::make_unique( + *this, + "whatobsoletes", + '\0', + "Limit the resulting set only to packages that obsolete any of .", + "CAPABILITY,...", + ","); + whatrecommends = std::make_unique( + *this, + "whatrecommends", + '\0', + "Limit the resulting set only to packages that recommend any of . Use --whatdepends if you want " + "to list all depending packages.", + "CAPABILITY,...", + ","); + whatenhances = std::make_unique( + *this, + "whatenhances", + '\0', + "Limit the resulting set only to packages that enhance any of . Use --whatdepends if you want to " + "list all depending packages.", + "CAPABILITY,...", + ","); + whatsupplements = std::make_unique( + *this, + "whatsupplements", + '\0', + "Limit the resulting set only to packages that supplement any of . Use --whatdepends if you " + "want to list all depending packages.", + "CAPABILITY,...", + ","); + whatsuggests = std::make_unique( + *this, + "whatsuggests", + '\0', + "Limit the resulting set only to packages that suggest any of . Use --whatdepends if you want to " + "list all depending packages.", + "CAPABILITY,...", + ","); + + exactdeps = std::make_unique( + *this, + "exactdeps", + '\0', + "This option is stackable with --whatrequires or --whatdepends only. Limit the resulting set only to packages " + "that require specified by –whatrequires.", + false); + advisory_name = std::make_unique(*this); advisory_security = std::make_unique(*this); advisory_bugfix = std::make_unique(*this); @@ -141,6 +219,22 @@ void RepoqueryCommand::load_additional_packages() { } } +// In case of input being nevras -> resolve them to packages +static libdnf::rpm::PackageQuery resolve_nevras_to_packges( + libdnf::Base & base, std::vector nevra_globs, libdnf::rpm::PackageQuery base_query) { + auto resolved_nevras_query = libdnf::rpm::PackageQuery(base, libdnf::sack::ExcludeFlags::APPLY_EXCLUDES, true); + auto settings = libdnf::ResolveSpecSettings(); + settings.with_provides = false; + settings.with_filenames = false; + for (auto nevra : nevra_globs) { + auto tmp_query = base_query; + tmp_query.resolve_pkg_spec(nevra, settings, true); + resolved_nevras_query |= tmp_query; + } + + return resolved_nevras_query; +} + void RepoqueryCommand::run() { auto & ctx = get_context(); @@ -161,6 +255,124 @@ void RepoqueryCommand::run() { full_package_query.filter_advisories(advisories.value(), libdnf::sack::QueryCmp::GTE); } + if (!whatdepends->get_value().empty()) { + auto matched_reldeps = libdnf::rpm::ReldepList(ctx.base); + for (const auto & reldep_glob : whatdepends->get_value()) { + matched_reldeps.add_reldep_with_glob(reldep_glob); + } + + // Filter requires by reldeps + auto dependsquery = full_package_query; + dependsquery.filter_requires(matched_reldeps, libdnf::sack::QueryCmp::EQ); + + // Filter weak deps via reldeps + auto recommends_reldep_query = full_package_query; + recommends_reldep_query.filter_recommends(matched_reldeps, libdnf::sack::QueryCmp::EQ); + dependsquery |= recommends_reldep_query; + auto enhances_reldep_query = full_package_query; + enhances_reldep_query.filter_enhances(matched_reldeps, libdnf::sack::QueryCmp::EQ); + dependsquery |= enhances_reldep_query; + auto supplements_reldep_query = full_package_query; + supplements_reldep_query.filter_supplements(matched_reldeps, libdnf::sack::QueryCmp::EQ); + dependsquery |= supplements_reldep_query; + auto suggests_reldep_query = full_package_query; + suggests_reldep_query.filter_suggests(matched_reldeps, libdnf::sack::QueryCmp::EQ); + dependsquery |= suggests_reldep_query; + + if (!exactdeps->get_value()) { + auto pkgs_from_resolved_nevras = + resolve_nevras_to_packges(ctx.base, whatdepends->get_value(), full_package_query); + + // Filter requires by packages from resolved nevras + auto what_requires_resolved_nevras = full_package_query; + what_requires_resolved_nevras.filter_requires(pkgs_from_resolved_nevras); + dependsquery |= what_requires_resolved_nevras; + + // Filter weak deps by packages from resolved nevras + auto recommends_pkg_query = full_package_query; + recommends_pkg_query.filter_recommends(pkgs_from_resolved_nevras, libdnf::sack::QueryCmp::EQ); + dependsquery |= recommends_pkg_query; + auto enhances_pkg_query = full_package_query; + enhances_pkg_query.filter_enhances(pkgs_from_resolved_nevras, libdnf::sack::QueryCmp::EQ); + dependsquery |= enhances_pkg_query; + auto supplements_pkg_query = full_package_query; + supplements_pkg_query.filter_supplements(pkgs_from_resolved_nevras, libdnf::sack::QueryCmp::EQ); + dependsquery |= supplements_pkg_query; + auto suggests_pkg_query = full_package_query; + suggests_pkg_query.filter_suggests(pkgs_from_resolved_nevras, libdnf::sack::QueryCmp::EQ); + dependsquery |= suggests_pkg_query; + } + //TODO(amatej): add recurisve option call + + full_package_query = dependsquery; + } + if (!whatprovides->get_value().empty()) { + auto provides_query = full_package_query; + provides_query.filter_provides(whatprovides->get_value(), libdnf::sack::QueryCmp::GLOB); + if (!provides_query.empty()) { + full_package_query = provides_query; + } else { + // If provides query doesn't match anything try matching files + full_package_query.filter_file(whatprovides->get_value(), libdnf::sack::QueryCmp::GLOB); + } + } + if (!whatrequires->get_value().empty()) { + if (exactdeps->get_value()) { + full_package_query.filter_requires(whatrequires->get_value(), libdnf::sack::QueryCmp::GLOB); + } else { + auto requires_resolved = full_package_query; + requires_resolved.filter_requires( + resolve_nevras_to_packges(ctx.base, whatrequires->get_value(), full_package_query)); + + full_package_query.filter_requires(whatrequires->get_value(), libdnf::sack::QueryCmp::GLOB); + full_package_query |= requires_resolved; + //TODO(amatej): add recurisve option call + } + } + if (!whatobsoletes->get_value().empty()) { + full_package_query.filter_obsoletes(whatobsoletes->get_value(), libdnf::sack::QueryCmp::GLOB); + } + if (!whatconflicts->get_value().empty()) { + auto conflicts_resolved = full_package_query; + conflicts_resolved.filter_conflicts( + resolve_nevras_to_packges(ctx.base, whatconflicts->get_value(), full_package_query)); + + full_package_query.filter_conflicts(whatconflicts->get_value(), libdnf::sack::QueryCmp::GLOB); + full_package_query |= conflicts_resolved; + } + if (!whatrecommends->get_value().empty()) { + auto recommends_resolved = full_package_query; + recommends_resolved.filter_recommends( + resolve_nevras_to_packges(ctx.base, whatrecommends->get_value(), full_package_query)); + + full_package_query.filter_recommends(whatrecommends->get_value(), libdnf::sack::QueryCmp::GLOB); + full_package_query |= recommends_resolved; + } + if (!whatenhances->get_value().empty()) { + auto enhances_resolved = full_package_query; + enhances_resolved.filter_enhances( + resolve_nevras_to_packges(ctx.base, whatenhances->get_value(), full_package_query)); + + full_package_query.filter_enhances(whatenhances->get_value(), libdnf::sack::QueryCmp::GLOB); + full_package_query |= enhances_resolved; + } + if (!whatsupplements->get_value().empty()) { + auto supplements_resolved = full_package_query; + supplements_resolved.filter_supplements( + resolve_nevras_to_packges(ctx.base, whatsupplements->get_value(), full_package_query)); + + full_package_query.filter_supplements(whatsupplements->get_value(), libdnf::sack::QueryCmp::GLOB); + full_package_query |= supplements_resolved; + } + if (!whatsuggests->get_value().empty()) { + auto suggests_resolved = full_package_query; + suggests_resolved.filter_suggests( + resolve_nevras_to_packges(ctx.base, whatsuggests->get_value(), full_package_query)); + + full_package_query.filter_suggests(whatsuggests->get_value(), libdnf::sack::QueryCmp::GLOB); + full_package_query |= suggests_resolved; + } + if (pkg_specs.empty() && pkg_file_paths.empty()) { result_pset |= full_package_query; } else { diff --git a/dnf5/commands/repoquery/repoquery.hpp b/dnf5/commands/repoquery/repoquery.hpp index 3bc356bfa..d138c4731 100644 --- a/dnf5/commands/repoquery/repoquery.hpp +++ b/dnf5/commands/repoquery/repoquery.hpp @@ -51,6 +51,18 @@ class RepoqueryCommand : public Command { std::vector pkg_file_paths; std::vector cmdline_packages; + std::unique_ptr whatdepends{nullptr}; + std::unique_ptr whatconflicts{nullptr}; + std::unique_ptr whatenhances{nullptr}; + std::unique_ptr whatobsoletes{nullptr}; + std::unique_ptr whatprovides{nullptr}; + std::unique_ptr whatrecommends{nullptr}; + std::unique_ptr whatrequires{nullptr}; + std::unique_ptr whatsuggests{nullptr}; + std::unique_ptr whatsupplements{nullptr}; + + std::unique_ptr exactdeps{nullptr}; + std::unique_ptr advisory_name{nullptr}; std::unique_ptr advisory_security{nullptr}; std::unique_ptr advisory_bugfix{nullptr};