From 6ec1c273d7c944c9b5b19a94abe9c10f60c106f0 Mon Sep 17 00:00:00 2001 From: Byoungchan Lee Date: Sat, 18 May 2024 09:44:49 +0900 Subject: [PATCH] Added de-duplication for environment list print Previously, `dnf5 environment list` would print duplicate environment with the same id and name. It would be confusing for the user to see duplicate environment names. This patch introduces de-duplication for the environment list print feature to merge duplicate environment entries. The original order of the environments is preserved by assigning an index value to each environment entry. Fixes: #1502 --- libdnf5-cli/output/environmentlist.cpp | 60 +++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/libdnf5-cli/output/environmentlist.cpp b/libdnf5-cli/output/environmentlist.cpp index 0167989eb..3277dd223 100644 --- a/libdnf5-cli/output/environmentlist.cpp +++ b/libdnf5-cli/output/environmentlist.cpp @@ -23,6 +23,8 @@ along with libdnf. If not, see . #include +#include + namespace libdnf5::cli::output { namespace { @@ -30,6 +32,33 @@ namespace { // environment list table columns enum { COL_ENVIRONMENT_ID, COL_ENVIRONMENT_NAME, COL_INSTALLED }; +struct EnvironmentListEntry { + std::string environmentid; + std::string name; + + // Actual comparison operator isn't important as we finally + // sort the table by the inserted order. + std::strong_ordering operator<=>(const EnvironmentListEntry & other) const { + int result = std::strcmp(environmentid.c_str(), other.environmentid.c_str()); + if (result < 0) { + return std::strong_ordering::less; + } else if (result > 0) { + return std::strong_ordering::greater; + } + result = std::strcmp(name.c_str(), other.name.c_str()); + if (result < 0) { + return std::strong_ordering::less; + } else if (result > 0) { + return std::strong_ordering::greater; + } + return std::strong_ordering::equal; + } +}; + +struct IndexAndInstalled { + int index; + bool installed; +}; struct libscols_table * create_environmentlist_table() { struct libscols_table * table = scols_new_table(); @@ -61,12 +90,31 @@ void add_line_into_environmentlist_table( void print_environmentlist_table(std::vector> & environment_list) { struct libscols_table * table = create_environmentlist_table(); - for (auto & environment : environment_list) { - add_line_into_environmentlist_table( - table, - environment->get_environmentid().c_str(), - environment->get_name().c_str(), - environment->get_installed()); + + // de-duplicate environments. + // If any of the environments is installed, the entry is considered installed. + // To keep the order of environments, we use a map and assign an index to each environment. + std::map environments; + int i = 0; + for (const auto & environment : environment_list) { + EnvironmentListEntry entry{environment->get_environmentid(), environment->get_name()}; + auto it = environments.find(entry); + if (it == environments.end()) { + environments[entry] = IndexAndInstalled{.index = i, .installed = environment->get_installed()}; + i++; + } else { + it->second.installed = it->second.installed || environment->get_installed(); + } + } + + std::vector> environments_sorted; + environments_sorted.resize(environments.size()); + for (const auto & [entry, index_and_installed] : environments) { + environments_sorted[index_and_installed.index] = {entry, index_and_installed.installed}; + } + + for (auto & [entry, installed] : environments_sorted) { + add_line_into_environmentlist_table(table, entry.environmentid.c_str(), entry.name.c_str(), installed); } auto cl = scols_table_get_column(table, COL_ENVIRONMENT_ID); scols_sort_table(table, cl);