From 6cc39c750ace7e0da116559ebf2f43b8519886b3 Mon Sep 17 00:00:00 2001 From: Pavla Kratochvilova Date: Thu, 21 Sep 2023 12:35:02 +0200 Subject: [PATCH] modules: Add module list command --- dnf5/commands/module/module.cpp | 8 +- dnf5/commands/module/module_list.cpp | 16 +++- dnf5/commands/module/module_list.hpp | 1 + include/libdnf5-cli/output/modulelist.hpp | 109 ++++++++++++++++++++++ 4 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 include/libdnf5-cli/output/modulelist.hpp diff --git a/dnf5/commands/module/module.cpp b/dnf5/commands/module/module.cpp index f993fe0110..e245a09808 100644 --- a/dnf5/commands/module/module.cpp +++ b/dnf5/commands/module/module.cpp @@ -48,10 +48,10 @@ void ModuleCommand::register_subcommands() { auto & cmd = *get_argument_parser_command(); // query commands - // auto * query_commands_group = parser.add_new_group("module_query_commands"); - // query_commands_group->set_header("Query Commands:"); - // cmd.register_group(query_commands_group); - // register_subcommand(std::make_unique(get_context()), query_commands_group); + auto * query_commands_group = parser.add_new_group("module_query_commands"); + query_commands_group->set_header("Query Commands:"); + cmd.register_group(query_commands_group); + register_subcommand(std::make_unique(get_context()), query_commands_group); // register_subcommand(std::make_unique(get_context()), query_commands_group); // register_subcommand(std::make_unique(get_context()), query_commands_group); diff --git a/dnf5/commands/module/module_list.cpp b/dnf5/commands/module/module_list.cpp index 3f0a434af2..19f81b848b 100644 --- a/dnf5/commands/module/module_list.cpp +++ b/dnf5/commands/module/module_list.cpp @@ -19,13 +19,27 @@ along with libdnf. If not, see . #include "module_list.hpp" +#include +#include + namespace dnf5 { +using namespace libdnf5::cli; + void ModuleListCommand::set_argument_parser() { auto & cmd = *get_argument_parser_command(); cmd.set_description("List module streams"); } -void ModuleListCommand::run() {} +void ModuleListCommand::configure() { + auto & context = get_context(); + context.set_load_system_repo(true); + context.set_load_available_repos(Context::LoadAvailableRepos::ENABLED); +} + +void ModuleListCommand::run() { + libdnf5::module::ModuleQuery query(get_context().base); + output::print_modulelist_table(query.list()); +} } // namespace dnf5 diff --git a/dnf5/commands/module/module_list.hpp b/dnf5/commands/module/module_list.hpp index 98b9abb2cd..109bebd27f 100644 --- a/dnf5/commands/module/module_list.hpp +++ b/dnf5/commands/module/module_list.hpp @@ -28,6 +28,7 @@ class ModuleListCommand : public Command { public: explicit ModuleListCommand(Context & context) : Command(context, "list") {} void set_argument_parser() override; + void configure() override; void run() override; }; diff --git a/include/libdnf5-cli/output/modulelist.hpp b/include/libdnf5-cli/output/modulelist.hpp new file mode 100644 index 0000000000..8984c73696 --- /dev/null +++ b/include/libdnf5-cli/output/modulelist.hpp @@ -0,0 +1,109 @@ +/* +Copyright Contributors to the libdnf project. + +This file is part of libdnf: https://github.com/rpm-software-management/libdnf/ + +Libdnf is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 2.1 of the License, or +(at your option) any later version. + +Libdnf is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with libdnf. If not, see . +*/ + + +#ifndef LIBDNF_CLI_OUTPUT_MODULELIST_HPP +#define LIBDNF_CLI_OUTPUT_MODULELIST_HPP + +#include "utils/string.hpp" + +#include "libdnf5-cli/tty.hpp" + +#include +#include + +namespace libdnf5::cli::output { + + +// module list table columns +enum { COL_MODULE_NAME, COL_MODULE_STREAM, COL_MODULE_PROFILES, COL_MODULE_SUMMARY }; + + +static struct libscols_table * create_modulelist_table() { + struct libscols_table * table = scols_new_table(); + if (libdnf5::cli::tty::is_interactive()) { + scols_table_enable_colors(table, 1); + } + struct libscols_column * cl = scols_table_new_column(table, "Name", 20, 0); + scols_column_set_cmpfunc(cl, scols_cmpstr_cells, NULL); + scols_table_new_column(table, "Stream", 0.5, SCOLS_FL_TRUNC); + scols_table_new_column(table, "Profiles", 0.5, SCOLS_FL_TRUNC); + scols_table_new_column(table, "Summary", 0.5, SCOLS_FL_TRUNC); + return table; +} + + +static void add_line_into_modulelist_table( + struct libscols_table * table, + const char * name, + const char * stream, + const char * profiles, + const char * summary) { + struct libscols_line * ln = scols_table_new_line(table, NULL); + scols_line_set_data(ln, COL_MODULE_NAME, name); + scols_line_set_data(ln, COL_MODULE_STREAM, stream); + scols_line_set_data(ln, COL_MODULE_PROFILES, profiles); + scols_line_set_data(ln, COL_MODULE_SUMMARY, summary); +} + + +template +void print_modulelist_table(Query & module_list) { + // TODO(pkratoch): Sort the table + struct libscols_table * table = create_modulelist_table(); + std::set> name_stream_pairs; + for (auto & module_item : module_list) { + const std::string & name = module_item.get_name(); + const std::string & stream = module_item.get_stream(); + if (!name_stream_pairs.contains(make_pair(name, stream))) { + // Get stream string (append [e] or [x] if needed) + std::string stream_string = stream; + const module::ModuleStatus & status = module_item.get_status(); + if (status == module::ModuleStatus::ENABLED) { + stream_string.append(" [e]"); + } else if (status == module::ModuleStatus::DISABLED) { + stream_string.append(" [x]"); + } + + // Get profile strings (append [d] or [i] if needed) + std::vector profile_strings; + for (auto profile : module_item.get_profiles()) { + // TODO(pkratoch): Also show "[i]" for installed profiles + // TODO(pkratoch): Make sure defaults are loaded + profile_strings.push_back(profile.is_default() ? profile.get_name() + " [d]" : profile.get_name()); + } + + add_line_into_modulelist_table( + table, + name.c_str(), + stream_string.c_str(), + utils::string::join(profile_strings, ", ").c_str(), + module_item.get_summary().c_str()); + name_stream_pairs.emplace(make_pair(name, stream)); + } + } + scols_sort_table(table, scols_table_get_column(table, COL_MODULE_NAME)); + scols_print_table(table); + scols_unref_table(table); +} + + +} // namespace libdnf5::cli::output + +#endif // LIBDNF_CLI_OUTPUT_MODULELIST_HPP