Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Channel initialization #2953

Merged
merged 29 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7cf1005
Set default_channels at config level
AntoinePrv Oct 24, 2023
f9059e4
Resolve default multi channel at the config level
AntoinePrv Oct 24, 2023
69d0dfc
Fix Yaml source printers
AntoinePrv Oct 25, 2023
ceed6ab
Resolve local multi channel at the config level
AntoinePrv Oct 24, 2023
90ea4ab
Remove ChannelContext::make_simple_channel
AntoinePrv Oct 24, 2023
dcfb600
Remove Channel::name usage
AntoinePrv Nov 2, 2023
7f17c19
Factorize split_once functions
AntoinePrv Nov 3, 2023
293588c
Try looking for name match in URL path
AntoinePrv Nov 3, 2023
49034c1
Refactor ending_splits_in
AntoinePrv Nov 3, 2023
6eeb1b9
Code improvement
AntoinePrv Nov 3, 2023
acb889c
Replace get_common_parts with concat_dedup
AntoinePrv Nov 6, 2023
8499dc9
Remove Channel::name
AntoinePrv Nov 6, 2023
2a17059
Remove Channel::location
AntoinePrv Nov 6, 2023
704c97d
Use URL for priority in channel loader
AntoinePrv Nov 6, 2023
ea122a4
Make Channel value-based
AntoinePrv Nov 6, 2023
df806fa
Add range hashing
AntoinePrv Nov 6, 2023
3eae72a
Add Channel comparison and hash
AntoinePrv Nov 6, 2023
65a9fdb
Make channel map/list return by value
AntoinePrv Nov 7, 2023
c42db23
Resolve 1
AntoinePrv Nov 10, 2023
087faf1
Resolve 2
AntoinePrv Nov 10, 2023
bd8e88b
Resolve 3
AntoinePrv Nov 10, 2023
2173d6b
Remove unknown channels
AntoinePrv Nov 10, 2023
838b8fb
Hide get_known_platforms
AntoinePrv Nov 10, 2023
a2d3d37
Add unknown ChannelSpec
AntoinePrv Nov 13, 2023
c7a93a1
Remove unused function
AntoinePrv Nov 13, 2023
33628c7
Rename Channel::canonical_name > display_name
AntoinePrv Nov 15, 2023
891a4bb
Remove Channel friend class
AntoinePrv Nov 15, 2023
c85659f
Add Channel::resolve
AntoinePrv Nov 15, 2023
ff79bf0
Remove ChannelContext::from_value
AntoinePrv Nov 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Taskfile.dist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ tasks:
Mamba. Many tasks are automatically run inside this environment.
The environment is located at "{{.DEV_ENV_DIR}}" and can also be activated with micromamba to
benefit from the executables and LSP tools.
cmds: [{task: '_create-env', vars: {prefix: '{{.DEV_ENV_DIR}}'}}]
cmds: [{task: '_create-env', vars: {prefix: '{{.PWD}}/{{.DEV_ENV_DIR}}'}}]

create-test-env:
desc: Create a local test environment with as a copy of the dev environment.
Expand Down
101 changes: 49 additions & 52 deletions libmamba/include/mamba/core/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#ifndef MAMBA_CORE_CHANNEL_HPP
#define MAMBA_CORE_CHANNEL_HPP

#include <map>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>

#include "mamba/specs/conda_url.hpp"
Expand All @@ -26,27 +26,43 @@ namespace mamba
namespace specs
{
class ChannelSpec;
class AuthenticationDataBase;
}

std::vector<std::string> get_known_platforms();

// Note: Channels can only be created using ChannelContext.
class Channel
{
public:

Channel(const Channel&) = delete;
Channel& operator=(const Channel&) = delete;
Channel(Channel&&) noexcept = default;
Channel& operator=(Channel&&) noexcept = default;
struct ResolveParams
{
using platform_list = util::flat_set<std::string>;
using channel_list = std::vector<Channel>;
using channel_map = std::map<std::string, Channel>;
using multichannel_map = std::unordered_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
};

using platform_list = util::flat_set<std::string>;

~Channel();
[[nodiscard]] static auto resolve(specs::ChannelSpec spec, ResolveParams params) -> Channel;

const std::string& location() const;
const std::string& name() const;
const std::string& canonical_name() const;
const util::flat_set<std::string>& platforms() const;
const specs::CondaURL& url() const;
Channel(specs::CondaURL url, std::string display_name, util::flat_set<std::string> platforms = {});

[[nodiscard]] auto url() const -> const specs::CondaURL&;
void set_url(specs::CondaURL url);

[[nodiscard]] auto platforms() const -> const platform_list&;
void set_platforms(platform_list platforms);

[[nodiscard]] auto display_name() const -> const 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;
Expand All @@ -57,38 +73,33 @@ namespace mamba

private:

Channel(
specs::CondaURL url,
std::string location,
std::string name,
std::string canonical_name,
util::flat_set<std::string> platforms = {}
);

specs::CondaURL m_url;
std::string m_location;
std::string m_name;
std::string m_canonical_name;
std::string m_display_name;
util::flat_set<std::string> m_platforms;

// Note: as long as Channel is not a regular value-type and we want each
// instance only possible to create through ChannelContext, we need
// to have Channel's constructor only available to ChannelContext,
// therefore enabling it's use through this `friend` statement.
// However, all this should be removed as soon as Channel is changed to
// be a regular value-type (regular as in the regular concept).
friend class ChannelContext;
};

