mirror of https://github.com/mamba-org/mamba.git
Fix `repoquery` issues (#2330)
Fix `depends` and `whoneeds` repoquery sub-commands in micromamba
This commit is contained in:
parent
b38377a479
commit
e549d07b0c
|
@ -100,6 +100,8 @@ namespace mamba
|
|||
|
||||
std::ostream& pretty(std::ostream&) const;
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
|
||||
void reset_pkg_view_list();
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace mamba
|
|||
{
|
||||
auto& ctx = Context::instance();
|
||||
auto& config = Configuration::instance();
|
||||
|
||||
config.at("show_banner").set_value(false);
|
||||
config.at("use_target_prefix_fallback").set_value(true);
|
||||
config.at("target_prefix_checks")
|
||||
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX);
|
||||
|
@ -29,6 +31,10 @@ namespace mamba
|
|||
MultiPackageCache package_caches(ctx.pkgs_dirs);
|
||||
if (use_local)
|
||||
{
|
||||
if (format != QueryResultFormat::kJSON)
|
||||
{
|
||||
Console::stream() << "Using local repodata..." << std::endl;
|
||||
}
|
||||
auto exp_prefix_data = PrefixData::create(ctx.target_prefix);
|
||||
if (!exp_prefix_data)
|
||||
{
|
||||
|
@ -37,10 +43,18 @@ namespace mamba
|
|||
}
|
||||
PrefixData& prefix_data = exp_prefix_data.value();
|
||||
MRepo::create(pool, prefix_data);
|
||||
Console::stream() << "Loaded current active prefix: " << ctx.target_prefix << std::endl;
|
||||
if (format != QueryResultFormat::kJSON)
|
||||
{
|
||||
Console::stream() << "Loaded current active prefix: " << ctx.target_prefix
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (format != QueryResultFormat::kJSON)
|
||||
{
|
||||
Console::stream() << "Getting repodata from channels..." << std::endl;
|
||||
}
|
||||
auto exp_load = load_channels(pool, package_caches, 0);
|
||||
if (!exp_load)
|
||||
{
|
||||
|
@ -70,6 +84,11 @@ namespace mamba
|
|||
default:
|
||||
res.groupby("name").table(std::cout);
|
||||
}
|
||||
if (res.empty())
|
||||
{
|
||||
std::cout << "Channels may not be configured. Try giving a channel with '-c,--channel' option, or use `--use-local=1` to search for installed packages."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == QueryType::kDEPENDS)
|
||||
|
@ -91,6 +110,12 @@ namespace mamba
|
|||
case QueryResultFormat::kRECURSIVETABLE:
|
||||
res.sort("name").table(std::cout);
|
||||
}
|
||||
if (res.empty() && format != QueryResultFormat::kJSON)
|
||||
{
|
||||
std::cout << query
|
||||
<< " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else if (type == QueryType::kWHONEEDS)
|
||||
{
|
||||
|
@ -114,6 +139,12 @@ namespace mamba
|
|||
{ "Name", "Version", "Build", concat("Depends:", query), "Channel" }
|
||||
);
|
||||
}
|
||||
if (res.empty() && format != QueryResultFormat::kJSON)
|
||||
{
|
||||
std::cout << query
|
||||
<< " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
config.operation_teardown();
|
||||
|
|
|
@ -658,18 +658,6 @@ namespace mamba
|
|||
return out;
|
||||
}
|
||||
|
||||
std::ostream& query_result::pretty(std::ostream& out) const
|
||||
{
|
||||
if (!m_pkg_view_list.empty())
|
||||
{
|
||||
for (const auto& pkg : m_pkg_view_list)
|
||||
{
|
||||
print_solvable(pkg);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
nlohmann::json query_result::json() const
|
||||
{
|
||||
nlohmann::json j;
|
||||
|
@ -699,6 +687,23 @@ namespace mamba
|
|||
return j;
|
||||
}
|
||||
|
||||
std::ostream& query_result::pretty(std::ostream& out) const
|
||||
{
|
||||
if (!m_pkg_view_list.empty())
|
||||
{
|
||||
for (const auto& pkg : m_pkg_view_list)
|
||||
{
|
||||
print_solvable(pkg);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool query_result::empty() const
|
||||
{
|
||||
return m_dep_graph.empty();
|
||||
}
|
||||
|
||||
void query_result::reset_pkg_view_list()
|
||||
{
|
||||
auto it = m_dep_graph.nodes().begin();
|
||||
|
|
|
@ -357,19 +357,25 @@ PYBIND11_MODULE(bindings, m)
|
|||
"find",
|
||||
[](const Query& q, const std::string& query, const query::RESULT_FORMAT format) -> std::string
|
||||
{
|
||||
query_result res = q.find(query);
|
||||
std::stringstream res_stream;
|
||||
switch (format)
|
||||
{
|
||||
case query::JSON:
|
||||
res_stream << q.find(query).groupby("name").json().dump(4);
|
||||
res_stream << res.groupby("name").json().dump(4);
|
||||
break;
|
||||
case query::TREE:
|
||||
case query::TABLE:
|
||||
case query::RECURSIVETABLE:
|
||||
q.find(query).groupby("name").table(res_stream);
|
||||
res.groupby("name").table(res_stream);
|
||||
break;
|
||||
case query::PRETTY:
|
||||
q.find(query).groupby("name").pretty(res_stream);
|
||||
res.groupby("name").pretty(res_stream);
|
||||
}
|
||||
if (res.empty())
|
||||
{
|
||||
res_stream << query
|
||||
<< " may not be installed. Try specifying a channel with '-c,--channel' option\n";
|
||||
}
|
||||
return res_stream.str();
|
||||
}
|
||||
|
@ -397,6 +403,11 @@ PYBIND11_MODULE(bindings, m)
|
|||
{ "Name", "Version", "Build", concat("Depends:", query), "Channel" }
|
||||
);
|
||||
}
|
||||
if (res.empty())
|
||||
{
|
||||
res_stream << query
|
||||
<< " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery\n";
|
||||
}
|
||||
return res_stream.str();
|
||||
}
|
||||
)
|
||||
|
@ -424,6 +435,11 @@ PYBIND11_MODULE(bindings, m)
|
|||
// query), "Channel"});
|
||||
res.table(res_stream);
|
||||
}
|
||||
if (res.empty())
|
||||
{
|
||||
res_stream << query
|
||||
<< " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery\n";
|
||||
}
|
||||
return res_stream.str();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -60,7 +60,7 @@ set_common_search(CLI::App* subcom, bool is_repoquery)
|
|||
subcom->add_flag(
|
||||
"--recursive",
|
||||
recursive,
|
||||
"Show dependencies recursively (i.e. transitive dependencies)."
|
||||
"Show dependencies recursively, i.e. transitive dependencies (only for `depends`)"
|
||||
);
|
||||
|
||||
static bool pretty_print = false;
|
||||
|
@ -69,8 +69,12 @@ set_common_search(CLI::App* subcom, bool is_repoquery)
|
|||
static std::vector<std::string> specs;
|
||||
subcom->add_option("specs", specs, "Specs to search")->required();
|
||||
|
||||
static int local = 0;
|
||||
subcom->add_flag("--local,!--remote", local, "Use installed data or remote repositories");
|
||||
static int local = -1;
|
||||
subcom->add_option(
|
||||
"--use-local",
|
||||
local,
|
||||
"Use installed data (--use-local=1, default for `depends` and `whoneeds`) or remote repositories (--use-local=0, default for `search`).\nIf the `-c,--channel` option is set, it has the priority and --use-local is set to 0"
|
||||
);
|
||||
|
||||
auto& platform = config.at("platform");
|
||||
subcom->add_option("--platform", platform.get_cli_config<std::string>(), platform.description());
|
||||
|
@ -80,19 +84,20 @@ set_common_search(CLI::App* subcom, bool is_repoquery)
|
|||
{
|
||||
auto qtype = str_to_qtype(query_type);
|
||||
QueryResultFormat format = QueryResultFormat::kTABLE;
|
||||
bool use_local = true;
|
||||
switch (qtype)
|
||||
{
|
||||
case QueryType::kSEARCH:
|
||||
format = QueryResultFormat::kTABLE;
|
||||
local = (local == 0) ? false : local > 0;
|
||||
use_local = local > 0; // use remote repodata by default for `search`
|
||||
break;
|
||||
case QueryType::kDEPENDS:
|
||||
format = QueryResultFormat::kTABLE;
|
||||
local = (local == 0) ? true : local > 0;
|
||||
use_local = (local == -1) || (local > 0);
|
||||
break;
|
||||
case QueryType::kWHONEEDS:
|
||||
format = QueryResultFormat::kTABLE;
|
||||
local = (local == 0) ? true : local > 0;
|
||||
use_local = (local == -1) || (local > 0);
|
||||
break;
|
||||
}
|
||||
if (qtype == QueryType::kDEPENDS && recursive)
|
||||
|
@ -110,10 +115,15 @@ set_common_search(CLI::App* subcom, bool is_repoquery)
|
|||
format = QueryResultFormat::kPRETTY;
|
||||
}
|
||||
|
||||
// if (ctx.json)
|
||||
// format = QueryResultFormat::kJSON;
|
||||
if (config.at("json").compute().value<bool>())
|
||||
{
|
||||
format = QueryResultFormat::kJSON;
|
||||
}
|
||||
|
||||
repoquery(qtype, format, local, specs[0]);
|
||||
auto& channels = config.at("channels").compute().value<std::vector<std::string>>();
|
||||
use_local = use_local && channels.empty();
|
||||
|
||||
repoquery(qtype, format, use_local, specs[0]);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -307,6 +307,23 @@ def umamba_run(*args, **kwargs):
|
|||
return res.decode()
|
||||
|
||||
|
||||
def umamba_repoquery(*args, no_rc=True):
|
||||
umamba = get_umamba()
|
||||
|
||||
cmd = [umamba, "repoquery"] + [arg for arg in args if arg]
|
||||
|
||||
if no_rc:
|
||||
cmd += ["--no-rc"]
|
||||
|
||||
res = subprocess_run(*cmd)
|
||||
|
||||
if "--json" in args:
|
||||
j = json.loads(res)
|
||||
return j
|
||||
|
||||
return res.decode()
|
||||
|
||||
|
||||
def get_concrete_pkg(t, needle):
|
||||
pkgs = t["actions"]["LINK"]
|
||||
for p in pkgs:
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
import os
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
from .helpers import create, get_env, random_string, umamba_repoquery
|
||||
|
||||
|
||||
class TestRepoquery:
|
||||
env_name = random_string()
|
||||
root_prefix = os.environ["MAMBA_ROOT_PREFIX"]
|
||||
current_prefix = os.environ["CONDA_PREFIX"]
|
||||
prefix = os.path.join(root_prefix, "envs", env_name)
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
create(
|
||||
"yaml=0.2.5",
|
||||
"pyyaml=6.0",
|
||||
"-c",
|
||||
"conda-forge",
|
||||
"-n",
|
||||
TestRepoquery.env_name,
|
||||
"--json",
|
||||
no_dry_run=True,
|
||||
)
|
||||
os.environ["CONDA_PREFIX"] = TestRepoquery.prefix
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
os.environ["CONDA_PREFIX"] = TestRepoquery.current_prefix
|
||||
shutil.rmtree(get_env(TestRepoquery.env_name))
|
||||
|
||||
# Testing `depends`
|
||||
def test_depends(self):
|
||||
res = umamba_repoquery("depends", "yaml=0.2.5", "--json")
|
||||
|
||||
assert res["query"]["query"] == "yaml =0.2.5*"
|
||||
assert res["query"]["type"] == "depends"
|
||||
|
||||
pkgs = res["result"]["pkgs"]
|
||||
assert any(x["channel"] == "conda-forge" for x in pkgs)
|
||||
assert any(x["name"] == "yaml" for x in pkgs)
|
||||
assert any(x["version"] == "0.2.5" for x in pkgs)
|
||||
|
||||
if platform.system() == "Linux":
|
||||
assert any(x["name"] == "libgcc-ng" for x in pkgs)
|
||||
|
||||
def test_depends_remote(self):
|
||||
res = umamba_repoquery("depends", "yaml", "--use-local=0")
|
||||
|
||||
assert 'No entries matching "yaml" found' in res
|
||||
|
||||
def test_depends_not_installed(self):
|
||||
res = umamba_repoquery("depends", "xtensor")
|
||||
|
||||
assert 'No entries matching "xtensor" found' in res
|
||||
|
||||
def test_depends_not_installed_with_channel(self):
|
||||
res = umamba_repoquery(
|
||||
"depends", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
||||
)
|
||||
|
||||
assert res["query"]["query"] == "xtensor =0.24.5*"
|
||||
assert res["query"]["type"] == "depends"
|
||||
assert "conda-forge" in res["result"]["graph_roots"][0]["channel"]
|
||||
assert res["result"]["graph_roots"][0]["name"] == "xtensor"
|
||||
assert res["result"]["graph_roots"][0]["version"] == "0.24.5"
|
||||
|
||||
pkgs = res["result"]["pkgs"]
|
||||
|
||||
assert any(x["name"] == "xtensor" for x in pkgs)
|
||||
assert any(x["name"] == "xtl" for x in pkgs)
|
||||
|
||||
if platform.system() == "Linux":
|
||||
assert any(x["name"] == "libgcc-ng" for x in pkgs)
|
||||
assert any(x["name"] == "libstdcxx-ng" for x in pkgs)
|
||||
|
||||
def test_depends_recursive(self):
|
||||
res = umamba_repoquery(
|
||||
"depends", "-c", "conda-forge", "xtensor=0.24.5", "--recursive"
|
||||
)
|
||||
|
||||
if platform.system() == "Linux":
|
||||
assert "libzlib" in res
|
||||
elif platform.system() == "Darwin":
|
||||
assert "libcxx" in res
|
||||
elif platform.system() == "Windows":
|
||||
assert "vc" in res
|
||||
|
||||
def test_depends_tree(self):
|
||||
res = umamba_repoquery(
|
||||
"depends", "-c", "conda-forge", "xtensor=0.24.5", "--tree"
|
||||
)
|
||||
|
||||
if platform.system() == "Linux":
|
||||
assert "libzlib" in res
|
||||
elif platform.system() == "Darwin":
|
||||
assert "libcxx" in res
|
||||
elif platform.system() == "Windows":
|
||||
assert "vc" in res
|
||||
|
||||
# Testing `whoneeds`
|
||||
def test_whoneeds(self):
|
||||
res = umamba_repoquery("whoneeds", "yaml", "--json")
|
||||
|
||||
assert res["query"]["query"] == "yaml"
|
||||
assert res["query"]["type"] == "whoneeds"
|
||||
assert res["result"]["pkgs"][0]["channel"] == "conda-forge"
|
||||
assert res["result"]["pkgs"][0]["name"] == "pyyaml"
|
||||
assert res["result"]["pkgs"][0]["version"] == "6.0"
|
||||
|
||||
def test_whoneeds_remote(self):
|
||||
res = umamba_repoquery("whoneeds", "yaml", "--use-local=0")
|
||||
|
||||
assert 'No entries matching "yaml" found' in res
|
||||
|
||||
def test_whoneeds_not_installed(self):
|
||||
res = umamba_repoquery("whoneeds", "xtensor")
|
||||
|
||||
assert 'No entries matching "xtensor" found' in res
|
||||
|
||||
def test_whoneeds_not_installed_with_channel(self):
|
||||
res = umamba_repoquery(
|
||||
"whoneeds", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
||||
)
|
||||
|
||||
assert res["query"]["query"] == "xtensor =0.24.5*"
|
||||
assert res["query"]["type"] == "whoneeds"
|
||||
|
||||
pkgs = res["result"]["pkgs"]
|
||||
assert all("conda-forge" in x["channel"] for x in pkgs)
|
||||
assert any(x["name"] == "cppcolormap" for x in pkgs)
|
||||
assert any(x["name"] == "pyxtensor" for x in pkgs)
|
||||
assert any(x["name"] == "qpot" for x in pkgs)
|
||||
|
||||
def test_whoneeds_tree(self):
|
||||
res = umamba_repoquery(
|
||||
"whoneeds", "-c", "conda-forge", "xtensor=0.24.5", "--tree"
|
||||
)
|
||||
|
||||
assert "cppcolormap" in res
|
||||
assert "pyxtensor" in res
|
||||
assert "qpot" in res
|
||||
|
||||
# Testing `search`
|
||||
def test_remote_search_installed_pkg(self):
|
||||
res = umamba_repoquery("search", "yaml")
|
||||
|
||||
assert 'No entries matching "yaml" found' in res
|
||||
assert (
|
||||
"Channels may not be configured. Try giving a channel with '-c,--channel' option, or use `--use-local=1` to search for installed packages."
|
||||
in res
|
||||
)
|
||||
|
||||
def test_local_search_installed_pkg(self):
|
||||
res = umamba_repoquery("search", "yaml", "--use-local=1", "--json")
|
||||
|
||||
assert res["query"]["query"] == "yaml"
|
||||
assert res["query"]["type"] == "search"
|
||||
assert res["result"]["pkgs"][0]["channel"] == "conda-forge"
|
||||
assert res["result"]["pkgs"][0]["name"] == "yaml"
|
||||
assert res["result"]["pkgs"][0]["version"] == "0.2.5"
|
||||
|
||||
def test_remote_search_not_installed_pkg(self):
|
||||
res = umamba_repoquery(
|
||||
"search", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
||||
)
|
||||
|
||||
assert res["query"]["query"] == "xtensor =0.24.5*"
|
||||
assert res["query"]["type"] == "search"
|
||||
assert "conda-forge" in res["result"]["pkgs"][0]["channel"]
|
||||
assert res["result"]["pkgs"][0]["name"] == "xtensor"
|
||||
assert res["result"]["pkgs"][0]["version"] == "0.24.5"
|
Loading…
Reference in New Issue