mirror of https://github.com/mamba-org/mamba.git
Add multiple queries to repoquery search (#2897)
* Remove kENUM * Fix Hide URL confidential * Refactor repoquery initialization * Hide implementation headers * Add enum_name(QueryType) * Add QueryType_from_name * Mulitple queries in repoquery search * Stubgen * No mathspec in Json query * Remove unused ChannelContext
This commit is contained in:
parent
620ae9500c
commit
5d515fa043
|
@ -4,6 +4,10 @@
|
||||||
//
|
//
|
||||||
// The full license is in the file LICENSE, distributed with this software.
|
// The full license is in the file LICENSE, distributed with this software.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mamba/api/configuration.hpp"
|
||||||
#include "mamba/core/query.hpp"
|
#include "mamba/core/query.hpp"
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
|
@ -13,6 +17,6 @@ namespace mamba
|
||||||
QueryType type,
|
QueryType type,
|
||||||
QueryResultFormat format,
|
QueryResultFormat format,
|
||||||
bool use_local,
|
bool use_local,
|
||||||
const std::string& query
|
const std::vector<std::string>& query
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,17 +9,9 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <solv/pool.h>
|
|
||||||
#include <solv/repo.h>
|
|
||||||
#include <solv/selection.h>
|
|
||||||
#include <solv/solver.h>
|
|
||||||
extern "C" // Incomplete header
|
|
||||||
{
|
|
||||||
#include <solv/conda.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "mamba/core/context.hpp"
|
#include "mamba/core/context.hpp"
|
||||||
#include "mamba/core/package_info.hpp"
|
#include "mamba/core/package_info.hpp"
|
||||||
#include "mamba/core/pool.hpp"
|
#include "mamba/core/pool.hpp"
|
||||||
|
@ -47,7 +39,7 @@ namespace mamba
|
||||||
|
|
||||||
Query(MPool& pool);
|
Query(MPool& pool);
|
||||||
|
|
||||||
query_result find(const std::string& query) const;
|
query_result find(const std::vector<std::string>& queries) const;
|
||||||
query_result whoneeds(const std::string& query, bool tree) const;
|
query_result whoneeds(const std::string& query, bool tree) const;
|
||||||
query_result depends(const std::string& query, bool tree) const;
|
query_result depends(const std::string& query, bool tree) const;
|
||||||
|
|
||||||
|
@ -58,18 +50,21 @@ namespace mamba
|
||||||
|
|
||||||
enum class QueryType
|
enum class QueryType
|
||||||
{
|
{
|
||||||
kSEARCH,
|
Search,
|
||||||
kDEPENDS,
|
Depends,
|
||||||
kWHONEEDS
|
WhoNeeds
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr auto enum_name(QueryType t) -> std::string_view;
|
||||||
|
auto QueryType_from_name(std::string_view name) -> QueryType;
|
||||||
|
|
||||||
enum class QueryResultFormat
|
enum class QueryResultFormat
|
||||||
{
|
{
|
||||||
kJSON = 0,
|
Json = 0,
|
||||||
kTREE = 1,
|
Tree = 1,
|
||||||
kTABLE = 2,
|
Table = 2,
|
||||||
kPRETTY = 3,
|
Pretty = 3,
|
||||||
kRECURSIVETABLE = 4,
|
RecursiveTable = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_result
|
class query_result
|
||||||
|
@ -97,7 +92,7 @@ namespace mamba
|
||||||
std::ostream& table(std::ostream&) const;
|
std::ostream& table(std::ostream&) const;
|
||||||
std::ostream& table(std::ostream&, const std::vector<std::string_view>& fmt) const;
|
std::ostream& table(std::ostream&, const std::vector<std::string_view>& fmt) const;
|
||||||
std::ostream& tree(std::ostream&, const GraphicsParams& graphics) const;
|
std::ostream& tree(std::ostream&, const GraphicsParams& graphics) const;
|
||||||
nlohmann::json json(ChannelContext& channel_context) const;
|
nlohmann::json json() const;
|
||||||
|
|
||||||
std::ostream& pretty(std::ostream&, const Context::OutputParams& outputParams) const;
|
std::ostream& pretty(std::ostream&, const Context::OutputParams& outputParams) const;
|
||||||
|
|
||||||
|
@ -118,6 +113,25 @@ namespace mamba
|
||||||
package_id_list m_pkg_id_list = {};
|
package_id_list m_pkg_id_list = {};
|
||||||
ordered_package_list m_ordered_pkg_id_list = {};
|
ordered_package_list m_ordered_pkg_id_list = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/********************
|
||||||
|
* Implementation *
|
||||||
|
********************/
|
||||||
|
|
||||||
|
constexpr auto enum_name(QueryType t) -> std::string_view
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case QueryType::Search:
|
||||||
|
return "Search";
|
||||||
|
case QueryType::WhoNeeds:
|
||||||
|
return "WhoNeeds";
|
||||||
|
case QueryType::Depends:
|
||||||
|
return "Depends";
|
||||||
|
}
|
||||||
|
throw std::invalid_argument("Invalid enum value");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mamba
|
} // namespace mamba
|
||||||
|
|
||||||
#endif // MAMBA_QUERY_HPP
|
#endif // MAMBA_QUERY_HPP
|
||||||
|
|
|
@ -17,76 +17,90 @@
|
||||||
|
|
||||||
namespace mamba
|
namespace mamba
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
auto repoquery_init(Configuration& config, QueryResultFormat format, bool use_local)
|
||||||
|
{
|
||||||
|
auto& ctx = config.context();
|
||||||
|
|
||||||
|
config.at("use_target_prefix_fallback").set_value(true);
|
||||||
|
config.at("target_prefix_checks")
|
||||||
|
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX);
|
||||||
|
config.load();
|
||||||
|
|
||||||
|
ChannelContext channel_context{ ctx };
|
||||||
|
MPool pool{ channel_context };
|
||||||
|
|
||||||
|
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
|
||||||
|
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
||||||
|
if (use_local)
|
||||||
|
{
|
||||||
|
if (format != QueryResultFormat::Json)
|
||||||
|
{
|
||||||
|
Console::stream() << "Using local repodata..." << std::endl;
|
||||||
|
}
|
||||||
|
auto exp_prefix_data = PrefixData::create(
|
||||||
|
ctx.prefix_params.target_prefix,
|
||||||
|
channel_context
|
||||||
|
);
|
||||||
|
if (!exp_prefix_data)
|
||||||
|
{
|
||||||
|
// TODO: propagate tl::expected mechanism
|
||||||
|
throw std::runtime_error(exp_prefix_data.error().what());
|
||||||
|
}
|
||||||
|
PrefixData& prefix_data = exp_prefix_data.value();
|
||||||
|
MRepo(pool, prefix_data);
|
||||||
|
if (format != QueryResultFormat::Json)
|
||||||
|
{
|
||||||
|
Console::stream()
|
||||||
|
<< "Loaded current active prefix: " << ctx.prefix_params.target_prefix
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (format != QueryResultFormat::Json)
|
||||||
|
{
|
||||||
|
Console::stream() << "Getting repodata from channels..." << std::endl;
|
||||||
|
}
|
||||||
|
auto exp_load = load_channels(pool, package_caches, 0);
|
||||||
|
if (!exp_load)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(exp_load.error().what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void repoquery(
|
void repoquery(
|
||||||
Configuration& config,
|
Configuration& config,
|
||||||
QueryType type,
|
QueryType type,
|
||||||
QueryResultFormat format,
|
QueryResultFormat format,
|
||||||
bool use_local,
|
bool use_local,
|
||||||
const std::string& query
|
const std::vector<std::string>& queries
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto& ctx = config.context();
|
auto& ctx = config.context();
|
||||||
|
auto pool = repoquery_init(config, format, use_local);
|
||||||
config.at("use_target_prefix_fallback").set_value(true);
|
|
||||||
config.at("target_prefix_checks")
|
|
||||||
.set_value(MAMBA_ALLOW_EXISTING_PREFIX | MAMBA_ALLOW_MISSING_PREFIX);
|
|
||||||
config.load();
|
|
||||||
|
|
||||||
ChannelContext channel_context{ ctx };
|
|
||||||
MPool pool{ channel_context };
|
|
||||||
|
|
||||||
// bool installed = (type == QueryType::kDepends) || (type == QueryType::kWhoneeds);
|
|
||||||
MultiPackageCache package_caches(ctx.pkgs_dirs, ctx.validation_params);
|
|
||||||
if (use_local)
|
|
||||||
{
|
|
||||||
if (format != QueryResultFormat::kJSON)
|
|
||||||
{
|
|
||||||
Console::stream() << "Using local repodata..." << std::endl;
|
|
||||||
}
|
|
||||||
auto exp_prefix_data = PrefixData::create(ctx.prefix_params.target_prefix, channel_context);
|
|
||||||
if (!exp_prefix_data)
|
|
||||||
{
|
|
||||||
// TODO: propagate tl::expected mechanism
|
|
||||||
throw std::runtime_error(exp_prefix_data.error().what());
|
|
||||||
}
|
|
||||||
PrefixData& prefix_data = exp_prefix_data.value();
|
|
||||||
MRepo(pool, prefix_data);
|
|
||||||
if (format != QueryResultFormat::kJSON)
|
|
||||||
{
|
|
||||||
Console::stream() << "Loaded current active prefix: "
|
|
||||||
<< ctx.prefix_params.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)
|
|
||||||
{
|
|
||||||
throw std::runtime_error(exp_load.error().what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Query q(pool);
|
Query q(pool);
|
||||||
if (type == QueryType::kSEARCH)
|
|
||||||
|
if (type == QueryType::Search)
|
||||||
{
|
{
|
||||||
if (ctx.output_params.json)
|
if (ctx.output_params.json)
|
||||||
{
|
{
|
||||||
std::cout << q.find(query).groupby("name").json(pool.channel_context()).dump(4);
|
std::cout << q.find(queries).groupby("name").json().dump(4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "\n" << std::endl;
|
std::cout << "\n" << std::endl;
|
||||||
auto res = q.find(query);
|
auto res = q.find(queries);
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case QueryResultFormat::kJSON:
|
case QueryResultFormat::Json:
|
||||||
std::cout << res.json(pool.channel_context()).dump(4);
|
std::cout << res.json().dump(4);
|
||||||
break;
|
break;
|
||||||
case QueryResultFormat::kPRETTY:
|
case QueryResultFormat::Pretty:
|
||||||
res.pretty(std::cout, ctx.output_params);
|
res.pretty(std::cout, ctx.output_params);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -99,49 +113,57 @@ namespace mamba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == QueryType::kDEPENDS)
|
else if (type == QueryType::Depends)
|
||||||
{
|
{
|
||||||
|
if (queries.size() != 1)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Only one query supported for 'depends'.");
|
||||||
|
}
|
||||||
auto res = q.depends(
|
auto res = q.depends(
|
||||||
query,
|
queries.front(),
|
||||||
format == QueryResultFormat::kTREE || format == QueryResultFormat::kRECURSIVETABLE
|
format == QueryResultFormat::Tree || format == QueryResultFormat::RecursiveTable
|
||||||
);
|
);
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case QueryResultFormat::kTREE:
|
case QueryResultFormat::Tree:
|
||||||
case QueryResultFormat::kPRETTY:
|
case QueryResultFormat::Pretty:
|
||||||
res.tree(std::cout, config.context().graphics_params);
|
res.tree(std::cout, config.context().graphics_params);
|
||||||
break;
|
break;
|
||||||
case QueryResultFormat::kJSON:
|
case QueryResultFormat::Json:
|
||||||
std::cout << res.json(pool.channel_context()).dump(4);
|
std::cout << res.json().dump(4);
|
||||||
break;
|
break;
|
||||||
case QueryResultFormat::kTABLE:
|
case QueryResultFormat::Table:
|
||||||
case QueryResultFormat::kRECURSIVETABLE:
|
case QueryResultFormat::RecursiveTable:
|
||||||
res.sort("name").table(std::cout);
|
res.sort("name").table(std::cout);
|
||||||
}
|
}
|
||||||
if (res.empty() && format != QueryResultFormat::kJSON)
|
if (res.empty() && format != QueryResultFormat::Json)
|
||||||
{
|
{
|
||||||
std::cout << query
|
std::cout << queries.front(
|
||||||
<< " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery"
|
) << " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == QueryType::kWHONEEDS)
|
else if (type == QueryType::WhoNeeds)
|
||||||
{
|
{
|
||||||
|
if (queries.size() != 1)
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("Only one query supported for 'whoneeds'.");
|
||||||
|
}
|
||||||
auto res = q.whoneeds(
|
auto res = q.whoneeds(
|
||||||
query,
|
queries.front(),
|
||||||
format == QueryResultFormat::kTREE || format == QueryResultFormat::kRECURSIVETABLE
|
format == QueryResultFormat::Tree || format == QueryResultFormat::RecursiveTable
|
||||||
);
|
);
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case QueryResultFormat::kTREE:
|
case QueryResultFormat::Tree:
|
||||||
case QueryResultFormat::kPRETTY:
|
case QueryResultFormat::Pretty:
|
||||||
res.tree(std::cout, config.context().graphics_params);
|
res.tree(std::cout, config.context().graphics_params);
|
||||||
break;
|
break;
|
||||||
case QueryResultFormat::kJSON:
|
case QueryResultFormat::Json:
|
||||||
std::cout << res.json(pool.channel_context()).dump(4);
|
std::cout << res.json().dump(4);
|
||||||
break;
|
break;
|
||||||
case QueryResultFormat::kTABLE:
|
case QueryResultFormat::Table:
|
||||||
case QueryResultFormat::kRECURSIVETABLE:
|
case QueryResultFormat::RecursiveTable:
|
||||||
res.sort("name").table(
|
res.sort("name").table(
|
||||||
std::cout,
|
std::cout,
|
||||||
{ "Name",
|
{ "Name",
|
||||||
|
@ -149,15 +171,15 @@ namespace mamba
|
||||||
"Build",
|
"Build",
|
||||||
printers::alignmentMarker(printers::alignment::left),
|
printers::alignmentMarker(printers::alignment::left),
|
||||||
printers::alignmentMarker(printers::alignment::right),
|
printers::alignmentMarker(printers::alignment::right),
|
||||||
util::concat("Depends:", query),
|
util::concat("Depends:", queries.front()),
|
||||||
"Channel",
|
"Channel",
|
||||||
"Subdir" }
|
"Subdir" }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (res.empty() && format != QueryResultFormat::kJSON)
|
if (res.empty() && format != QueryResultFormat::Json)
|
||||||
{
|
{
|
||||||
std::cout << query
|
std::cout << queries.front(
|
||||||
<< " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery"
|
) << " may not be installed. Try giving a channel with '-c,--channel' option for remote repoquery"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,17 @@
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
#include <solv/evr.h>
|
#include <solv/evr.h>
|
||||||
|
#include <solv/pool.h>
|
||||||
|
#include <solv/repo.h>
|
||||||
|
#include <solv/selection.h>
|
||||||
|
#include <solv/solver.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
extern "C" // Incomplete header
|
||||||
|
{
|
||||||
|
#include <solv/conda.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include "mamba/core/context.hpp"
|
#include "mamba/core/context.hpp"
|
||||||
#include "mamba/core/match_spec.hpp"
|
|
||||||
#include "mamba/core/output.hpp"
|
#include "mamba/core/output.hpp"
|
||||||
#include "mamba/core/package_info.hpp"
|
#include "mamba/core/package_info.hpp"
|
||||||
#include "mamba/core/query.hpp"
|
#include "mamba/core/query.hpp"
|
||||||
|
@ -347,16 +354,19 @@ namespace mamba
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result Query::find(const std::string& query) const
|
query_result Query::find(const std::vector<std::string>& queries) const
|
||||||
{
|
{
|
||||||
solv::ObjQueue job, solvables;
|
solv::ObjQueue job, solvables;
|
||||||
|
|
||||||
const Id id = pool_conda_matchspec(m_pool.get(), query.c_str());
|
for (const auto& query : queries)
|
||||||
if (!id)
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Could not generate query for " + query);
|
const Id id = pool_conda_matchspec(m_pool.get(), query.c_str());
|
||||||
|
if (!id)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Could not generate query for " + query);
|
||||||
|
}
|
||||||
|
job.push_back(SOLVER_SOLVABLE_PROVIDES, id);
|
||||||
}
|
}
|
||||||
job.push_back(SOLVER_SOLVABLE_PROVIDES, id);
|
|
||||||
|
|
||||||
selection_solvables(m_pool.get(), job.raw(), solvables.raw());
|
selection_solvables(m_pool.get(), job.raw(), solvables.raw());
|
||||||
query_result::dependency_graph g;
|
query_result::dependency_graph g;
|
||||||
|
@ -382,7 +392,11 @@ namespace mamba
|
||||||
g.add_node(std::move(pkg_info).value());
|
g.add_node(std::move(pkg_info).value());
|
||||||
}
|
}
|
||||||
|
|
||||||
return query_result(QueryType::kSEARCH, query, std::move(g));
|
return query_result(
|
||||||
|
QueryType::Search,
|
||||||
|
fmt::format("{}", fmt::join(queries, " ")), // Yes this is disgusting
|
||||||
|
std::move(g)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result Query::whoneeds(const std::string& query, bool tree) const
|
query_result Query::whoneeds(const std::string& query, bool tree) const
|
||||||
|
@ -421,7 +435,7 @@ namespace mamba
|
||||||
g.add_node(std::move(pkg_info).value());
|
g.add_node(std::move(pkg_info).value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return query_result(QueryType::kWHONEEDS, query, std::move(g));
|
return query_result(QueryType::WhoNeeds, query, std::move(g));
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result Query::depends(const std::string& query, bool tree) const
|
query_result Query::depends(const std::string& query, bool tree) const
|
||||||
|
@ -466,7 +480,29 @@ namespace mamba
|
||||||
walk_graph(m_pool, g, node_id, latest, visited, not_found, depth);
|
walk_graph(m_pool, g, node_id, latest, visited, not_found, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query_result(QueryType::kDEPENDS, query, std::move(g));
|
return query_result(QueryType::Depends, query, std::move(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
* QueryType implementation *
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
auto QueryType_from_name(std::string_view name) -> QueryType
|
||||||
|
{
|
||||||
|
auto l_name = util::to_lower(name);
|
||||||
|
if (l_name == "search")
|
||||||
|
{
|
||||||
|
return QueryType::Search;
|
||||||
|
}
|
||||||
|
if (l_name == "depends")
|
||||||
|
{
|
||||||
|
return QueryType::Depends;
|
||||||
|
}
|
||||||
|
if (l_name == "whoneeds")
|
||||||
|
{
|
||||||
|
return QueryType::WhoNeeds;
|
||||||
|
}
|
||||||
|
throw std::invalid_argument(fmt::format("Invalid enum name \"{}\"", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
|
@ -831,14 +867,11 @@ namespace mamba
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
nlohmann::json query_result::json(ChannelContext& channel_context) const
|
nlohmann::json query_result::json() const
|
||||||
{
|
{
|
||||||
nlohmann::json j;
|
nlohmann::json j;
|
||||||
std::string query_type = m_type == QueryType::kSEARCH
|
std::string query_type = std::string(util::to_lower(enum_name(m_type)));
|
||||||
? "search"
|
j["query"] = { { "query", m_query }, { "type", query_type } };
|
||||||
: (m_type == QueryType::kDEPENDS ? "depends" : "whoneeds");
|
|
||||||
j["query"] = { { "query", MatchSpec{ m_query, channel_context }.conda_build_form() },
|
|
||||||
{ "type", query_type } };
|
|
||||||
|
|
||||||
std::string msg = m_pkg_id_list.empty() ? "No entries matching \"" + m_query + "\" found"
|
std::string msg = m_pkg_id_list.empty() ? "No entries matching \"" + m_query + "\" found"
|
||||||
: "";
|
: "";
|
||||||
|
@ -857,7 +890,7 @@ namespace mamba
|
||||||
j["result"]["pkgs"].push_back(std::move(pkg_info_json));
|
j["result"]["pkgs"].push_back(std::move(pkg_info_json));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type != QueryType::kSEARCH && !m_pkg_id_list.empty())
|
if (m_type != QueryType::Search && !m_pkg_id_list.empty())
|
||||||
{
|
{
|
||||||
j["result"]["graph_roots"] = nlohmann::json::array();
|
j["result"]["graph_roots"] = nlohmann::json::array();
|
||||||
if (!m_dep_graph.successors(0).empty())
|
if (!m_dep_graph.successors(0).empty())
|
||||||
|
|
|
@ -328,7 +328,9 @@ namespace mamba::specs
|
||||||
(strip_scheme == StripScheme::no) ? "://" : "",
|
(strip_scheme == StripScheme::no) ? "://" : "",
|
||||||
user(Decode::yes),
|
user(Decode::yes),
|
||||||
password(Decode::no).empty() ? "" : ":",
|
password(Decode::no).empty() ? "" : ":",
|
||||||
(hide_confifential == HideConfidential::no) ? password(Decode::yes) : "*****",
|
password(Decode::no).empty()
|
||||||
|
? ""
|
||||||
|
: ((hide_confifential == HideConfidential::no) ? password(Decode::yes) : "*****"),
|
||||||
user(Decode::no).empty() ? "" : "@",
|
user(Decode::no).empty() ? "" : "@",
|
||||||
host(Decode::yes),
|
host(Decode::yes),
|
||||||
port().empty() ? "" : ":",
|
port().empty() ? "" : ":",
|
||||||
|
|
|
@ -509,7 +509,9 @@ namespace mamba::util
|
||||||
(strip_scheme == StripScheme::no) ? "://" : "",
|
(strip_scheme == StripScheme::no) ? "://" : "",
|
||||||
user(Decode::yes),
|
user(Decode::yes),
|
||||||
m_password.empty() ? "" : ":",
|
m_password.empty() ? "" : ":",
|
||||||
(hide_confidential == HideConfidential::no) ? password(Decode::yes) : "*****",
|
password(Decode::no).empty()
|
||||||
|
? ""
|
||||||
|
: ((hide_confidential == HideConfidential::no) ? password(Decode::yes) : "*****"),
|
||||||
m_user.empty() ? "" : "@",
|
m_user.empty() ? "" : "@",
|
||||||
host(Decode::yes),
|
host(Decode::yes),
|
||||||
m_port.empty() ? "" : ":",
|
m_port.empty() ? "" : ":",
|
||||||
|
|
|
@ -1235,7 +1235,10 @@ class ProblemsGraph:
|
||||||
class Query:
|
class Query:
|
||||||
def __init__(self, arg0: Pool) -> None: ...
|
def __init__(self, arg0: Pool) -> None: ...
|
||||||
def depends(self, arg0: str, arg1: QueryFormat) -> str: ...
|
def depends(self, arg0: str, arg1: QueryFormat) -> str: ...
|
||||||
|
@typing.overload
|
||||||
def find(self, arg0: str, arg1: QueryFormat) -> str: ...
|
def find(self, arg0: str, arg1: QueryFormat) -> str: ...
|
||||||
|
@typing.overload
|
||||||
|
def find(self, arg0: typing.List[str], arg1: QueryFormat) -> str: ...
|
||||||
def whoneeds(self, arg0: str, arg1: QueryFormat) -> str: ...
|
def whoneeds(self, arg0: str, arg1: QueryFormat) -> str: ...
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -510,39 +510,41 @@ PYBIND11_MODULE(bindings, m)
|
||||||
.value("PRETTY", query::RESULT_FORMAT::PRETTY)
|
.value("PRETTY", query::RESULT_FORMAT::PRETTY)
|
||||||
.value("RECURSIVETABLE", query::RESULT_FORMAT::RECURSIVETABLE);
|
.value("RECURSIVETABLE", query::RESULT_FORMAT::RECURSIVETABLE);
|
||||||
|
|
||||||
|
auto queries_find = [](const Query& q,
|
||||||
|
const std::vector<std::string>& queries,
|
||||||
|
const query::RESULT_FORMAT format) -> std::string
|
||||||
|
{
|
||||||
|
query_result res = q.find(queries);
|
||||||
|
std::stringstream res_stream;
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case query::JSON:
|
||||||
|
res_stream << res.groupby("name").json().dump(4);
|
||||||
|
break;
|
||||||
|
case query::TREE:
|
||||||
|
case query::TABLE:
|
||||||
|
case query::RECURSIVETABLE:
|
||||||
|
res.groupby("name").table(res_stream);
|
||||||
|
break;
|
||||||
|
case query::PRETTY:
|
||||||
|
res.groupby("name").pretty(res_stream, mambapy::singletons.context().output_params);
|
||||||
|
}
|
||||||
|
if (res.empty() && format != query::JSON)
|
||||||
|
{
|
||||||
|
res_stream << fmt::format("{}", fmt::join(queries, " "))
|
||||||
|
<< " may not be installed. Try specifying a channel with '-c,--channel' option\n";
|
||||||
|
}
|
||||||
|
return res_stream.str();
|
||||||
|
};
|
||||||
|
|
||||||
py::class_<Query>(m, "Query")
|
py::class_<Query>(m, "Query")
|
||||||
.def(py::init<MPool&>())
|
.def(py::init<MPool&>())
|
||||||
.def(
|
.def(
|
||||||
"find",
|
"find",
|
||||||
[](const Query& q, const std::string& query, const query::RESULT_FORMAT format) -> std::string
|
[queries_find](const Query& q, const std::string& query, const query::RESULT_FORMAT format)
|
||||||
{
|
-> std::string { return queries_find(q, { query }, format); }
|
||||||
query_result res = q.find(query);
|
|
||||||
std::stringstream res_stream;
|
|
||||||
switch (format)
|
|
||||||
{
|
|
||||||
case query::JSON:
|
|
||||||
res_stream
|
|
||||||
<< res.groupby("name").json(mambapy::singletons.channel_context()).dump(4);
|
|
||||||
break;
|
|
||||||
case query::TREE:
|
|
||||||
case query::TABLE:
|
|
||||||
case query::RECURSIVETABLE:
|
|
||||||
res.groupby("name").table(res_stream);
|
|
||||||
break;
|
|
||||||
case query::PRETTY:
|
|
||||||
res.groupby("name").pretty(
|
|
||||||
res_stream,
|
|
||||||
mambapy::singletons.context().output_params
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (res.empty() && format != query::JSON)
|
|
||||||
{
|
|
||||||
res_stream << query
|
|
||||||
<< " may not be installed. Try specifying a channel with '-c,--channel' option\n";
|
|
||||||
}
|
|
||||||
return res_stream.str();
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
.def("find", queries_find)
|
||||||
.def(
|
.def(
|
||||||
"whoneeds",
|
"whoneeds",
|
||||||
[](const Query& q, const std::string& query, const query::RESULT_FORMAT format) -> std::string
|
[](const Query& q, const std::string& query, const query::RESULT_FORMAT format) -> std::string
|
||||||
|
@ -557,7 +559,7 @@ PYBIND11_MODULE(bindings, m)
|
||||||
res.tree(res_stream, mambapy::singletons.context().graphics_params);
|
res.tree(res_stream, mambapy::singletons.context().graphics_params);
|
||||||
break;
|
break;
|
||||||
case query::JSON:
|
case query::JSON:
|
||||||
res_stream << res.json(mambapy::singletons.channel_context()).dump(4);
|
res_stream << res.json().dump(4);
|
||||||
break;
|
break;
|
||||||
case query::TABLE:
|
case query::TABLE:
|
||||||
case query::RECURSIVETABLE:
|
case query::RECURSIVETABLE:
|
||||||
|
@ -597,7 +599,7 @@ PYBIND11_MODULE(bindings, m)
|
||||||
res.tree(res_stream, mambapy::singletons.context().graphics_params);
|
res.tree(res_stream, mambapy::singletons.context().graphics_params);
|
||||||
break;
|
break;
|
||||||
case query::JSON:
|
case query::JSON:
|
||||||
res_stream << res.json(mambapy::singletons.channel_context()).dump(4);
|
res_stream << res.json().dump(4);
|
||||||
break;
|
break;
|
||||||
case query::TABLE:
|
case query::TABLE:
|
||||||
case query::RECURSIVETABLE:
|
case query::RECURSIVETABLE:
|
||||||
|
|
|
@ -9,24 +9,6 @@
|
||||||
|
|
||||||
#include "common_options.hpp"
|
#include "common_options.hpp"
|
||||||
|
|
||||||
mamba::QueryType
|
|
||||||
str_to_qtype(const std::string& s)
|
|
||||||
{
|
|
||||||
if (s == "search")
|
|
||||||
{
|
|
||||||
return mamba::QueryType::kSEARCH;
|
|
||||||
}
|
|
||||||
if (s == "depends")
|
|
||||||
{
|
|
||||||
return mamba::QueryType::kDEPENDS;
|
|
||||||
}
|
|
||||||
if (s == "whoneeds")
|
|
||||||
{
|
|
||||||
return mamba::QueryType::kWHONEEDS;
|
|
||||||
}
|
|
||||||
throw std::runtime_error("Could not parse query type");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
set_common_search(CLI::App* subcom, mamba::Configuration& config, bool is_repoquery)
|
set_common_search(CLI::App* subcom, mamba::Configuration& config, bool is_repoquery)
|
||||||
{
|
{
|
||||||
|
@ -75,55 +57,59 @@ set_common_search(CLI::App* subcom, mamba::Configuration& config, bool is_repoqu
|
||||||
auto& platform = config.at("platform");
|
auto& platform = config.at("platform");
|
||||||
subcom->add_option("--platform", platform.get_cli_config<std::string>(), platform.description());
|
subcom->add_option("--platform", platform.get_cli_config<std::string>(), platform.description());
|
||||||
|
|
||||||
|
auto specs_has_wildcard = [](auto first, auto last) -> bool
|
||||||
|
{
|
||||||
|
auto has_wildcard = [](std::string_view spec) -> bool
|
||||||
|
{ return spec.find('*') != std::string_view::npos; };
|
||||||
|
return std::any_of(first, last, has_wildcard);
|
||||||
|
};
|
||||||
|
|
||||||
subcom->callback(
|
subcom->callback(
|
||||||
[&]
|
[&]
|
||||||
{
|
{
|
||||||
using namespace mamba;
|
using namespace mamba;
|
||||||
|
|
||||||
auto qtype = str_to_qtype(query_type);
|
auto qtype = QueryType_from_name(query_type);
|
||||||
QueryResultFormat format = QueryResultFormat::kTABLE;
|
QueryResultFormat format = QueryResultFormat::Table;
|
||||||
bool use_local = true;
|
bool use_local = true;
|
||||||
switch (qtype)
|
switch (qtype)
|
||||||
{
|
{
|
||||||
case QueryType::kSEARCH:
|
case QueryType::Search:
|
||||||
format = QueryResultFormat::kTABLE;
|
format = QueryResultFormat::Table;
|
||||||
use_local = local > 0; // use remote repodata by default for `search`
|
use_local = local > 0; // use remote repodata by default for `search`
|
||||||
break;
|
break;
|
||||||
case QueryType::kDEPENDS:
|
case QueryType::Depends:
|
||||||
format = QueryResultFormat::kTABLE;
|
case QueryType::WhoNeeds:
|
||||||
use_local = (local == -1) || (local > 0);
|
format = QueryResultFormat::Table;
|
||||||
break;
|
|
||||||
case QueryType::kWHONEEDS:
|
|
||||||
format = QueryResultFormat::kTABLE;
|
|
||||||
use_local = (local == -1) || (local > 0);
|
use_local = (local == -1) || (local > 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (qtype == QueryType::kDEPENDS && recursive)
|
if (qtype == QueryType::Depends && recursive)
|
||||||
{
|
{
|
||||||
format = QueryResultFormat::kRECURSIVETABLE;
|
format = QueryResultFormat::RecursiveTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == QueryType::kDEPENDS && show_as_tree)
|
if (qtype == QueryType::Depends && show_as_tree)
|
||||||
{
|
{
|
||||||
format = QueryResultFormat::kTREE;
|
format = QueryResultFormat::Tree;
|
||||||
}
|
}
|
||||||
// Best guess to detect wildcard search; if there's no wildcard search, we want to show
|
// Best guess to detect wildcard search; if there's no wildcard search, we want to show
|
||||||
// the pretty single package view.
|
// the pretty single package view.
|
||||||
if (qtype == QueryType::kSEARCH
|
if (qtype == QueryType::Search
|
||||||
&& (pretty_print || specs[0].find("*") == std::string::npos))
|
&& (pretty_print || specs_has_wildcard(specs.cbegin(), specs.cend())))
|
||||||
{
|
{
|
||||||
format = QueryResultFormat::kPRETTY;
|
format = QueryResultFormat::Pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.at("json").compute().value<bool>())
|
if (config.at("json").compute().value<bool>())
|
||||||
{
|
{
|
||||||
format = QueryResultFormat::kJSON;
|
format = QueryResultFormat::Json;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& channels = config.at("channels").compute().value<std::vector<std::string>>();
|
auto& channels = config.at("channels").compute().value<std::vector<std::string>>();
|
||||||
use_local = use_local && channels.empty();
|
use_local = use_local && channels.empty();
|
||||||
|
|
||||||
repoquery(config, qtype, format, use_local, specs[0]);
|
repoquery(config, qtype, format, use_local, specs);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ def yaml_env(tmp_prefix: Path) -> None:
|
||||||
def test_depends(yaml_env: Path):
|
def test_depends(yaml_env: Path):
|
||||||
res = helpers.umamba_repoquery("depends", "yaml=0.2.5", "--json")
|
res = helpers.umamba_repoquery("depends", "yaml=0.2.5", "--json")
|
||||||
|
|
||||||
assert res["query"]["query"] == "yaml =0.2.5*"
|
assert res["query"]["query"] == "yaml=0.2.5"
|
||||||
assert res["query"]["type"] == "depends"
|
assert res["query"]["type"] == "depends"
|
||||||
|
|
||||||
pkgs = res["result"]["pkgs"]
|
pkgs = res["result"]["pkgs"]
|
||||||
|
@ -67,7 +67,7 @@ def test_depends_not_installed_with_channel(yaml_env: Path, with_platform):
|
||||||
"depends", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
"depends", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert res["query"]["query"] == "xtensor =0.24.5*"
|
assert res["query"]["query"] == "xtensor=0.24.5"
|
||||||
assert res["query"]["type"] == "depends"
|
assert res["query"]["type"] == "depends"
|
||||||
assert "conda-forge" in res["result"]["graph_roots"][0]["channel"]
|
assert "conda-forge" in res["result"]["graph_roots"][0]["channel"]
|
||||||
assert res["result"]["graph_roots"][0]["name"] == "xtensor"
|
assert res["result"]["graph_roots"][0]["name"] == "xtensor"
|
||||||
|
@ -155,7 +155,7 @@ def test_whoneeds_not_installed_with_channel(yaml_env: Path, with_platform):
|
||||||
"whoneeds", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
"whoneeds", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert res["query"]["query"] == "xtensor =0.24.5*"
|
assert res["query"]["query"] == "xtensor=0.24.5"
|
||||||
assert res["query"]["type"] == "whoneeds"
|
assert res["query"]["type"] == "whoneeds"
|
||||||
|
|
||||||
pkgs = res["result"]["pkgs"]
|
pkgs = res["result"]["pkgs"]
|
||||||
|
@ -233,7 +233,7 @@ def test_remote_search_not_installed_pkg(yaml_env: Path):
|
||||||
"search", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
"search", "-c", "conda-forge", "xtensor=0.24.5", "--json"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert res["query"]["query"] == "xtensor =0.24.5*"
|
assert res["query"]["query"] == "xtensor=0.24.5"
|
||||||
assert res["query"]["type"] == "search"
|
assert res["query"]["type"] == "search"
|
||||||
assert "conda-forge" in res["result"]["pkgs"][0]["channel"]
|
assert "conda-forge" in res["result"]["pkgs"][0]["channel"]
|
||||||
assert res["result"]["pkgs"][0]["name"] == "xtensor"
|
assert res["result"]["pkgs"][0]["name"] == "xtensor"
|
||||||
|
|
Loading…
Reference in New Issue