using ChannelCache = std::map<std::string, Channel>;
/** Tuple-like equality of all observable members */
auto operator==(const Channel& a, const Channel& b) -> bool;
auto operator!=(const Channel& a, const Channel& b) -> bool;
}

template <>
struct std::hash<mamba::Channel>
{
auto operator()(const mamba::Channel& c) const -> std::size_t;
};


namespace mamba
{

class ChannelContext
{
public:

using channel_list = std::vector<std::string>;
using channel_map = std::map<std::string, Channel>;
using multichannel_map = std::map<std::string, std::vector<std::string>>;
using channel_list = std::vector<Channel>;
using multichannel_map = std::unordered_map<std::string, channel_list>;

ChannelContext(Context& context);
~ChannelContext();
Expand All @@ -99,7 +110,7 @@ namespace mamba
ChannelContext& operator=(ChannelContext&&) = delete;

const Channel& make_channel(const std::string& value);
std::vector<const Channel*> get_channels(const std::vector<std::string>& channel_names);
auto get_channels(const std::vector<std::string>& channel_names) -> channel_list;

const specs::CondaURL& get_channel_alias() const;
const channel_map& get_custom_channels() const;
Expand All @@ -112,29 +123,15 @@ namespace mamba

private:

using ChannelCache = std::map<std::string, Channel>;

Context& m_context;
ChannelCache m_channel_cache;
specs::CondaURL m_channel_alias;
channel_map m_custom_channels;
multichannel_map m_custom_multichannels;

void init_custom_channels();

Channel make_simple_channel(
const specs::CondaURL& channel_alias,
const std::string& channel_url,
const std::string& channel_name,
const std::string& channel_canonical_name
);

Channel from_any_path(specs::ChannelSpec&& spec);
Channel from_package_path(specs::ChannelSpec&& spec);
Channel from_path(specs::ChannelSpec&& spec);
Channel from_any_url(specs::ChannelSpec&& spec);
Channel from_package_url(specs::ChannelSpec&& spec);
Channel from_url(specs::ChannelSpec&& spec);
Channel from_name(specs::ChannelSpec&& spec);
Channel from_value(const std::string& value);
};

} // namespace mamba
Expand Down
19 changes: 16 additions & 3 deletions libmamba/include/mamba/specs/channel_spec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef MAMBA_SPECS_CHANNEL_SPEC_HPP
#define MAMBA_SPECS_CHANNEL_SPEC_HPP

#include <array>
#include <string>
#include <string_view>

Expand Down Expand Up @@ -63,10 +64,22 @@ namespace mamba::specs
* Example "conda-forge", "locals", "my-channel/my-label".
*/
Name,
/**
* An unknown channel source.
*
* It is currently unclear why it is needed.
*/
Unknown,
};

static constexpr std::string_view default_name = "defaults";
static constexpr std::string_view platform_separators = "|,;";
static constexpr std::string_view unknown_channel = "<unknown>";
static constexpr std::array<std::string_view, 4> invalid_channels_lower = {
"<unknown>",
"none:///<unknown>",
"none",
":///<unknown>",
};

using dynamic_platform_set = util::flat_set<std::string>;

Expand All @@ -87,9 +100,9 @@ namespace mamba::specs

private:

std::string m_location = std::string(default_name);
std::string m_location = std::string(unknown_channel);
dynamic_platform_set m_platform_filters = {};
Type m_type = {};
Type m_type = Type::Unknown;
};
}
#endif
32 changes: 24 additions & 8 deletions libmamba/include/mamba/util/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -192,6 +194,16 @@ namespace mamba::util
template <typename UnaryFunc>
std::array<std::wstring_view, 3> strip_if_parts(std::wstring_view input, UnaryFunc should_strip);

[[nodiscard]] auto split_once(std::string_view str, char sep)
-> std::tuple<std::string_view, std::optional<std::string_view>>;
[[nodiscard]] auto split_once(std::string_view str, std::string_view sep)
-> std::tuple<std::string_view, std::optional<std::string_view>>;

