From 9bae31aa74bc476706e5b8ede2064a34f4494047 Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Fri, 3 Jan 2025 09:13:11 +0100 Subject: [PATCH 1/2] Bash completion: always offer NEVRAs for packages Originally, for packages, the NAME was offered in bash completion. In the case of multiple packages with the same NAME, there was an option to offer NEVRA instead of the NAME for those packages. Now, bash completion always offers NEVRA for packages. There is an option to offer package NAMEs in addition to NEVRAs. This is useful, for example, when the user wants to install a package. Usually the user only wants to enter the package NAME and not the entire NEVRA. If multiple packages with the same NAME are available, the specific package is then selected by the solver. --- dnf5/context.cpp | 20 ++++++++------------ dnf5/include/dnf5/context.hpp | 7 ++++--- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/dnf5/context.cpp b/dnf5/context.cpp index a7a6a4079..6fd620e71 100644 --- a/dnf5/context.cpp +++ b/dnf5/context.cpp @@ -1073,7 +1073,7 @@ std::vector match_specs( bool installed, bool available, bool paths, - bool nevra_for_same_name, + bool only_nevras, const char * file_name_regex) { auto & base = ctx.get_base(); @@ -1128,19 +1128,15 @@ std::vector match_specs( matched_pkgs_query.resolve_pkg_spec(pattern + '*', settings, true); for (const auto & package : matched_pkgs_query) { - auto [it, inserted] = result_set.insert(package.get_name()); - - // Package name was already present - not inserted. There are multiple packages with the same name. - // If requested, removes the name and inserts a full nevra for these packages. - if (nevra_for_same_name && !inserted) { - result_set.erase(it); - libdnf5::rpm::PackageQuery name_query(matched_pkgs_query); - name_query.filter_name({package.get_name()}); - for (const auto & pkg : name_query) { - result_set.insert(pkg.get_full_nevra()); - matched_pkgs_query.remove(pkg); + if (!only_nevras) { + if (auto name = package.get_name(); name.length() >= pattern.length()) { + // The output must not include a package name shorter than the length of the input patter + // (we don't want to shorten the user-specified input). + result_set.insert(std::move(name)); } } + + result_set.insert(package.get_full_nevra()); } } diff --git a/dnf5/include/dnf5/context.hpp b/dnf5/include/dnf5/context.hpp index bfa3041e2..0cf841f0f 100644 --- a/dnf5/include/dnf5/context.hpp +++ b/dnf5/include/dnf5/context.hpp @@ -285,8 +285,9 @@ class DNF_API RpmTransCB : public libdnf5::rpm::TransactionCallbacks { DNF_API void run_transaction(libdnf5::rpm::Transaction & transaction); -/// Returns the names of matching packages and paths of matching package file names and directories. -/// If `nevra_for_same_name` is true, it returns a full nevra for packages with the same name. +/// Returns the names and nevras of the matching packages and +/// the paths to the matching package file names and directories. +/// The names of the matching packages are returned only if `only_nevras` is false. /// Only files whose names match `file_name_regex` are returned. /// NOTE: This function is intended to be used only for autocompletion purposes as the argument parser's /// complete hook argument. It does the base setup and repos loading inside. @@ -296,7 +297,7 @@ DNF_API std::vector match_specs( bool installed, bool available, bool paths, - bool nevra_for_same_name, + bool only_nevras, const char * file_name_regex = ".*\\.rpm"); } // namespace dnf5 From c17fa88c53bd8dbd9b132627e35302e0c44e5207 Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Mon, 6 Jan 2025 16:05:25 +0100 Subject: [PATCH 2/2] DNF5 bash completion: Offer package NAMEs in all cases For installed packages (for dnf5 commands reinstall, remove, repoquery, swap) bash completion offered only NEVRAs. Now bash completion for dnf5 offers NAMEs in addition to NEVRAs in all cases. --- dnf5/commands/reinstall/reinstall.cpp | 2 +- dnf5/commands/remove/remove.cpp | 2 +- dnf5/commands/repoquery/repoquery.cpp | 2 +- dnf5/commands/swap/swap.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dnf5/commands/reinstall/reinstall.cpp b/dnf5/commands/reinstall/reinstall.cpp index 7ac214814..f9ba1e54b 100644 --- a/dnf5/commands/reinstall/reinstall.cpp +++ b/dnf5/commands/reinstall/reinstall.cpp @@ -48,7 +48,7 @@ void ReinstallCommand::set_argument_parser() { } return true; }); - keys->set_complete_hook_func([&ctx](const char * arg) { return match_specs(ctx, arg, true, false, true, true); }); + keys->set_complete_hook_func([&ctx](const char * arg) { return match_specs(ctx, arg, true, false, true, false); }); cmd.register_positional_arg(keys); allow_erasing = std::make_unique(*this); diff --git a/dnf5/commands/remove/remove.cpp b/dnf5/commands/remove/remove.cpp index a14669b51..1dd139361 100644 --- a/dnf5/commands/remove/remove.cpp +++ b/dnf5/commands/remove/remove.cpp @@ -55,7 +55,7 @@ void RemoveCommand::set_argument_parser() { } return true; }); - keys->set_complete_hook_func([&ctx](const char * arg) { return match_specs(ctx, arg, true, false, false, true); }); + keys->set_complete_hook_func([&ctx](const char * arg) { return match_specs(ctx, arg, true, false, false, false); }); cmd.register_positional_arg(keys); create_offline_option(*this); diff --git a/dnf5/commands/repoquery/repoquery.cpp b/dnf5/commands/repoquery/repoquery.cpp index fbfc7f200..6b76b9835 100644 --- a/dnf5/commands/repoquery/repoquery.cpp +++ b/dnf5/commands/repoquery/repoquery.cpp @@ -106,7 +106,7 @@ void RepoqueryCommand::set_argument_parser() { }); keys->set_complete_hook_func([this, &ctx](const char * arg) { if (this->installed_option->get_value()) { - return match_specs(ctx, arg, true, false, false, true); + return match_specs(ctx, arg, true, false, false, false); } else { return match_specs(ctx, arg, false, true, true, false); } diff --git a/dnf5/commands/swap/swap.cpp b/dnf5/commands/swap/swap.cpp index c14caa03b..1c54f4b03 100644 --- a/dnf5/commands/swap/swap.cpp +++ b/dnf5/commands/swap/swap.cpp @@ -51,7 +51,7 @@ void SwapCommand::set_argument_parser() { return true; }); remove_spec_arg->set_complete_hook_func( - [&ctx](const char * arg) { return match_specs(ctx, arg, true, false, false, true); }); + [&ctx](const char * arg) { return match_specs(ctx, arg, true, false, false, false); }); cmd.register_positional_arg(remove_spec_arg); auto install_spec_arg = parser.add_new_positional_arg("install_spec", 1, nullptr, nullptr);