Skip to content

Commit

Permalink
Add unknown ChannelSpec
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoinePrv committed Nov 13, 2023
1 parent ddaa356 commit af6df40
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 9 deletions.
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
4 changes: 4 additions & 0 deletions libmamba/src/core/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,10 @@ namespace mamba
{
return resolve_name(std::move(spec), params);
}
case specs::ChannelSpec::Type::Unknown:
{
return Channel(specs::CondaURL{}, spec.clear_location());
}
}
throw std::invalid_argument("Invalid ChannelSpec::Type");
}
Expand Down
26 changes: 23 additions & 3 deletions libmamba/src/specs/channel_spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
//
// The full license is in the file LICENSE, distributed with this software.

#include <algorithm>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <tuple>
Expand Down Expand Up @@ -108,14 +110,24 @@ namespace mamba::specs
out = util::rstrip(out, '/');
return out;
}

auto is_unknown_channel(std::string_view str) -> bool
{
auto it = std::find(
ChannelSpec::invalid_channels_lower.cbegin(),
ChannelSpec::invalid_channels_lower.cend(),
util::to_lower(str)
);
return str.empty() || (it != ChannelSpec::invalid_channels_lower.cend());
}
}

auto ChannelSpec::parse(std::string_view str) -> ChannelSpec
{
str = util::strip(str);
if (str.empty())
if (is_unknown_channel(str))
{
return {};
return { std::string(unknown_channel), {}, Type::Unknown };
}

auto [location, filters] = split_location_platform(str);
Expand Down Expand Up @@ -148,9 +160,17 @@ namespace mamba::specs
, m_platform_filters(std::move(filters))
, m_type(type)
{
if (m_type == Type::Unknown)
{
m_location = unknown_channel;
m_platform_filters = {};
}
if (m_location.empty())
{
m_location = std::string(default_name);
throw std::invalid_argument( //
"Cannot channel with empty location, "
"use unknown type instead."
);
}
}

Expand Down
34 changes: 31 additions & 3 deletions libmamba/tests/src/specs/test_channel_spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,50 @@

#include <doctest/doctest.h>

#include "mamba/fs/filesystem.hpp"
#include "mamba/specs/channel_spec.hpp"
#include "mamba/util/build.hpp"
#include "mamba/util/path_manip.hpp"
#include "mamba/util/string.hpp"

using namespace mamba;
using namespace mamba::specs;

TEST_SUITE("specs::channel_spec")
{
TEST_CASE("Constructor")
{
SUBCASE("Default")
{
const auto spec = ChannelSpec();
CHECK_EQ(spec.type(), ChannelSpec::Type::Unknown);
CHECK_EQ(spec.location(), "<unknown>");
CHECK(spec.platform_filters().empty());
}

SUBCASE("Unknown")
{
const auto spec = ChannelSpec("hello", { "linux-78" }, ChannelSpec::Type::Unknown);
CHECK_EQ(spec.type(), ChannelSpec::Type::Unknown);
CHECK_EQ(spec.location(), "<unknown>");
CHECK(spec.platform_filters().empty());
}
}

TEST_CASE("Parsing")
{
using Type = typename ChannelSpec::Type;
using PlatformSet = typename util::flat_set<std::string>;

SUBCASE("Invalid channels")
{
for (std::string_view str : { "", "<unknown>", ":///<unknown>", "none" })
{
CAPTURE(str);
const auto spec = ChannelSpec::parse(str);
CHECK_EQ(spec.type(), Type::Unknown);
CHECK_EQ(spec.location(), "<unknown>");
CHECK_EQ(spec.platform_filters(), PlatformSet{});
}
}

SUBCASE("https://repo.anaconda.com/conda-forge")
{
const auto spec = ChannelSpec::parse("https://repo.anaconda.com/conda-forge");
Expand Down

0 comments on commit af6df40

Please sign in to comment.