Skip to content

Commit

Permalink
Resolve ChannelSpec into a Channel (#2899)
Browse files Browse the repository at this point in the history
* Change URL custom_channel matcher

* Cannot change location at once

* Simpler channel_alias_location

* Change URL channel_alias matcher

* Refactor ChannelContext::from_url

* Add Windows URL path encoding test

* Simplify URL::set_path

* Fix URL encoding parsing

* Refactor platforms urls

* Fix missing forward declaration

* Fix Win file URL encoding

* Split Channel url functions

* Remove no-URL ctor from ChannelContext::from_name

* Remove no-URL ctor from ChannelContext::make_simple_channel

* Remove old Channel ctor

* Remove channel_alias_location

* Refactor Channel::base_url

* Try not to use location mamba.py

* Remove Channel comparison

* Try Channel::platform_url

* Refactor Channel::platform_urls to use platform_url

* Remove build_url

* Remove concat_scheme_url

* Use spec in from_name

* Tuple equality for URL

* Add tuple_hash

* Add std::hash<mamba::util::URL>

* Make CondaURL hashable

* Refactor make_channel

* New algorithm for authetification map

* Add specs::AutheticationDataBase

* Fix typo authentification > authentication

* Use AuthenticationDataBase

* Fix AuthenticationDataBase

* use AuthenticationDataBase::find_compatible

* Use canonical_name

* Add Credential check to URL

* Simplify crendential check in channel

* Refactor AuthDB credential setters

* No Channel::location in tests

* Remove Channel user scheme password

* Document AuthenticationInfo

* Remove Channel token

* Remove Channel::auth

* Remove Channel::package_name

* More replacement name > canonical_name

* Remove unused function

* No credential from URLs

* Remove unneeded header

* Disable Channel::repo_checker

This is disbled as TUF implementation is not well defined and this
function is not used except in experimental conditions.

* Apply auth info as needed

* Simplify custom_channels instanciation

* Simplify custom_multi_channels instanciation

* Review improvements
  • Loading branch information
AntoinePrv authored Oct 25, 2023
1 parent f23e078 commit c7aba97
Show file tree
Hide file tree
Showing 37 changed files with 913 additions and 808 deletions.
4 changes: 3 additions & 1 deletion libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ set(LIBMAMBA_SOURCES
${LIBMAMBA_SOURCE_DIR}/core/compression.cpp
# Implementation of version and matching specs
${LIBMAMBA_SOURCE_DIR}/specs/archive.cpp
${LIBMAMBA_SOURCE_DIR}/specs/authentication_info.cpp
${LIBMAMBA_SOURCE_DIR}/specs/platform.cpp
${LIBMAMBA_SOURCE_DIR}/specs/conda_url.cpp
${LIBMAMBA_SOURCE_DIR}/specs/version.cpp
Expand Down Expand Up @@ -227,10 +228,11 @@ set(LIBMAMBA_PUBLIC_HEADERS
${LIBMAMBA_INCLUDE_DIR}/mamba/util/iterator.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/string.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/path_manip.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/tuple_hash.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/url_manip.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/util/url.hpp
# Implementation of version and matching specs
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/authentification_info.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/authentication_info.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/archive.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/platform.hpp
${LIBMAMBA_INCLUDE_DIR}/mamba/specs/conda_url.hpp
Expand Down
38 changes: 5 additions & 33 deletions libmamba/include/mamba/core/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#define MAMBA_CORE_CHANNEL_HPP

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
Expand Down Expand Up @@ -44,40 +42,21 @@ namespace mamba

~Channel();

std::string_view scheme() const;
const std::string& location() const;
const std::string& name() const;
const std::string& canonical_name() const;
const util::flat_set<std::string>& platforms() const;
std::optional<std::string> auth() const;
std::optional<std::string> user() const;
std::optional<std::string> password() const;
std::optional<std::string> token() const;
std::optional<std::string> package_filename() const;
const validation::RepoChecker&
repo_checker(Context& context, MultiPackageCache& caches) const;
const specs::CondaURL& url() const;

std::string base_url() const;
std::string platform_url(std::string platform, bool with_credential = true) const;
std::string platform_url(std::string_view platform, bool with_credential = true) const;
// 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;

private:

Channel(
std::string_view scheme,
std::string location,
std::string name,
std::string canonical_name,
std::string_view user = {},
std::string_view password = {},
std::string_view token = {},
std::string_view package_filename = {},
util::flat_set<std::string> platforms = {}
);

Channel(
specs::CondaURL url,
std::string location,
Expand All @@ -86,17 +65,12 @@ namespace mamba
util::flat_set<std::string> platforms = {}
);

const specs::CondaURL& url() const;

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

// This is used to make sure that there is a unique repo for every channel
mutable std::unique_ptr<validation::RepoChecker> p_repo_checker;

// 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,
Expand All @@ -106,10 +80,6 @@ namespace mamba
friend class ChannelContext;
};

bool operator==(const Channel& lhs, const Channel& rhs);
bool operator!=(const Channel& lhs, const Channel& rhs);


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

class ChannelContext
Expand Down Expand Up @@ -160,8 +130,10 @@ namespace mamba
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(const std::string& name);
Channel from_name(specs::ChannelSpec&& spec);
Channel from_value(const std::string& value);
};

Expand Down
9 changes: 4 additions & 5 deletions libmamba/include/mamba/core/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "mamba/core/palette.hpp"
#include "mamba/core/tasksync.hpp"
#include "mamba/fs/filesystem.hpp"
#include "mamba/specs/authentification_info.hpp"
#include "mamba/specs/authentication_info.hpp"
#include "mamba/specs/platform.hpp"
#include "mamba/version.hpp"

Expand Down Expand Up @@ -214,9 +214,8 @@ namespace mamba
};

