mirror of https://github.com/mamba-org/mamba.git
Migrate Channel::make_channel to resolve multi channels (#2986)
* Add one to many get_channels * Refactor ChannelContext params * ChannelContext::make_channel migration 1 * ChannelContext::make_channel migration 2 * ChannelContext::make_channel migration 3 * ChannelContext::make_channel migration 4 * ChannelContext::make_channel migration 5 * ChannelContext::make_channel migration 6 * ChannelContext::make_channel migration 7 * Remove Channel bindings * Remove ChannelContext::make_channel * ChannelContext::get_channels migration 1 * ChannelContext::get_channels migration 2 * ChannelContext::get_channels migration 3 * Remove get_channels bindings * Remove ChannelContext::get_channels * Channel::resolve return a list * Resolve multi_channel in Channel::resolve * Use weakening map for multi_channels * Split Channel resolve_name * Cleanup signatures * Add Channel::clear_xxx * Force removal of trailing '/' in Channel * Add weak channel comparison * Use better channel comparisons * Remove Channel::base_url * Rename Channel::make_chan > make_channel * Add doc * Resolve Channel paths from params * Review from JohanMabille * Fix absolute path
This commit is contained in:
parent
0177c44383
commit
e874e7ea71
|
@ -55,40 +55,55 @@ namespace mamba
|
|||
-> std::optional<std::string_view>;
|
||||
};
|
||||
|
||||
template <typename Key, typename Value>
|
||||
using name_map = util::weakening_map<std::unordered_map<Key, Value>, NameWeakener>;
|
||||
|
||||
using platform_list = util::flat_set<std::string>;
|
||||
using channel_list = std::vector<Channel>;
|
||||
using channel_map = util::weakening_map<std::unordered_map<std::string, Channel>, NameWeakener>;
|
||||
using multichannel_map = std::unordered_map<std::string, channel_list>;
|
||||
using channel_map = name_map<std::string, Channel>;
|
||||
using multichannel_map = name_map<std::string, channel_list>;
|
||||
|
||||
const platform_list& platforms;
|
||||
const specs::CondaURL& channel_alias;
|
||||
const channel_map& custom_channels;
|
||||
const specs::AuthenticationDataBase& auth_db;
|
||||
|
||||
// TODO add CWD and home
|
||||
const multichannel_map& custom_multichannels;
|
||||
const specs::AuthenticationDataBase& authentication_db;
|
||||
std::string_view home_dir;
|
||||
std::string_view current_working_dir;
|
||||
};
|
||||
|
||||
using platform_list = util::flat_set<std::string>;
|
||||
using platform_list = ResolveParams::platform_list;
|
||||
using channel_list = ResolveParams::channel_list;
|
||||
|
||||
[[nodiscard]] static auto resolve(specs::ChannelSpec spec, ResolveParams params) -> Channel;
|
||||
[[nodiscard]] static auto resolve(specs::ChannelSpec spec, ResolveParams params)
|
||||
-> channel_list;
|
||||
|
||||
Channel(specs::CondaURL url, std::string display_name, util::flat_set<std::string> platforms = {});
|
||||
|
||||
[[nodiscard]] auto url() const -> const specs::CondaURL&;
|
||||
auto clear_url() -> const specs::CondaURL;
|
||||
void set_url(specs::CondaURL url);
|
||||
|
||||
[[nodiscard]] auto platforms() const -> const platform_list&;
|
||||
auto clear_platforms() -> platform_list;
|
||||
void set_platforms(platform_list platforms);
|
||||
|
||||
[[nodiscard]] auto display_name() const -> const std::string&;
|
||||
auto clear_display_name() -> std::string;
|
||||
void set_display_name(std::string display_name);
|
||||
|
||||
std::string base_url() const;
|
||||
std::string platform_url(std::string_view platform, bool with_credential = true) const;
|
||||
[[nodiscard]] auto url_equivalent_with(const Channel& other) const -> bool;
|
||||
|
||||
[[nodiscard]] auto is_equivalent_to(const Channel& other) const -> bool;
|
||||
|
||||
[[nodiscard]] auto contains_equivalent(const Channel& other) const -> bool;
|
||||
|
||||
[[nodiscard]] auto
|
||||
platform_url(std::string_view platform, bool with_credential = true) const -> std::string;
|
||||
// The pairs consist of (platform,url)
|
||||
util::flat_set<std::pair<std::string, std::string>>
|
||||
platform_urls(bool with_credential = true) const;
|
||||
util::flat_set<std::string> urls(bool with_credential = true) const;
|
||||
[[nodiscard]] auto platform_urls(bool with_credential = true) const
|
||||
-> util::flat_set<std::pair<std::string, std::string>>;
|
||||
[[nodiscard]] auto urls(bool with_credential = true) const -> util::flat_set<std::string>;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -118,40 +133,42 @@ namespace mamba
|
|||
|
||||
using channel_map = Channel::ResolveParams::channel_map;
|
||||
using channel_list = Channel::ResolveParams::channel_list;
|
||||
using multichannel_map = Channel::ResolveParams::multichannel_map;
|
||||
using platform_list = Channel::ResolveParams::platform_list;
|
||||
using multichannel_map = std::unordered_map<std::string, channel_list>;
|
||||
|
||||
ChannelContext(Context& context);
|
||||
~ChannelContext();
|
||||
|
||||
ChannelContext(const ChannelContext&) = delete;
|
||||
ChannelContext& operator=(const ChannelContext&) = delete;
|
||||
auto operator=(const ChannelContext&) -> ChannelContext& = delete;
|
||||
ChannelContext(ChannelContext&&) = delete;
|
||||
ChannelContext& operator=(ChannelContext&&) = delete;
|
||||
auto operator=(ChannelContext&&) -> ChannelContext& = delete;
|
||||
|
||||
const Channel& make_channel(const std::string& value);
|
||||
auto get_channels(const std::vector<std::string>& channel_names) -> channel_list;
|
||||
auto make_channel(std::string_view name) -> channel_list;
|
||||
|
||||
const specs::CondaURL& get_channel_alias() const;
|
||||
const channel_map& get_custom_channels() const;
|
||||
const multichannel_map& get_custom_multichannels() const;
|
||||
auto get_channel_alias() const -> const specs::CondaURL&;
|
||||
auto get_custom_channels() const -> const channel_map&;
|
||||
auto get_custom_multichannels() const -> const multichannel_map&;
|
||||
|
||||
Context& context() const
|
||||
auto context() const -> Context&
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
using ChannelCache = std::map<std::string, Channel>;
|
||||
using ChannelCache = std::unordered_map<std::string, channel_list>;
|
||||
|
||||
Context& m_context;
|
||||
ChannelCache m_channel_cache;
|
||||
specs::CondaURL m_channel_alias;
|
||||
platform_list m_platforms;
|
||||
channel_map m_custom_channels;
|
||||
multichannel_map m_custom_multichannels;
|
||||
platform_list m_platforms;
|
||||
std::string m_home_dir;
|
||||
std::string m_current_working_dir;
|
||||
|
||||
auto params() -> Channel::ResolveParams;
|
||||
void init_custom_channels();
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,16 @@
|
|||
|
||||
namespace mamba::util
|
||||
{
|
||||
/**
|
||||
* Lightweight file path manipulation.
|
||||
*
|
||||
* The purpose of this file is to provide a lightweight functions for manipulating paths
|
||||
* for things that manipulate "path-like" objects, such as parsers and URLs.
|
||||
* In general, users should prefer using the correct abstraction, such as @ref URL
|
||||
* and @ref u8path.
|
||||
* However some features provided here, such as @ref expand_home, are not available elsewhere.
|
||||
*/
|
||||
|
||||
inline static constexpr char preferred_path_separator_posix = '/';
|
||||
inline static constexpr char preferred_path_separator_win = '\\';
|
||||
|
||||
|
|
|
@ -51,50 +51,51 @@ namespace mamba
|
|||
|
||||
auto& ctx = pool.context();
|
||||
|
||||
std::vector<std::string> channel_urls = ctx.channels;
|
||||
|
||||
std::vector<MSubdirData> subdirs;
|
||||
|
||||
std::vector<std::pair<int, int>> priorities;
|
||||
int max_prio = static_cast<int>(channel_urls.size());
|
||||
int max_prio = static_cast<int>(ctx.channels.size());
|
||||
auto prev_channel_url = specs::CondaURL();
|
||||
|
||||
Console::instance().init_progress_bar_manager(ProgressBarMode::multi);
|
||||
|
||||
std::vector<mamba_error> error_list;
|
||||
|
||||
for (auto channel : pool.channel_context().get_channels(channel_urls))
|
||||
for (const auto& location : ctx.channels)
|
||||
{
|
||||
for (auto& [platform, url] : channel.platform_urls(true))
|
||||
for (auto channel : pool.channel_context().make_channel(location))
|
||||
{
|
||||
auto sdires = MSubdirData::create(
|
||||
pool.channel_context(),
|
||||
channel,
|
||||
platform,
|
||||
url,
|
||||
package_caches,
|
||||
"repodata.json"
|
||||
);
|
||||
if (!sdires.has_value())
|
||||
for (auto& [platform, url] : channel.platform_urls(true))
|
||||
{
|
||||
error_list.push_back(std::move(sdires).error());
|
||||
continue;
|
||||
}
|
||||
auto sdir = std::move(sdires).value();
|
||||
subdirs.push_back(std::move(sdir));
|
||||
if (ctx.channel_priority == ChannelPriority::Disabled)
|
||||
{
|
||||
priorities.push_back(std::make_pair(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Consider 'flexible' and 'strict' the same way
|
||||
if (channel.url() != prev_channel_url)
|
||||
auto sdires = MSubdirData::create(
|
||||
pool.channel_context(),
|
||||
channel,
|
||||
platform,
|
||||
url,
|
||||
package_caches,
|
||||
"repodata.json"
|
||||
);
|
||||
if (!sdires.has_value())
|
||||
{
|
||||
max_prio--;
|
||||
prev_channel_url = channel.url();
|
||||
error_list.push_back(std::move(sdires).error());
|
||||
continue;
|
||||
}
|
||||
auto sdir = std::move(sdires).value();
|
||||
subdirs.push_back(std::move(sdir));
|
||||
if (ctx.channel_priority == ChannelPriority::Disabled)
|
||||
{
|
||||
priorities.push_back(std::make_pair(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Consider 'flexible' and 'strict' the same way
|
||||
if (channel.url() != prev_channel_url)
|
||||
{
|
||||
max_prio--;
|
||||
prev_channel_url = channel.url();
|
||||
}
|
||||
priorities.push_back(std::make_pair(max_prio, 0));
|
||||
}
|
||||
priorities.push_back(std::make_pair(max_prio, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,16 +160,17 @@ namespace mamba
|
|||
}
|
||||
items.push_back({ "virtual packages", virtual_pkgs });
|
||||
|
||||
std::vector<std::string> channels = ctx.channels;
|
||||
// Always append context channels
|
||||
auto& ctx_channels = ctx.channels;
|
||||
std::copy(ctx_channels.begin(), ctx_channels.end(), std::back_inserter(channels));
|
||||
std::vector<std::string> channel_urls;
|
||||
for (auto channel : channel_context.get_channels(channels))
|
||||
channel_urls.reserve(ctx.channels.size() * 2); // Lower bound * (platform + noarch)
|
||||
for (const auto& loc : ctx.channels)
|
||||
{
|
||||
for (auto url : channel.urls(true))
|
||||
for (auto channel : channel_context.make_channel(loc))
|
||||
{
|
||||
channel_urls.push_back(url);
|
||||
for (auto url : channel.urls(true))
|
||||
{
|
||||
channel_urls.push_back(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
items.push_back({ "channels", channel_urls });
|
||||
|
|
|
@ -73,11 +73,13 @@ namespace mamba
|
|||
|
||||
if (regex.empty() || std::regex_search(pkg_info.name, spec_pat))
|
||||
{
|
||||
auto& channel = channel_context.make_channel(pkg_info.url);
|
||||
obj["base_url"] = channel.base_url();
|
||||
auto channels = channel_context.make_channel(pkg_info.url);
|
||||
assert(channels.size() == 1); // A URL can only resolve to one channel
|
||||
obj["base_url"] = channels.front().url().str(specs::CondaURL::Credentials::Remove
|
||||
);
|
||||
obj["build_number"] = pkg_info.build_number;
|
||||
obj["build_string"] = pkg_info.build_string;
|
||||
obj["channel"] = channel.display_name();
|
||||
obj["channel"] = channels.front().display_name();
|
||||
obj["dist_name"] = pkg_info.str();
|
||||
obj["name"] = pkg_info.name;
|
||||
obj["platform"] = pkg_info.subdir;
|
||||
|
@ -111,8 +113,9 @@ namespace mamba
|
|||
}
|
||||
else
|
||||
{
|
||||
const Channel& channel = channel_context.make_channel(package.second.url);
|
||||
formatted_pkgs.channel = channel.display_name();
|
||||
auto channels = channel_context.make_channel(package.second.url);
|
||||
assert(channels.size() == 1); // A URL can only resolve to one channel
|
||||
formatted_pkgs.channel = channels.front().display_name();
|
||||
}
|
||||
packages.push_back(formatted_pkgs);
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include "mamba/core/channel.hpp"
|
||||
#include "mamba/core/context.hpp"
|
||||
#include "mamba/specs/channel_spec.hpp"
|
||||
#include "mamba/specs/conda_url.hpp"
|
||||
#include "mamba/util/environment.hpp"
|
||||
#include "mamba/util/path_manip.hpp"
|
||||
#include "mamba/util/string.hpp"
|
||||
#include "mamba/util/tuple_hash.hpp"
|
||||
|
@ -22,9 +22,9 @@
|
|||
|
||||
namespace mamba
|
||||
{
|
||||
/********************************
|
||||
* NameWeakener Implmentation *
|
||||
********************************/
|
||||
/*********************************
|
||||
* NameWeakener Implementation *
|
||||
*********************************/
|
||||
|
||||
auto Channel::ResolveParams::NameWeakener::make_first_key(std::string_view key) const
|
||||
-> std::string_view
|
||||
|
@ -47,6 +47,9 @@ namespace mamba
|
|||
, m_display_name(std::move(display_name))
|
||||
, m_platforms(std::move(platforms))
|
||||
{
|
||||
auto p = m_url.clear_path();
|
||||
p = util::rstrip(p, '/');
|
||||
m_url.set_path(std::move(p));
|
||||
}
|
||||
|
||||
auto Channel::url() const -> const specs::CondaURL&
|
||||
|
@ -54,6 +57,11 @@ namespace mamba
|
|||
return m_url;
|
||||
}
|
||||
|
||||
auto Channel::clear_url() -> const specs::CondaURL
|
||||
{
|
||||
return std::exchange(m_url, {});
|
||||
}
|
||||
|
||||
void Channel::set_url(specs::CondaURL url)
|
||||
{
|
||||
m_url = std::move(url);
|
||||
|
@ -64,6 +72,11 @@ namespace mamba
|
|||
return m_platforms;
|
||||
}
|
||||
|
||||
auto Channel::clear_platforms() -> platform_list
|
||||
{
|
||||
return std::exchange(m_platforms, {});
|
||||
}
|
||||
|
||||
void Channel::set_platforms(platform_list platforms)
|
||||
{
|
||||
m_platforms = std::move(platforms);
|
||||
|
@ -74,17 +87,41 @@ namespace mamba
|
|||
return m_display_name;
|
||||
}
|
||||
|
||||
auto Channel::clear_display_name() -> std::string
|
||||
{
|
||||
return std::exchange(m_display_name, {});
|
||||
}
|
||||
|
||||
void Channel::set_display_name(std::string display_name)
|
||||
{
|
||||
m_display_name = std::move(display_name);
|
||||
}
|
||||
|
||||
std::string Channel::base_url() const
|
||||
auto Channel::url_equivalent_with(const Channel& other) const -> bool
|
||||
{
|
||||
return url().str(specs::CondaURL::Credentials::Remove);
|
||||
using Decode = typename specs::CondaURL::Decode;
|
||||
|
||||
const auto& this_url = url();
|
||||
const auto& other_url = other.url();
|
||||
// Not checking users, passwords, and tokens
|
||||
return
|
||||
// Schemes
|
||||
(this_url.scheme() == other_url.scheme())
|
||||
// Hosts
|
||||
&& (this_url.host(Decode::no) == other_url.host(Decode::no))
|
||||
// Different ports are considered different channels
|
||||
&& (this_url.port() == other_url.port())
|
||||
// Removing potential trailing '/'
|
||||
&& (util::rstrip(this_url.path_without_token(Decode::no), '/')
|
||||
== util::rstrip(other_url.path_without_token(Decode::no), '/'));
|
||||
}
|
||||
|
||||
util::flat_set<std::string> Channel::urls(bool with_credential) const
|
||||
auto Channel::contains_equivalent(const Channel& other) const -> bool
|
||||
{
|
||||
return url_equivalent_with(other) && util::set_is_superset_of(platforms(), other.platforms());
|
||||
}
|
||||
|
||||
auto Channel::urls(bool with_credential) const -> util::flat_set<std::string>
|
||||
{
|
||||
if (!url().package().empty())
|
||||
{
|
||||
|
@ -102,8 +139,8 @@ namespace mamba
|
|||
return out;
|
||||
}
|
||||
|
||||
util::flat_set<std::pair<std::string, std::string>>
|
||||
Channel::platform_urls(bool with_credential) const
|
||||
auto Channel::platform_urls(bool with_credential) const
|
||||
-> util::flat_set<std::pair<std::string, std::string>>
|
||||
{
|
||||
if (!url().package().empty())
|
||||
{
|
||||
|
@ -118,7 +155,7 @@ namespace mamba
|
|||
return out;
|
||||
}
|
||||
|
||||
std::string Channel::platform_url(std::string_view platform, bool with_credential) const
|
||||
auto Channel::platform_url(std::string_view platform, bool with_credential) const -> std::string
|
||||
{
|
||||
auto cred = with_credential ? specs::CondaURL::Credentials::Show
|
||||
: specs::CondaURL::Credentials::Remove;
|
||||
|
@ -256,9 +293,25 @@ namespace mamba
|
|||
return uri.pretty_str();
|
||||
}
|
||||
|
||||
auto resolve_path_location(std::string location, Channel::ResolveParams params) -> std::string
|
||||
{
|
||||
if (util::url_has_scheme(location))
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
const auto home = util::path_to_posix(std::string(params.home_dir));
|
||||
auto path = fs::u8path(util::expand_home(location, home));
|
||||
if (path.is_relative())
|
||||
{
|
||||
path = (fs::u8path(params.current_working_dir) / std::move(path)).lexically_normal();
|
||||
}
|
||||
return util::abs_path_to_url(std::move(path).string());
|
||||
}
|
||||
|
||||
auto resolve_path(specs::ChannelSpec&& spec, Channel::ResolveParams params) -> Channel
|
||||
{
|
||||
auto uri = specs::CondaURL::parse(util::path_or_url_to_url(spec.location()));
|
||||
auto uri = specs::CondaURL::parse(resolve_path_location(spec.clear_location(), params));
|
||||
auto display_name = resolve_path_name(uri, params);
|
||||
auto platforms = Channel::ResolveParams::platform_list{};
|
||||
if (spec.type() == specs::ChannelSpec::Type::Path)
|
||||
|
@ -266,7 +319,7 @@ namespace mamba
|
|||
platforms = make_platforms(spec.clear_platform_filters(), params.platforms);
|
||||
}
|
||||
|
||||
return Channel(std::move(uri), std::move(display_name), std::move(platforms));
|
||||
return { std::move(uri), std::move(display_name), std::move(platforms) };
|
||||
}
|
||||
|
||||
auto resolve_url_name(const specs::CondaURL& url, Channel::ResolveParams params) -> std::string
|
||||
|
@ -300,68 +353,110 @@ namespace mamba
|
|||
|
||||
auto url = specs::CondaURL::parse(spec.location());
|
||||
auto display_name = resolve_url_name(url, params);
|
||||
set_fallback_credential_from_db(url, params.auth_db);
|
||||
set_fallback_credential_from_db(url, params.authentication_db);
|
||||
auto platforms = Channel::ResolveParams::platform_list{};
|
||||
if (spec.type() == specs::ChannelSpec::Type::URL)
|
||||
{
|
||||
platforms = make_platforms(spec.clear_platform_filters(), params.platforms);
|
||||
}
|
||||
|
||||
return Channel(std::move(url), std::move(display_name), std::move(platforms));
|
||||
return { std::move(url), std::move(display_name), std::move(platforms) };
|
||||
}
|
||||
|
||||
auto resolve_name(specs::ChannelSpec&& spec, Channel::ResolveParams params) -> Channel
|
||||
auto resolve_name_in_custom_channel(
|
||||
specs::ChannelSpec&& spec,
|
||||
Channel::ResolveParams params,
|
||||
const Channel& match
|
||||
) -> Channel
|
||||
{
|
||||
std::string name = spec.clear_location();
|
||||
auto url = match.url();
|
||||
// we can have a channel like
|
||||
// testchannel: https://server.com/private/testchannel
|
||||
// where `name == private/testchannel` and we need to join the remaining label part
|
||||
// of the channel (e.g. -c testchannel/mylabel/xyz)
|
||||
// needs to result in `name = private/testchannel/mylabel/xyz`
|
||||
std::string combined_name = util::concat_dedup_splits(
|
||||
util::rstrip(url.path(), '/'),
|
||||
util::lstrip(spec.location(), '/'),
|
||||
'/'
|
||||
);
|
||||
url.set_path(combined_name);
|
||||
|
||||
const auto& custom_chans = params.custom_channels;
|
||||
if (auto it = custom_chans.find_weaken(name); it != custom_chans.cend())
|
||||
set_fallback_credential_from_db(url, params.authentication_db);
|
||||
return {
|
||||
/* url= */ std::move(url),
|
||||
/* display_name= */ spec.clear_location(),
|
||||
/* platforms= */ make_platforms(spec.clear_platform_filters(), params.platforms),
|
||||
};
|
||||
}
|
||||
|
||||
auto resolve_name_in_custom_mulitchannels(
|
||||
const specs::ChannelSpec& spec,
|
||||
Channel::ResolveParams params,
|
||||
const Channel::channel_list& matches
|
||||
) -> Channel::channel_list
|
||||
{
|
||||
auto out = Channel::channel_list();
|
||||
out.reserve(matches.size());
|
||||
|
||||
for (const auto& chan : matches)
|
||||
{
|
||||
auto url = it->second.url();
|
||||
// we can have a channel like
|
||||
// testchannel: https://server.com/private/testchannel
|
||||
// where `name == private/testchannel` and we need to join the remaining label part
|
||||
// of the channel (e.g. -c testchannel/mylabel/xyz)
|
||||
// needs to result in `name = private/testchannel/mylabel/xyz`
|
||||
std::string combined_name = util::concat_dedup_splits(
|
||||
util::rstrip(url.path(), '/'),
|
||||
util::lstrip(name, '/'),
|
||||
'/'
|
||||
);
|
||||
url.set_path(combined_name);
|
||||
|
||||
set_fallback_credential_from_db(url, params.auth_db);
|
||||
return Channel(
|
||||
auto url = chan.url();
|
||||
set_fallback_credential_from_db(url, params.authentication_db);
|
||||
out.emplace_back(
|
||||
/* url= */ std::move(url),
|
||||
/* display_name= */ std::move(name),
|
||||
/* platforms= */ make_platforms(spec.clear_platform_filters(), params.platforms)
|
||||
/* display_name= */ chan.display_name(), // Not using multi_channel name
|
||||
/* platforms= */ make_platforms(spec.platform_filters(), params.platforms)
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
auto resolve_name_from_alias(specs::ChannelSpec&& spec, Channel::ResolveParams params)
|
||||
-> Channel
|
||||
{
|
||||
auto url = params.channel_alias;
|
||||
url.append_path(name);
|
||||
set_fallback_credential_from_db(url, params.auth_db);
|
||||
return Channel(
|
||||
url.append_path(spec.location());
|
||||
set_fallback_credential_from_db(url, params.authentication_db);
|
||||
return {
|
||||
/* url= */ std::move(url),
|
||||
/* display_name= */ name,
|
||||
/* platforms= */ make_platforms(spec.clear_platform_filters(), params.platforms)
|
||||
);
|
||||
/* display_name= */ spec.clear_location(),
|
||||
/* platforms= */ make_platforms(spec.clear_platform_filters(), params.platforms),
|
||||
};
|
||||
}
|
||||
|
||||
auto resolve_name(specs::ChannelSpec&& spec, Channel::ResolveParams params)
|
||||
-> Channel::channel_list
|
||||
{
|
||||
if (auto it = params.custom_channels.find_weaken(spec.location());
|
||||
it != params.custom_channels.cend())
|
||||
{
|
||||
return { resolve_name_in_custom_channel(std::move(spec), params, it->second) };
|
||||
}
|
||||
|
||||
if (auto it = params.custom_multichannels.find(spec.location());
|
||||
it != params.custom_multichannels.end())
|
||||
{
|
||||
return resolve_name_in_custom_mulitchannels(spec, params, it->second);
|
||||
}
|
||||
|
||||
return { resolve_name_from_alias(std::move(spec), params) };
|
||||
}
|
||||
}
|
||||
|
||||
auto Channel::resolve(specs::ChannelSpec spec, ResolveParams params) -> Channel
|
||||
auto Channel::resolve(specs::ChannelSpec spec, ResolveParams params) -> channel_list
|
||||
{
|
||||
switch (spec.type())
|
||||
{
|
||||
case specs::ChannelSpec::Type::PackagePath:
|
||||
case specs::ChannelSpec::Type::Path:
|
||||
{
|
||||
return resolve_path(std::move(spec), params);
|
||||
return { resolve_path(std::move(spec), params) };
|
||||
}
|
||||
case specs::ChannelSpec::Type::PackageURL:
|
||||
case specs::ChannelSpec::Type::URL:
|
||||
{
|
||||
return resolve_url(std::move(spec), params);
|
||||
return { resolve_url(std::move(spec), params) };
|
||||
}
|
||||
case specs::ChannelSpec::Type::Name:
|
||||
{
|
||||
|
@ -369,69 +464,41 @@ namespace mamba
|
|||
}
|
||||
case specs::ChannelSpec::Type::Unknown:
|
||||
{
|
||||
return Channel(specs::CondaURL{}, spec.clear_location());
|
||||
return { { specs::CondaURL{}, spec.clear_location() } };
|
||||
}
|
||||
}
|
||||
throw std::invalid_argument("Invalid ChannelSpec::Type");
|
||||
}
|
||||
|
||||
const Channel& ChannelContext::make_channel(const std::string& value)
|
||||
auto ChannelContext::params() -> Channel::ResolveParams
|
||||
{
|
||||
if (const auto it = m_channel_cache.find(value); it != m_channel_cache.end())
|
||||
return {
|
||||
/* .platforms= */ m_platforms,
|
||||
/* .channel_alias= */ m_channel_alias,
|
||||
/* .custom_channels= */ m_custom_channels,
|
||||
/* .custom_multichannels= */ m_custom_multichannels,
|
||||
/* .authentication_db= */ m_context.authentication_info(),
|
||||
/* .home_dir= */ m_home_dir,
|
||||
/* .current_working_dir= */ m_current_working_dir,
|
||||
};
|
||||
}
|
||||
|
||||
auto ChannelContext::make_channel(std::string_view name) -> channel_list
|
||||
{
|
||||
if (const auto it = m_channel_cache.find(std::string(name)); it != m_channel_cache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto spec = specs::ChannelSpec::parse(value);
|
||||
auto params = Channel::ResolveParams{
|
||||
/* .platforms */ m_platforms,
|
||||
/* .channel_alias */ m_channel_alias,
|
||||
/* .custom_channels */ m_custom_channels,
|
||||
/* .auth_db */ m_context.authentication_info(),
|
||||
};
|
||||
|
||||
auto [it, inserted] = m_channel_cache.emplace(value, Channel::resolve(std::move(spec), params));
|
||||
auto [it, inserted] = m_channel_cache.emplace(
|
||||
name,
|
||||
Channel::resolve(specs::ChannelSpec::parse(name), params())
|
||||
);
|
||||
assert(inserted);
|
||||
return it->second;
|
||||
return { it->second };
|
||||
}
|
||||
|
||||
auto ChannelContext::get_channels(const std::vector<std::string>& channel_names) -> channel_list
|
||||
{
|
||||
auto added = std::unordered_set<Channel>();
|
||||
auto result = channel_list();
|
||||
for (auto name : channel_names)
|
||||
{
|
||||
auto spec = specs::ChannelSpec::parse(name);
|
||||
|
||||
const auto& multi_chan = get_custom_multichannels();
|
||||
if (auto iter = multi_chan.find(spec.location()); iter != multi_chan.end())
|
||||
{
|
||||
for (const auto& chan : iter->second)
|
||||
{
|
||||
auto channel = chan;
|
||||
if (!spec.platform_filters().empty())
|
||||
{
|
||||
channel.set_platforms(spec.platform_filters());
|
||||
}
|
||||
if (added.insert(channel).second)
|
||||
{
|
||||
result.push_back(std::move(channel));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto channel = make_channel(name);
|
||||
if (added.insert(channel).second)
|
||||
{
|
||||
result.push_back(std::move(channel));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const specs::CondaURL& ChannelContext::get_channel_alias() const
|
||||
auto ChannelContext::get_channel_alias() const -> const specs::CondaURL&
|
||||
{
|
||||
return m_channel_alias;
|
||||
}
|
||||
|
@ -449,9 +516,13 @@ namespace mamba
|
|||
ChannelContext::ChannelContext(Context& context)
|
||||
: m_context(context)
|
||||
, m_channel_alias(specs::CondaURL::parse(util::path_or_url_to_url(m_context.channel_alias)))
|
||||
, m_home_dir(util::user_home_dir())
|
||||
, m_current_working_dir(fs::current_path())
|
||||
{
|
||||
m_platforms = [](const auto& plats)
|
||||
{ return platform_list(plats.cbegin(), plats.cend()); }(m_context.platforms());
|
||||
{
|
||||
const auto& plats = m_context.platforms();
|
||||
m_platforms = Channel::ResolveParams::platform_list(plats.cbegin(), plats.cend());
|
||||
}
|
||||
init_custom_channels();
|
||||
}
|
||||
|
||||
|
@ -461,9 +532,10 @@ namespace mamba
|
|||
{
|
||||
for (const auto& [name, location] : m_context.custom_channels)
|
||||
{
|
||||
auto channel = make_channel(location);
|
||||
channel.set_display_name(name);
|
||||
m_custom_channels.emplace(name, std::move(channel));
|
||||
auto channels = make_channel(location);
|
||||
assert(channels.size() == 1);
|
||||
channels.front().set_display_name(name);
|
||||
m_custom_channels.emplace(name, std::move(channels.front()));
|
||||
}
|
||||
|
||||
for (const auto& [multi_name, location_list] : m_context.custom_multichannels)
|
||||
|
@ -472,7 +544,10 @@ namespace mamba
|
|||
channels.reserve(location_list.size());
|
||||
for (auto& location : location_list)
|
||||
{
|
||||
channels.push_back(make_channel(location));
|
||||
for (auto& chan : make_channel(location))
|
||||
{
|
||||
channels.push_back(std::move(chan));
|
||||
}
|
||||
}
|
||||
m_custom_multichannels.emplace(multi_name, std::move(channels));
|
||||
}
|
||||
|
|
|
@ -93,9 +93,11 @@ namespace mamba
|
|||
);
|
||||
}
|
||||
|
||||
const auto& parsed_channel = channel_context.make_channel(spec_str);
|
||||
auto channels = channel_context.make_channel(spec_str);
|
||||
|
||||
if (auto pkg = parsed_channel.url().package(); !pkg.empty())
|
||||
// TODO we are not handling the custom_multichannel case where `channels` can have
|
||||
// more than one element.
|
||||
if (auto pkg = channels.front().url().package(); !pkg.empty())
|
||||
{
|
||||
auto dist = parse_legacy_dist(pkg);
|
||||
|
||||
|
@ -103,9 +105,9 @@ namespace mamba
|
|||
version = dist[1];
|
||||
build_string = dist[2];
|
||||
|
||||
channel = parsed_channel.display_name();
|
||||
channel = channels.front().display_name();
|
||||
// TODO how to handle this with multiple platforms?
|
||||
if (const auto& plats = parsed_channel.platforms(); !plats.empty())
|
||||
if (const auto& plats = channels.front().platforms(); !plats.empty())
|
||||
{
|
||||
subdir = plats.front();
|
||||
}
|
||||
|
|
|
@ -78,7 +78,9 @@ namespace mamba
|
|||
// FIXME: only do this for micromamba for now
|
||||
if (channel_context.context().command_params.is_micromamba)
|
||||
{
|
||||
m_url = channel_context.make_channel(pkg_info.url).urls(true)[0];
|
||||
auto channels = channel_context.make_channel(pkg_info.url);
|
||||
assert(channels.size() == 1); // A URL can only resolve to one channel
|
||||
m_url = channels.front().urls(true)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -140,63 +140,37 @@ namespace mamba
|
|||
|
||||
namespace
|
||||
{
|
||||
bool
|
||||
channel_match(ChannelContext& channel_context, const Channel& chan, const Channel& needle)
|
||||
enum struct ChannelMatch
|
||||
{
|
||||
if (chan.base_url() == needle.base_url())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
None,
|
||||
ChannelOnly,
|
||||
ChannelAndSubdir,
|
||||
};
|
||||
|
||||
auto& custom_multichannels = channel_context.context().custom_multichannels;
|
||||
auto x = custom_multichannels.find(needle.display_name());
|
||||
if (x != custom_multichannels.end())
|
||||
auto channel_match(
|
||||
const std::vector<Channel>& repo_channels,
|
||||
const std::vector<Channel>& candidate_channels
|
||||
) -> ChannelMatch
|
||||
{
|
||||
// More than one element means the channel spec was a custom_multi_channel,
|
||||
// which should never happen for the repo
|
||||
for (const auto& repo_chan : repo_channels)
|
||||
{
|
||||
for (auto el : (x->second))
|
||||
// More than one element means the channel spec was a custom_multi_channel.
|
||||
// We need to add any repo that matches.
|
||||
for (const auto& cand_chan : candidate_channels)
|
||||
{
|
||||
const Channel& inner = channel_context.make_channel(el);
|
||||
if (chan.base_url() == inner.base_url())
|
||||
if (repo_chan.url_equivalent_with(cand_chan))
|
||||
{
|
||||
return true;
|
||||
if (util::set_is_subset_of(repo_chan.platforms(), cand_chan.platforms()))
|
||||
{
|
||||
return ChannelMatch::ChannelAndSubdir;
|
||||
}
|
||||
return ChannelMatch::ChannelOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool subdir_match(std::string candidate_repo_url, std::string needle_spec)
|
||||
{
|
||||
// Example candidate_repo_url: https://.../conda-forge/linux-64
|
||||
// example needle_spec: conda-forge/osx-64::xtensor
|
||||
|
||||
std::string needle_channel = util::split(needle_spec, ":", 1)[0];
|
||||
if (!util::contains(needle_channel, "/"))
|
||||
{
|
||||
// Subdir not specified, so any subdir is fine
|
||||
return true;
|
||||
}
|
||||
std::string needle_subdir = util::rsplit(needle_channel, "/", 1)[1];
|
||||
|
||||
auto known_platforms = specs::known_platform_names();
|
||||
if (std::find(known_platforms.begin(), known_platforms.end(), needle_subdir)
|
||||
== known_platforms.end())
|
||||
{
|
||||
// Not a known subdir. This can happen for specs like pkgs/main.
|
||||
// so any subdir is fine
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string candidate_repo_subdir = util::rsplit(candidate_repo_url, "/", 1)[1];
|
||||
|
||||
if (candidate_repo_subdir == needle_subdir)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
throw std::runtime_error(fmt::format(
|
||||
"The package \"{}\" is not available for the specified platform",
|
||||
needle_spec
|
||||
));
|
||||
return ChannelMatch::None;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -223,18 +197,8 @@ namespace mamba
|
|||
ms.conda_build_form().c_str()
|
||||
);
|
||||
|
||||
const auto& multi_chan = channel_context.get_custom_multichannels();
|
||||
auto channels = std::vector<Channel>();
|
||||
if (auto iter = multi_chan.find(ms.channel); iter != multi_chan.end())
|
||||
{
|
||||
channels.insert(channels.end(), iter->second.cbegin(), iter->second.cend());
|
||||
}
|
||||
else
|
||||
{
|
||||
channels.push_back(channel_context.make_channel(ms.channel));
|
||||
}
|
||||
|
||||
solv::ObjQueue selected_pkgs = {};
|
||||
bool found_partial_matches = false;
|
||||
pool.for_each_whatprovides(
|
||||
match,
|
||||
[&](solv::ObjSolvableViewConst s)
|
||||
|
@ -242,21 +206,46 @@ namespace mamba
|
|||
// TODO this does not work with s.url(), we need to proper channel class
|
||||
// to properly manage this.
|
||||
auto repo = solv::ObjRepoView(*s.raw()->repo);
|
||||
// TODO make_channel should disapear avoiding conflict here
|
||||
auto const url = std::string(repo.url());
|
||||
for (auto const& c : channels)
|
||||
// TODO Replace MatchSpec channel and subdir with a ChannelSpec
|
||||
const auto chan_spec = [&]() -> std::string
|
||||
{
|
||||
if (channel_match(channel_context, channel_context.make_channel(url), c))
|
||||
if (ms.subdir.empty())
|
||||
{
|
||||
return ms.channel;
|
||||
}
|
||||
return util::concat(ms.channel, '[', ms.subdir, ']');
|
||||
}();
|
||||
const auto match = channel_match(
|
||||
channel_context.make_channel(repo.url()),
|
||||
channel_context.make_channel(chan_spec)
|
||||
);
|
||||
switch (match)
|
||||
{
|
||||
case (ChannelMatch::ChannelAndSubdir):
|
||||
{
|
||||
selected_pkgs.push_back(s.id());
|
||||
break;
|
||||
}
|
||||
case (ChannelMatch::ChannelOnly):
|
||||
{
|
||||
found_partial_matches = true;
|
||||
break;
|
||||
}
|
||||
case (ChannelMatch::None):
|
||||
{
|
||||
if (subdir_match(url, ms.spec))
|
||||
{
|
||||
selected_pkgs.push_back(s.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (selected_pkgs.empty() && found_partial_matches)
|
||||
{
|
||||
throw std::runtime_error(fmt::format(
|
||||
R"(The package "{}" is not available for the specified platform)",
|
||||
ms.spec
|
||||
));
|
||||
}
|
||||
|
||||
const solv::StringId repr_id = pool.add_string(repr);
|
||||
// FRAGILE This get deleted when calling ``pool_createwhatprovides`` so care
|
||||
// must be taken to do it before
|
||||
|
|
|
@ -164,8 +164,12 @@ namespace mamba
|
|||
// and conda-meta json files with channel names while mamba expects
|
||||
// PackageInfo channels to be platform urls. This fixes the issue described
|
||||
// in https://github.com/mamba-org/mamba/issues/2665
|
||||
const Channel& channel = m_channel_context.make_channel(prec.channel);
|
||||
prec.channel = channel.platform_url(prec.subdir);
|
||||
|
||||
auto channels = m_channel_context.make_channel(prec.channel);
|
||||
// If someone wrote multichannel names in repodata_record, we don't know which one is the
|
||||
// correct URL. This is must never happen!
|
||||
assert(channels.size() == 1);
|
||||
prec.channel = channels.front().platform_url(prec.subdir);
|
||||
m_package_records.insert({ prec.name, std::move(prec) });
|
||||
}
|
||||
} // namespace mamba
|
||||
|
|
|
@ -107,8 +107,19 @@ namespace mamba
|
|||
}
|
||||
|
||||
MatchSpec modified_spec(ms);
|
||||
const Channel& chan = m_pool.channel_context().make_channel(std::string(solvable->channel()));
|
||||
modified_spec.channel = chan.display_name();
|
||||
{
|
||||
auto channels = m_pool.channel_context().make_channel(std::string(solvable->channel()));
|
||||
if (channels.size() == 1)
|
||||
{
|
||||
modified_spec.channel = channels.front().display_name();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is more than one, it's a custom_multi_channel name.
|
||||
// This should never happen.
|
||||
modified_spec.channel = solvable->channel();
|
||||
}
|
||||
}
|
||||
|
||||
modified_spec.version = solvable->version();
|
||||
modified_spec.build_string = solvable->build_string();
|
||||
|
@ -146,7 +157,7 @@ namespace mamba
|
|||
// moment
|
||||
}
|
||||
|
||||
::Id const job_id = m_pool.matchspec2id(ms);
|
||||
const ::Id job_id = m_pool.matchspec2id(ms);
|
||||
|
||||
// This is checking if SOLVER_ERASE and SOLVER_INSTALL are set
|
||||
// which are the flags for SOLVER_UPDATE
|
||||
|
@ -224,7 +235,7 @@ namespace mamba
|
|||
// Add dummy solvable with a constraint on the pin (not installed if not present)
|
||||
auto [cons_solv_id, cons_solv] = installed->add_solvable();
|
||||
// TODO set some "pin" key on the solvable so that we can retrieve it during error messages
|
||||
std::string const cons_solv_name = fmt::format("pin-{}", m_pinned_specs.size());
|
||||
const std::string cons_solv_name = fmt::format("pin-{}", m_pinned_specs.size());
|
||||
cons_solv.set_name(cons_solv_name);
|
||||
cons_solv.set_version("1");
|
||||
cons_solv.add_constraints(solv::ObjQueue{ m_pool.matchspec2id(pin_ms) });
|
||||
|
|
|
@ -378,11 +378,16 @@ namespace mamba
|
|||
|
||||
bool check_zst(ChannelContext& channel_context, const Channel& channel)
|
||||
{
|
||||
// TODO the list of channels with zst should really be computed only once in
|
||||
// the ChannelContext
|
||||
for (const auto& c : channel_context.context().repodata_has_zst)
|
||||
{
|
||||
if (channel_context.make_channel(c).base_url() == channel.base_url())
|
||||
for (const auto& chan : channel_context.make_channel(c))
|
||||
{
|
||||
return true;
|
||||
if (chan.contains_equivalent(channel))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -1231,8 +1231,17 @@ namespace mamba
|
|||
}
|
||||
else
|
||||
{
|
||||
const Channel& chan = m_pool.channel_context().make_channel(str);
|
||||
chan_name = chan.display_name();
|
||||
auto channels = m_pool.channel_context().make_channel(str);
|
||||
if (channels.size() == 1)
|
||||
{
|
||||
chan_name = channels.front().display_name();
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is more than on, it's a custom_multi_channel name
|
||||
// This should never happen
|
||||
chan_name = str;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -89,10 +89,14 @@ namespace mamba
|
|||
CHECK_EQ(it->second.display_name(), "pkgs/main");
|
||||
|
||||
std::string value = "conda-forge";
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
CHECK_EQ(c.url(), CondaURL::parse("https://mydomain.com/channels/conda-forge"));
|
||||
CHECK_EQ(c.display_name(), "conda-forge");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
channels.front().url(),
|
||||
CondaURL::parse("https://mydomain.com/channels/conda-forge")
|
||||
);
|
||||
CHECK_EQ(channels.front().display_name(), "conda-forge");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
|
||||
ctx.channel_alias = "https://conda.anaconda.org";
|
||||
}
|
||||
|
@ -108,8 +112,9 @@ namespace mamba
|
|||
|
||||
ChannelContext channel_context{ ctx };
|
||||
auto base = std::string("https://ali.as/prefix-and-more/");
|
||||
auto& chan = channel_context.make_channel(base);
|
||||
CHECK_EQ(chan.urls(), UrlSet{ base + platform, base + "noarch" });
|
||||
const auto channels = channel_context.make_channel(base);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(channels.front().urls(), UrlSet{ base + platform, base + "noarch" });
|
||||
|
||||
ctx.channel_alias = "https://conda.anaconda.org";
|
||||
ctx.custom_channels.clear();
|
||||
|
@ -133,28 +138,33 @@ namespace mamba
|
|||
|
||||
{
|
||||
std::string value = "test_channel";
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
CHECK_EQ(c.url(), CondaURL::parse("file:///tmp/test_channel"));
|
||||
CHECK_EQ(c.display_name(), "test_channel");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(channels.front().url(), CondaURL::parse("file:///tmp/test_channel"));
|
||||
CHECK_EQ(channels.front().display_name(), "test_channel");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const UrlSet exp_urls({
|
||||
std::string("file:///tmp/test_channel/") + platform,
|
||||
"file:///tmp/test_channel/noarch",
|
||||
});
|
||||
CHECK_EQ(c.urls(), exp_urls);
|
||||
CHECK_EQ(channels.front().urls(), exp_urls);
|
||||
}
|
||||
|
||||
{
|
||||
std::string value = "some_channel";
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
CHECK_EQ(c.url(), CondaURL::parse("https://conda.mydomain.xyz/some_channel"));
|
||||
CHECK_EQ(c.display_name(), "some_channel");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
channels.front().url(),
|
||||
CondaURL::parse("https://conda.mydomain.xyz/some_channel")
|
||||
);
|
||||
CHECK_EQ(channels.front().display_name(), "some_channel");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const UrlSet exp_urls({
|
||||
std::string("https://conda.mydomain.xyz/some_channel/") + platform,
|
||||
"https://conda.mydomain.xyz/some_channel/noarch",
|
||||
});
|
||||
CHECK_EQ(c.urls(), exp_urls);
|
||||
CHECK_EQ(channels.front().urls(), exp_urls);
|
||||
}
|
||||
|
||||
ctx.channel_alias = "https://conda.anaconda.org";
|
||||
|
@ -179,7 +189,7 @@ namespace mamba
|
|||
|
||||
ChannelContext channel_context{ ctx };
|
||||
|
||||
auto x = channel_context.get_channels({ "xtest" });
|
||||
auto x = channel_context.make_channel("xtest");
|
||||
|
||||
CHECK_EQ(x.size(), 3);
|
||||
auto c1 = x[0];
|
||||
|
@ -196,7 +206,7 @@ namespace mamba
|
|||
"https://otherdomain.com/snakepit/noarch",
|
||||
});
|
||||
|
||||
auto y = channel_context.get_channels({ "ytest" });
|
||||
auto y = channel_context.make_channel("ytest");
|
||||
auto y3 = y[2];
|
||||
|
||||
CHECK_EQ(y3.urls(), exp_urlsy3);
|
||||
|
@ -223,7 +233,7 @@ namespace mamba
|
|||
|
||||
ChannelContext channel_context{ ctx };
|
||||
|
||||
auto x = channel_context.get_channels({ "everything" });
|
||||
auto x = channel_context.make_channel("everything");
|
||||
|
||||
CHECK_EQ(x.size(), 3);
|
||||
auto c1 = x[0];
|
||||
|
@ -266,7 +276,7 @@ namespace mamba
|
|||
|
||||
ChannelContext channel_context{ ctx };
|
||||
|
||||
auto x = channel_context.get_channels({ "defaults" });
|
||||
auto x = channel_context.make_channel("defaults");
|
||||
#if !defined(_WIN32)
|
||||
const Channel c1 = x[0];
|
||||
const Channel c2 = x[1];
|
||||
|
@ -301,7 +311,7 @@ namespace mamba
|
|||
ctx.custom_multichannels["defaults"] = ctx.default_channels;
|
||||
ChannelContext channel_context{ ctx };
|
||||
|
||||
auto x = channel_context.get_channels({ "defaults" });
|
||||
auto x = channel_context.make_channel("defaults");
|
||||
const Channel c1 = x[0];
|
||||
const Channel c2 = x[1];
|
||||
|
||||
|
@ -338,7 +348,7 @@ namespace mamba
|
|||
|
||||
CHECK_EQ(channel_context.get_custom_multichannels().at("local").size(), 3);
|
||||
|
||||
auto local_channels = channel_context.get_channels({ "local" });
|
||||
auto local_channels = channel_context.make_channel("local");
|
||||
CHECK_EQ(local_channels.size(), 3);
|
||||
}
|
||||
|
||||
|
@ -353,50 +363,56 @@ namespace mamba
|
|||
|
||||
{
|
||||
std::string value = "test_channel";
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
CHECK_EQ(c.url(), CondaURL::parse("https://server.com/private/channels/test_channel"));
|
||||
CHECK_EQ(c.display_name(), "test_channel");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
channels.front().url(),
|
||||
CondaURL::parse("https://server.com/private/channels/test_channel")
|
||||
);
|
||||
CHECK_EQ(channels.front().display_name(), "test_channel");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const UrlSet exp_urls({
|
||||
std::string("https://server.com/private/channels/test_channel/") + platform,
|
||||
"https://server.com/private/channels/test_channel/noarch",
|
||||
});
|
||||
CHECK_EQ(c.urls(), exp_urls);
|
||||
CHECK_EQ(channels.front().urls(), exp_urls);
|
||||
}
|
||||
|
||||
{
|
||||
std::string value = "test_channel/mylabel/xyz";
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
c.url(),
|
||||
channels.front().url(),
|
||||
CondaURL::parse("https://server.com/private/channels/test_channel/mylabel/xyz")
|
||||
);
|
||||
CHECK_EQ(c.display_name(), "test_channel/mylabel/xyz");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
CHECK_EQ(channels.front().display_name(), "test_channel/mylabel/xyz");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const UrlSet exp_urls({
|
||||
std::string("https://server.com/private/channels/test_channel/mylabel/xyz/")
|
||||
+ platform,
|
||||
"https://server.com/private/channels/test_channel/mylabel/xyz/noarch",
|
||||
});
|
||||
CHECK_EQ(c.urls(), exp_urls);
|
||||
CHECK_EQ(channels.front().urls(), exp_urls);
|
||||
}
|
||||
|
||||
{
|
||||
// https://github.com/mamba-org/mamba/issues/2553
|
||||
std::string value = "random/test_channel/pkg";
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
c.url(),
|
||||
channels.front().url(),
|
||||
CondaURL::parse("https://server.com/random/channels/random/test_channel/pkg")
|
||||
);
|
||||
CHECK_EQ(c.display_name(), "random/test_channel/pkg");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
CHECK_EQ(channels.front().display_name(), "random/test_channel/pkg");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const UrlSet exp_urls({
|
||||
std::string("https://server.com/random/channels/random/test_channel/pkg/")
|
||||
+ platform,
|
||||
"https://server.com/random/channels/random/test_channel/pkg/noarch",
|
||||
});
|
||||
CHECK_EQ(c.urls(), exp_urls);
|
||||
CHECK_EQ(channels.front().urls(), exp_urls);
|
||||
}
|
||||
|
||||
ctx.channel_alias = "https://conda.anaconda.org";
|
||||
|
@ -410,69 +426,82 @@ namespace mamba
|
|||
{
|
||||
std::string value = "https://repo.mamba.pm/conda-forge";
|
||||
ChannelContext channel_context{ mambatests::context() };
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
CHECK_EQ(c.url(), CondaURL::parse("https://repo.mamba.pm/conda-forge"));
|
||||
CHECK_EQ(c.display_name(), "https://repo.mamba.pm/conda-forge");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels = channel_context.make_channel(value);
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(channels.front().url(), CondaURL::parse("https://repo.mamba.pm/conda-forge"));
|
||||
CHECK_EQ(channels.front().display_name(), "https://repo.mamba.pm/conda-forge");
|
||||
CHECK_EQ(channels.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
}
|
||||
|
||||
TEST_CASE("make_channel")
|
||||
TEST_CASE("make_chan")
|
||||
{
|
||||
std::string value = "conda-forge";
|
||||
std::string value1 = "conda-forge";
|
||||
ChannelContext channel_context{ mambatests::context() };
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
CHECK_EQ(c.url(), CondaURL::parse("https://conda.anaconda.org/conda-forge"));
|
||||
CHECK_EQ(c.display_name(), "conda-forge");
|
||||
CHECK_EQ(c.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels1 = channel_context.make_channel(value1);
|
||||
REQUIRE_EQ(channels1.size(), 1);
|
||||
CHECK_EQ(channels1.front().url(), CondaURL::parse("https://conda.anaconda.org/conda-forge"));
|
||||
CHECK_EQ(channels1.front().display_name(), "conda-forge");
|
||||
CHECK_EQ(channels1.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
|
||||
std::string value2 = "https://repo.anaconda.com/pkgs/main[" + platform + "]";
|
||||
const Channel& c2 = channel_context.make_channel(value2);
|
||||
CHECK_EQ(c2.url(), CondaURL::parse("https://repo.anaconda.com/pkgs/main"));
|
||||
CHECK_EQ(c2.display_name(), "https://repo.anaconda.com/pkgs/main");
|
||||
CHECK_EQ(c2.platforms(), PlatformSet({ platform }));
|
||||
const auto channels2 = channel_context.make_channel(value2);
|
||||
REQUIRE_EQ(channels2.size(), 1);
|
||||
CHECK_EQ(channels2.front().url(), CondaURL::parse("https://repo.anaconda.com/pkgs/main"));
|
||||
CHECK_EQ(channels2.front().display_name(), "https://repo.anaconda.com/pkgs/main");
|
||||
CHECK_EQ(channels2.front().platforms(), PlatformSet({ platform }));
|
||||
|
||||
std::string value3 = "https://conda.anaconda.org/conda-forge[" + platform + "]";
|
||||
const Channel& c3 = channel_context.make_channel(value3);
|
||||
CHECK_EQ(c3.url(), c.url());
|
||||
CHECK_EQ(c3.display_name(), c.display_name());
|
||||
CHECK_EQ(c3.platforms(), PlatformSet({ platform }));
|
||||
const auto channels3 = channel_context.make_channel(value3);
|
||||
REQUIRE_EQ(channels3.size(), 1);
|
||||
CHECK_EQ(channels3.front().url(), channels1.front().url());
|
||||
CHECK_EQ(channels3.front().display_name(), channels1.front().display_name());
|
||||
CHECK_EQ(channels3.front().platforms(), PlatformSet({ platform }));
|
||||
|
||||
std::string value4 = "/home/mamba/test/channel_b";
|
||||
const Channel& c4 = channel_context.make_channel(value4);
|
||||
CHECK_EQ(c4.url(), CondaURL::parse(util::path_to_url(value4)));
|
||||
CHECK_EQ(c4.display_name(), c4.url().pretty_str());
|
||||
CHECK_EQ(c4.platforms(), PlatformSet({ platform, "noarch" }));
|
||||
const auto channels4 = channel_context.make_channel(value4);
|
||||
REQUIRE_EQ(channels4.size(), 1);
|
||||
CHECK_EQ(channels4.front().url(), CondaURL::parse(util::path_to_url(value4)));
|
||||
CHECK_EQ(channels4.front().display_name(), channels4.front().url().pretty_str());
|
||||
CHECK_EQ(channels4.front().platforms(), PlatformSet({ platform, "noarch" }));
|
||||
|
||||
std::string path5 = "/home/mamba/test/channel_b";
|
||||
std::string value5 = util::concat(path5, '[', platform, ']');
|
||||
const Channel& c5 = channel_context.make_channel(value5);
|
||||
CHECK_EQ(c5.url(), CondaURL::parse(util::path_to_url(path5)));
|
||||
CHECK_EQ(c5.display_name(), c5.url().pretty_str());
|
||||
CHECK_EQ(c5.platforms(), PlatformSet({ platform }));
|
||||
const auto channels5 = channel_context.make_channel(value5);
|
||||
REQUIRE_EQ(channels5.size(), 1);
|
||||
CHECK_EQ(channels5.front().url(), CondaURL::parse(util::path_to_url(path5)));
|
||||
CHECK_EQ(channels5.front().display_name(), channels5.front().url().pretty_str());
|
||||
CHECK_EQ(channels5.front().platforms(), PlatformSet({ platform }));
|
||||
|
||||
std::string value6a = "http://localhost:8000/conda-forge[noarch]";
|
||||
const Channel& c6a = channel_context.make_channel(value6a);
|
||||
CHECK_EQ(c6a.urls(false), UrlSet({ "http://localhost:8000/conda-forge/noarch" }));
|
||||
const auto channels6a = channel_context.make_channel(value6a);
|
||||
REQUIRE_EQ(channels6a.size(), 1);
|
||||
CHECK_EQ(
|
||||
channels6a.front().urls(false),
|
||||
UrlSet({ "http://localhost:8000/conda-forge/noarch" })
|
||||
);
|
||||
|
||||
std::string value6b = "http://localhost:8000/conda_mirror/conda-forge[noarch]";
|
||||
const Channel& c6b = channel_context.make_channel(value6b);
|
||||
const auto channels6b = channel_context.make_channel(value6b);
|
||||
REQUIRE_EQ(channels6b.size(), 1);
|
||||
CHECK_EQ(
|
||||
c6b.urls(false),
|
||||
channels6b.front().urls(false),
|
||||
UrlSet({ "http://localhost:8000/conda_mirror/conda-forge/noarch" })
|
||||
);
|
||||
|
||||
std::string value7 = "conda-forge[noarch,arbitrary]";
|
||||
const Channel& c7 = channel_context.make_channel(value7);
|
||||
CHECK_EQ(c7.platforms(), PlatformSet({ "noarch", "arbitrary" }));
|
||||
const auto channels7 = channel_context.make_channel(value7);
|
||||
REQUIRE_EQ(channels7.size(), 1);
|
||||
CHECK_EQ(channels7.front().platforms(), PlatformSet({ "noarch", "arbitrary" }));
|
||||
}
|
||||
|
||||
TEST_CASE("urls")
|
||||
{
|
||||
std::string value = "https://conda.anaconda.org/conda-forge[noarch,win-64,arbitrary]";
|
||||
std::string value1 = "https://conda.anaconda.org/conda-forge[noarch,win-64,arbitrary]";
|
||||
ChannelContext channel_context{ mambatests::context() };
|
||||
const Channel& c = channel_context.make_channel(value);
|
||||
const auto channels1 = channel_context.make_channel(value1);
|
||||
REQUIRE_EQ(channels1.size(), 1);
|
||||
CHECK_EQ(
|
||||
c.urls(),
|
||||
channels1.front().urls(),
|
||||
UrlSet({
|
||||
"https://conda.anaconda.org/conda-forge/arbitrary",
|
||||
"https://conda.anaconda.org/conda-forge/noarch",
|
||||
|
@ -480,9 +509,11 @@ namespace mamba
|
|||
})
|
||||
);
|
||||
|
||||
const Channel& c1 = channel_context.make_channel("https://conda.anaconda.org/conda-forge");
|
||||
const auto channels2 = channel_context.make_channel("https://conda.anaconda.org/conda-forge"
|
||||
);
|
||||
REQUIRE_EQ(channels2.size(), 1);
|
||||
CHECK_EQ(
|
||||
c1.urls(),
|
||||
channels2.front().urls(),
|
||||
UrlSet({
|
||||
"https://conda.anaconda.org/conda-forge/" + platform,
|
||||
"https://conda.anaconda.org/conda-forge/noarch",
|
||||
|
@ -500,13 +531,17 @@ namespace mamba
|
|||
|
||||
ChannelContext channel_context{ ctx };
|
||||
|
||||
const auto& chan = channel_context.make_channel("conda-forge[noarch]");
|
||||
CHECK_EQ(chan.url().token(), "my-12345-token");
|
||||
const auto channels = channel_context.make_channel("conda-forge[noarch]");
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(channels.front().url().token(), "my-12345-token");
|
||||
CHECK_EQ(
|
||||
chan.urls(true),
|
||||
channels.front().urls(true),
|
||||
UrlSet({ "https://conda.anaconda.org/t/my-12345-token/conda-forge/noarch" })
|
||||
);
|
||||
CHECK_EQ(chan.urls(false), UrlSet({ "https://conda.anaconda.org/conda-forge/noarch" }));
|
||||
CHECK_EQ(
|
||||
channels.front().urls(false),
|
||||
UrlSet({ "https://conda.anaconda.org/conda-forge/noarch" })
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("add_multiple_tokens")
|
||||
|
@ -520,8 +555,9 @@ namespace mamba
|
|||
|
||||
ChannelContext channel_context{ ctx };
|
||||
|
||||
const auto& chan = channel_context.make_channel("conda-forge[noarch]");
|
||||
CHECK_EQ(chan.url().token(), "channel-token");
|
||||
const auto channels = channel_context.make_channel("conda-forge[noarch]");
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(channels.front().url().token(), "channel-token");
|
||||
}
|
||||
|
||||
TEST_CASE("fix_win_file_path")
|
||||
|
@ -529,17 +565,19 @@ namespace mamba
|
|||
ChannelContext channel_context{ mambatests::context() };
|
||||
if (platform == "win-64")
|
||||
{
|
||||
const Channel& c = channel_context.make_channel("C:\\test\\channel");
|
||||
const auto channels = channel_context.make_channel(R"(C:\test\channel)");
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
c.urls(false),
|
||||
channels.front().urls(false),
|
||||
UrlSet({ "file:///C:/test/channel/win-64", "file:///C:/test/channel/noarch" })
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Channel& c = channel_context.make_channel("/test/channel");
|
||||
const auto channels = channel_context.make_channel("/test/channel");
|
||||
REQUIRE_EQ(channels.size(), 1);
|
||||
CHECK_EQ(
|
||||
c.urls(false),
|
||||
channels.front().urls(false),
|
||||
UrlSet({ std::string("file:///test/channel/") + platform,
|
||||
"file:///test/channel/noarch" })
|
||||
);
|
||||
|
@ -549,33 +587,42 @@ namespace mamba
|
|||
TEST_CASE("trailing_slash")
|
||||
{
|
||||
ChannelContext channel_context{ mambatests::context() };
|
||||
const Channel& c = channel_context.make_channel("http://localhost:8000/");
|
||||
CHECK_EQ(c.platform_url("win-64", false), "http://localhost:8000/win-64");
|
||||
CHECK_EQ(c.base_url(), "http://localhost:8000/");
|
||||
|
||||
const auto channels1 = channel_context.make_channel("http://localhost:8000/");
|
||||
REQUIRE_EQ(channels1.size(), 1);
|
||||
CHECK_EQ(channels1.front().platform_url("win-64", false), "http://localhost:8000/win-64");
|
||||
CHECK_EQ(channels1.front().url().str(), "http://localhost:8000/");
|
||||
const UrlSet expected_urls({ std::string("http://localhost:8000/") + platform,
|
||||
"http://localhost:8000/noarch" });
|
||||
CHECK_EQ(c.urls(true), expected_urls);
|
||||
const Channel& c4 = channel_context.make_channel("http://localhost:8000");
|
||||
CHECK_EQ(c4.platform_url("linux-64", false), "http://localhost:8000/linux-64");
|
||||
const Channel& c2 = channel_context.make_channel("http://user:test@localhost:8000/");
|
||||
CHECK_EQ(c2.platform_url("win-64", false), "http://localhost:8000/win-64");
|
||||
CHECK_EQ(c2.platform_url("win-64", true), "http://user:test@localhost:8000/win-64");
|
||||
const Channel& c3 = channel_context.make_channel(
|
||||
"https://localhost:8000/t/xy-12345678-1234-1234-1234-123456789012"
|
||||
);
|
||||
CHECK_EQ(c3.platform_url("win-64", false), "https://localhost:8000/win-64");
|
||||
CHECK_EQ(channels1.front().urls(true), expected_urls);
|
||||
|
||||
const auto channels4 = channel_context.make_channel("http://localhost:8000");
|
||||
REQUIRE_EQ(channels4.size(), 1);
|
||||
CHECK_EQ(channels4.front().platform_url("linux-64", false), "http://localhost:8000/linux-64");
|
||||
|
||||
const auto channels2 = channel_context.make_channel("http://user:test@localhost:8000/");
|
||||
REQUIRE_EQ(channels2.size(), 1);
|
||||
CHECK_EQ(channels2.front().platform_url("win-64", false), "http://localhost:8000/win-64");
|
||||
CHECK_EQ(
|
||||
c3.platform_url("win-64", true),
|
||||
"https://localhost:8000/t/xy-12345678-1234-1234-1234-123456789012/win-64"
|
||||
channels2.front().platform_url("win-64", true),
|
||||
"http://user:test@localhost:8000/win-64"
|
||||
);
|
||||
|
||||
const UrlSet expected_urls2({
|
||||
const auto channels3 = channel_context.make_channel(
|
||||
"https://localhost:8000/t/xy-12345678-1234-1234-1234-123456789012"
|
||||
);
|
||||
REQUIRE_EQ(channels3.size(), 1);
|
||||
CHECK_EQ(channels3.front().platform_url("win-64", false), "https://localhost:8000/win-64");
|
||||
CHECK_EQ(
|
||||
channels3.front().platform_url("win-64", true),
|
||||
"https://localhost:8000/t/xy-12345678-1234-1234-1234-123456789012/win-64"
|
||||
);
|
||||
const UrlSet expected_urls3({
|
||||
std::string("https://localhost:8000/t/xy-12345678-1234-1234-1234-123456789012/")
|
||||
+ platform,
|
||||
"https://localhost:8000/t/xy-12345678-1234-1234-1234-123456789012/noarch",
|
||||
});
|
||||
|
||||
CHECK_EQ(c3.urls(true), expected_urls2);
|
||||
CHECK_EQ(channels3.front().urls(true), expected_urls3);
|
||||
}
|
||||
|
||||
TEST_CASE("load_tokens")
|
||||
|
|
|
@ -330,14 +330,17 @@ namespace
|
|||
auto load_channels(MPool& pool, MultiPackageCache& cache, std::vector<std::string>&& channels)
|
||||
{
|
||||
auto sub_dirs = std::vector<MSubdirData>();
|
||||
for (const auto& chan : pool.channel_context().get_channels(channels))
|
||||
for (const auto& location : channels)
|
||||
{
|
||||
for (auto& [platform, url] : chan.platform_urls(true))
|
||||
for (const auto& chan : pool.channel_context().make_channel(location))
|
||||
{
|
||||
auto sub_dir = expected_value_or_throw(
|
||||
MSubdirData::create(pool.channel_context(), chan, platform, url, cache)
|
||||
);
|
||||
sub_dirs.push_back(std::move(sub_dir));
|
||||
for (auto& [platform, url] : chan.platform_urls(true))
|
||||
{
|
||||
auto sub_dir = expected_value_or_throw(
|
||||
MSubdirData::create(pool.channel_context(), chan, platform, url, cache)
|
||||
);
|
||||
sub_dirs.push_back(std::move(sub_dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1147,47 +1147,8 @@ bind_submodule_impl(pybind11::module_ m)
|
|||
py::arg("json_str")
|
||||
);
|
||||
|
||||
pyChannel
|
||||
.def(py::init(
|
||||
[](const std::string& value) {
|
||||
return const_cast<Channel*>(&mambapy::singletons.channel_context().make_channel(value)
|
||||
);
|
||||
}
|
||||
))
|
||||
.def_property_readonly("platforms", &Channel::platforms)
|
||||
.def_property_readonly("canonical_name", &Channel::display_name)
|
||||
.def("urls", &Channel::urls, py::arg("with_credentials") = true)
|
||||
.def("platform_urls", &Channel::platform_urls, py::arg("with_credentials") = true)
|
||||
.def("platform_url", &Channel::platform_url, py::arg("platform"), py::arg("with_credentials") = true)
|
||||
.def(
|
||||
"__repr__",
|
||||
[](const Channel& c)
|
||||
{
|
||||
auto s = c.display_name();
|
||||
s += "[";
|
||||
bool first = true;
|
||||
for (const auto& platform : c.platforms())
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
s += ",";
|
||||
}
|
||||
s += platform;
|
||||
first = false;
|
||||
}
|
||||
s += "]";
|
||||
return s;
|
||||
}
|
||||
);
|
||||
|
||||
m.def("clean", [](int flags) { return clean(mambapy::singletons.config(), flags); });
|
||||
|
||||
m.def(
|
||||
"get_channels",
|
||||
[](const std::vector<std::string>& channel_names)
|
||||
{ return mambapy::singletons.channel_context().get_channels(channel_names); }
|
||||
);
|
||||
|
||||
m.def(
|
||||
"transmute",
|
||||
+[](const fs::u8path& pkg_file, const fs::u8path& target, int compression_level, int compression_threads
|
||||
|
|
|
@ -144,11 +144,8 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
|
||||
for (const auto& record : records)
|
||||
{
|
||||
auto url = specs::CondaURL::parse(record.url);
|
||||
url.clear_token();
|
||||
url.clear_password();
|
||||
url.clear_user();
|
||||
std::cout << url.str();
|
||||
using Credentials = typename specs::CondaURL::Credentials;
|
||||
std::cout << specs::CondaURL::parse(record.url).str(Credentials::Hide);
|
||||
if (no_md5 != 1)
|
||||
{
|
||||
std::cout << "#" << record.md5;
|
||||
|
@ -176,7 +173,7 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
continue;
|
||||
}
|
||||
|
||||
const Channel& channel = channel_context.make_channel(v.channel);
|
||||
auto chans = channel_context.make_channel(v.channel);
|
||||
|
||||
if (from_history)
|
||||
{
|
||||
|
@ -187,7 +184,10 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
dependencies << "- ";
|
||||
if (channel_subdir)
|
||||
{
|
||||
dependencies << channel.display_name() << "/" << v.subdir << "::";
|
||||
dependencies
|
||||
// If the size is not one, it's a custom mutli channel
|
||||
<< ((chans.size() == 1) ? chans.front().display_name() : v.channel)
|
||||
<< "/" << v.subdir << "::";
|
||||
}
|
||||
dependencies << v.name << "=" << v.version;
|
||||
if (!no_build)
|
||||
|
@ -201,7 +201,10 @@ set_env_command(CLI::App* com, Configuration& config)
|
|||
dependencies << "\n";
|
||||
}
|
||||
|
||||
channels.insert(channel.display_name());
|
||||
for (auto const& chan : chans)
|
||||
{
|
||||
channels.insert(chan.display_name());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& c : channels)
|
||||
|
|
Loading…
Reference in New Issue