feat: add reverse flag to list command (#3705)

This commit is contained in:
Sandrine Pataut 2025-01-15 11:46:24 +01:00 committed by GitHub
parent 0023a3b13a
commit 630b62fa83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 77 additions and 6 deletions

View File

@ -24,6 +24,7 @@ namespace mamba
{
bool full_name;
bool no_pip;
bool reverse;
};
struct formatted_pkg
@ -36,6 +37,11 @@ namespace mamba
return a.name < b.name;
}
bool compare_reverse_alphabetically(const formatted_pkg& a, const formatted_pkg& b)
{
return a.name >= b.name;
}
std::string strip_from_filename_and_platform(
const std::string& full_str,
const std::string& filename,
@ -87,7 +93,18 @@ namespace mamba
{
keys.push_back(pkg.first);
}
std::sort(keys.begin(), keys.end());
if (options.reverse)
{
std::sort(
keys.begin(),
keys.end(),
[](const std::string& a, const std::string& b) { return a >= b; }
);
}
else
{
std::sort(keys.begin(), keys.end());
}
for (const auto& key : keys)
{
@ -168,7 +185,9 @@ namespace mamba
}
}
std::sort(packages.begin(), packages.end(), compare_alphabetically);
auto comparator = options.reverse ? compare_reverse_alphabetically
: compare_alphabetically;
std::sort(packages.begin(), packages.end(), comparator);
// format and print table
printers::Table t({ "Name", "Version", "Build", "Channel" });
@ -208,6 +227,7 @@ namespace mamba
detail::list_options options;
options.full_name = config.at("full_name").value<bool>();
options.no_pip = config.at("no_pip").value<bool>();
options.reverse = config.at("reverse").value<bool>();
auto channel_context = ChannelContext::make_conda_compatible(config.context());
detail::list_packages(config.context(), regex, channel_context, std::move(options));

View File

@ -34,6 +34,10 @@ init_list_parser(CLI::App* subcom, Configuration& config)
.description("Do not include pip-only installed packages."));
subcom->add_flag("--no-pip", no_pip.get_cli_config<bool>(), no_pip.description());
auto& reverse = config.insert(
Configurable("reverse", false).group("cli").description("List installed packages in reverse order.")
);
subcom->add_flag("--reverse", reverse.get_cli_config<bool>(), reverse.description());
// TODO: implement this in libmamba/list.cpp
/*auto& canonical = config.insert(Configurable("canonical", false)
.group("cli")

View File

@ -7,16 +7,19 @@ import pytest
from . import helpers
@pytest.mark.parametrize("reverse_flag", ["", "--reverse"])
@pytest.mark.parametrize("quiet_flag", ["", "-q", "--quiet"])
@pytest.mark.parametrize("env_selector", ["", "name", "prefix"])
@pytest.mark.parametrize("shared_pkgs_dirs", [True], indirect=True)
def test_list(tmp_home, tmp_root_prefix, tmp_env_name, tmp_xtensor_env, env_selector, quiet_flag):
def test_list(
tmp_home, tmp_root_prefix, tmp_env_name, tmp_xtensor_env, env_selector, quiet_flag, reverse_flag
):
if env_selector == "prefix":
res = helpers.umamba_list("-p", tmp_xtensor_env, "--json", quiet_flag)
res = helpers.umamba_list("-p", tmp_xtensor_env, "--json", quiet_flag, reverse_flag)
elif env_selector == "name":
res = helpers.umamba_list("-n", tmp_env_name, "--json", quiet_flag)
res = helpers.umamba_list("-n", tmp_env_name, "--json", quiet_flag, reverse_flag)
else:
res = helpers.umamba_list("--json", quiet_flag)
res = helpers.umamba_list("--json", quiet_flag, reverse_flag)
assert len(res) > 2
@ -28,6 +31,50 @@ def test_list(tmp_home, tmp_root_prefix, tmp_env_name, tmp_xtensor_env, env_sele
for i in res
)
if reverse_flag == "--reverse":
assert names.index("xtensor") > names.index("xtl")
else:
assert names.index("xtensor") < names.index("xtl")
@pytest.mark.parametrize("reverse_flag", ["", "--reverse"])
@pytest.mark.parametrize("quiet_flag", ["", "-q", "--quiet"])
@pytest.mark.parametrize("env_selector", ["", "name", "prefix"])
@pytest.mark.parametrize("shared_pkgs_dirs", [True], indirect=True)
def test_list_no_json(
tmp_home, tmp_root_prefix, tmp_env_name, tmp_xtensor_env, env_selector, quiet_flag, reverse_flag
):
if env_selector == "prefix":
res = helpers.umamba_list("-p", tmp_xtensor_env, quiet_flag, reverse_flag)
elif env_selector == "name":
res = helpers.umamba_list("-n", tmp_env_name, quiet_flag, reverse_flag)
else:
res = helpers.umamba_list(quiet_flag, reverse_flag)
assert len(res) > 10
assert "xtensor" in res
assert "xtl" in res
# This is what res looks like in this case (with or without a header delimiter):
# List of packages in environment: "xxx"
# Name Version Build Channel
# ────────────────────────────────────────────────────
# _libgcc_mutex 0.1 conda_forge conda-forge
# _openmp_mutex 4.5 2_gnu conda-forge
packages = res[res.rindex("Channel") :].split("\n", 1)[1]
packages_list = packages.strip().split("\n")[1:]
for package in packages_list:
channel = package.split(" ")[-1]
channel = channel.replace("\r", "")
assert channel == "conda-forge"
if reverse_flag == "--reverse":
assert res.find("xtensor") > res.find("xtl")
else:
assert res.find("xtensor") < res.find("xtl")
@pytest.mark.parametrize("quiet_flag", ["", "-q", "--quiet"])
@pytest.mark.parametrize("shared_pkgs_dirs", [True], indirect=True)