Skip to content

Commit

Permalink
Added de-duplication for environment list print
Browse files Browse the repository at this point in the history
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: rpm-software-management#1502
  • Loading branch information
bc-lee committed May 18, 2024
1 parent ae824d8 commit 6ec1c27
Showing 1 changed file with 54 additions and 6 deletions.
60 changes: 54 additions & 6 deletions libdnf5-cli/output/environmentlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,42 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.

#include <libsmartcols/libsmartcols.h>

#include <map>

namespace libdnf5::cli::output {

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();
Expand Down Expand Up @@ -61,12 +90,31 @@ void add_line_into_environmentlist_table(

void print_environmentlist_table(std::vector<std::unique_ptr<IEnvironment>> & 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<EnvironmentListEntry, IndexAndInstalled> 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<std::pair<EnvironmentListEntry, bool>> 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);
Expand Down

0 comments on commit 6ec1c27

Please sign in to comment.