std::string channel_alias = "https://conda.anaconda.org";
using authentication_info_map_t = std::map<std::string, specs::AuthenticationInfo>;
authentication_info_map_t& authentication_info();
const authentication_info_map_t& authentication_info() const;
specs::AuthenticationDataBase& authentication_info();
const specs::AuthenticationDataBase& authentication_info() const;
std::vector<fs::u8path> token_locations{ "~/.continuum/anaconda-client/tokens" };

bool override_channels_enabled = true;
Expand Down Expand Up @@ -253,7 +252,7 @@ namespace mamba
bool on_ci = false;

void load_authentication_info();
std::map<std::string, specs::AuthenticationInfo> m_authentication_info;
specs::AuthenticationDataBase m_authentication_info;
bool m_authentication_infos_loaded = false;

std::shared_ptr<Logger> logger;
Expand Down
2 changes: 2 additions & 0 deletions libmamba/include/mamba/core/query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "mamba/core/pool.hpp"
#include "mamba/util/graph.hpp"

typedef struct s_Solvable Solvable;

namespace mamba
{
using GraphicsParams = Context::GraphicsParams;
Expand Down
7 changes: 0 additions & 7 deletions libmamba/include/mamba/core/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,6 @@ namespace mamba
void split_package_extension(const std::string& file, std::string& name, std::string& extension);
fs::u8path strip_package_extension(const std::string& file);

template <class T>
inline bool vector_is_prefix(const std::vector<T>& prefix, const std::vector<T>& vec)
{
return vec.size() >= prefix.size()
&& prefix.end() == std::mismatch(prefix.begin(), prefix.end(), vec.begin()).first;
}

tl::expected<std::string, mamba_error> encode_base64(std::string_view input);
tl::expected<std::string, mamba_error> decode_base64(std::string_view input);

Expand Down
106 changes: 106 additions & 0 deletions libmamba/include/mamba/specs/authentication_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_SPECS_AUTHENTICATION_INFO_HPP
#define MAMBA_SPECS_AUTHENTICATION_INFO_HPP

#include <string>
#include <unordered_map>
#include <variant>

namespace mamba::specs
{
class CondaURL;

/** User and password authetification set in the URL. */
struct BasicHTTPAuthentication
{
std::string user;
std::string password;
};

/** HTTP Bearer token set in the request headers. */
struct BearerToken
{
std::string token;
};

/** A Conda token set in the URL path. */
struct CondaToken
{
std::string token;
};

using AuthenticationInfo = std::variant<BasicHTTPAuthentication, BearerToken, CondaToken>;

/**
* A class that holds the authentication info stored by users.
*
* Essentially a map, except that some keys can match mutliple queries.
* For instance "mamba.org/private" should be matched by queries "mamba.org/private",
* "mamba.org/private/channel", but not "mamba.org/public".
*
* A best effort is made to satifiy this with `xxx_compatible`.
*
* Future development of this class should aim to replace the map and keys with a
* `AuthenticationSpec`, that can decide whether or not a URL should benefit from such
* its authentication.
* Possibly, a string reprensentation such as "*.mamba.org/private/channel*" could be added
* to parse users intentions, rather than relying on the assumptions made here.
*/
class AuthenticationDataBase : private std::unordered_map<std::string, AuthenticationInfo>
{
public:

using Base = std::unordered_map<std::string, AuthenticationInfo>;

using typename Base::key_type;
using typename Base::mapped_type;
using typename Base::value_type;
using typename Base::size_type;
using typename Base::iterator;
using typename Base::const_iterator;

using Base::Base;

using Base::begin;
using Base::end;
using Base::cbegin;
using Base::cend;

using Base::empty;
using Base::size;
using Base::max_size;

using Base::clear;
using Base::insert;
using Base::insert_or_assign;
using Base::emplace;
using Base::emplace_hint;
using Base::try_emplace;
using Base::erase;
using Base::swap;
using Base::extract;
using Base::merge;

using Base::reserve;

using Base::at;

[[nodiscard]] auto at_compatible(const key_type& key) -> mapped_type&;
[[nodiscard]] auto at_compatible(const key_type& key) const -> const mapped_type&;

using Base::find;

auto find_compatible(const key_type& key) -> iterator;
auto find_compatible(const key_type& key) const -> const_iterator;

[[nodiscard]] auto contains(const key_type& key) const -> bool;

[[nodiscard]] auto contains_compatible(const key_type& key) const -> bool;
};
}
#endif
36 changes: 0 additions & 36 deletions libmamba/include/mamba/specs/authentification_info.hpp

This file was deleted.

17 changes: 16 additions & 1 deletion libmamba/include/mamba/specs/conda_url.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#ifndef MAMBA_SPECS_CONDA_URL_HPP
#define MAMBA_SPECS_CONDA_URL_HPP

#include <functional>
#include <string_view>

#include "mamba/specs/platform.hpp"
Expand Down Expand Up @@ -34,13 +35,17 @@ namespace mamba::specs
explicit CondaURL(util::URL&& url);
explicit CondaURL(const util::URL& url);

auto base() const -> const util::URL&;

using Base::scheme_is_defaulted;
using Base::scheme;
using Base::set_scheme;
using Base::clear_scheme;
using Base::has_user;
using Base::user;
using Base::set_user;
using Base::clear_user;
using Base::has_password;
using Base::password;
using Base::set_password;
using Base::clear_password;
Expand Down Expand Up @@ -99,6 +104,9 @@ namespace mamba::specs
*/
void append_path(std::string_view path, Encode::no_type);

/** Return wether a token is set. */
[[nodiscard]] auto has_token() const -> bool;

/** Return the Conda token, as delimited with "/t/", or empty if there isn't any. */
[[nodiscard]] auto token() const -> std::string_view;

Expand Down Expand Up @@ -226,12 +234,19 @@ namespace mamba::specs
friend auto operator==(const CondaURL&, const CondaURL&) -> bool;
};

/** Compare two CondaURL. */
/** Tuple-like equality of all observable members */
auto operator==(const CondaURL& a, const CondaURL& b) -> bool;
auto operator!=(const CondaURL& a, const CondaURL& b) -> bool;

/** A functional equivalent to ``CondaURL::append_path``. */
auto operator/(const CondaURL& url, std::string_view subpath) -> CondaURL;
auto operator/(CondaURL&& url, std::string_view subpath) -> CondaURL;
}

template <>
struct std::hash<mamba::specs::CondaURL>
{
auto operator()(const mamba::specs::CondaURL& p) const -> std::size_t;
};

#endif
Loading

0 comments on commit c7aba97

Please sign in to comment.