[[nodiscard]] auto rsplit_once(std::string_view str, char sep)
-> std::tuple<std::optional<std::string_view>, std::string_view>;
[[nodiscard]] auto rsplit_once(std::string_view str, std::string_view sep)
-> std::tuple<std::optional<std::string_view>, std::string_view>;

std::vector<std::string>
split(std::string_view input, std::string_view sep, std::size_t max_split = SIZE_MAX);
std::vector<std::wstring>
Expand All @@ -202,6 +214,18 @@ namespace mamba::util
std::vector<std::wstring>
rsplit(std::wstring_view input, std::wstring_view sep, std::size_t max_split = SIZE_MAX);

/**
* Concatenate string while removing the suffix of the first that may be prefix of second.
*
* Comparison are done as if comparing elements in a split given by @p sep.
* For instance "private/channel" and "channel/label/foo" with separator "/"
* would return "private/channel/label/foo", but "private/chan" and "channel/label/foo"
* would return the "private/chan/channel/label/foo".
*/
std::string concat_dedup_splits(std::string_view str1, std::string_view str2, char sep);
std::string
concat_dedup_splits(std::string_view str1, std::string_view str2, std::string_view sep);

void replace_all(std::string& data, std::string_view search, std::string_view replace);
void replace_all(std::wstring& data, std::wstring_view search, std::wstring_view replace);

Expand Down Expand Up @@ -643,14 +667,6 @@ namespace mamba::util
return hex_string(buffer, buffer.size());
}

/**
* Return the common parts of two strings by blocks located between the given sep,
* and considering that these common parts would be located at the end of str1 (search from
* left to right).
* str1 is considered smaller than (or equal to) str2.
* cf. Channels use case.
*/
std::string get_common_parts(std::string_view str1, std::string_view str2, std::string_view sep);
}

#endif
29 changes: 25 additions & 4 deletions libmamba/include/mamba/util/tuple_hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,41 @@

#include <functional>
#include <tuple>
#include <type_traits>

namespace mamba::util
{
constexpr void hash_combine(std::size_t& seed, std::size_t other)
constexpr auto hash_combine(std::size_t seed, std::size_t other) -> std::size_t
{
const auto boost_magic_num = 0x9e3779b9;
seed ^= other + boost_magic_num + (seed << 6) + (seed >> 2);
return seed;
}

template <class T, typename Hasher = std::hash<T>>
constexpr void hash_combine_val(std::size_t& seed, const T& val, const Hasher& hasher = {})
constexpr auto hash_combine_val(std::size_t seed, const T& val, const Hasher& hasher = {})
-> std::size_t
{
hash_combine(seed, hasher(val));
return hash_combine(seed, hasher(val));
}

template <typename Iter, typename Hasher = std::hash<std::decay_t<decltype(*std::declval<Iter>())>>>
auto hash_combine_val_range(std::size_t seed, Iter first, Iter last, const Hasher& hasher = {})
-> std::size_t
{
for (; first != last; ++first)
{
seed = hash_combine_val(seed, hasher(*first));
}
return seed;
}

template <typename... T>
constexpr auto hash_vals(const T&... vals) -> std::size_t
{
std::size_t seed = 0;
(hash_combine_val(seed, vals), ...);
auto combine = [&seed](const auto& val) { seed = hash_combine_val(seed, val); };
(combine(vals), ...);
return seed;
}

Expand All @@ -46,5 +61,11 @@ namespace mamba::util
return hash_tuple(t);
}
};

template <typename Range>
constexpr auto hash_range(const Range& rng) -> std::size_t
{
return hash_combine_val_range(0, rng.begin(), rng.end());
}
}
#endif
10 changes: 5 additions & 5 deletions libmamba/src/api/channel_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ namespace mamba

std::vector<std::pair<int, int>> priorities;
int max_prio = static_cast<int>(channel_urls.size());
std::string prev_channel_name;
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 (auto& [platform, url] : channel->platform_urls(true))
for (auto& [platform, url] : channel.platform_urls(true))
{
auto sdires = MSubdirData::create(
pool.channel_context(),
*channel,
channel,
platform,
url,
package_caches,
Expand All @@ -89,10 +89,10 @@ namespace mamba
else
{
// Consider 'flexible' and 'strict' the same way
if (channel->canonical_name() != prev_channel_name)
if (channel.url() != prev_channel_url)
{
max_prio--;
prev_channel_name = channel->canonical_name();
prev_channel_url = channel.url();
}
priorities.push_back(std::make_pair(max_prio, 0));
}
Expand Down
Loading