mirror of https://github.com/mamba-org/mamba.git
Fix VersionSpec free ranges (#3088)
This commit is contained in:
parent
4ee7531fd6
commit
3f6484c23c
|
@ -7,6 +7,7 @@
|
|||
#ifndef MAMBA_SPECS_VERSION_SPEC_HPP
|
||||
#define MAMBA_SPECS_VERSION_SPEC_HPP
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
#include <variant>
|
||||
|
@ -128,6 +129,8 @@ namespace mamba::specs
|
|||
static constexpr char left_parenthesis_token = '(';
|
||||
static constexpr char right_parenthesis_token = ')';
|
||||
|
||||
static constexpr std::string_view prefered_free_str = "=*";
|
||||
static constexpr std::array<std::string_view, 4> all_free_strs = { "", "*", "=*", "==*" };
|
||||
static constexpr std::string_view starts_with_str = "=";
|
||||
static constexpr std::string_view equal_str = "==";
|
||||
static constexpr std::string_view not_equal_str = "!=";
|
||||
|
|
|
@ -290,16 +290,17 @@ namespace mamba::specs
|
|||
|
||||
namespace
|
||||
{
|
||||
auto is_char(std::string_view str, char c) -> bool
|
||||
template <typename Val, typename Range>
|
||||
constexpr auto equal_any(const Val& val, const Range& range) -> bool
|
||||
{
|
||||
return (str.size() == 1) && (str.front() == c);
|
||||
return std::find(range.cbegin(), range.cend(), val) != range.cend();
|
||||
}
|
||||
|
||||
auto parse_op_and_version(std::string_view str) -> VersionPredicate
|
||||
{
|
||||
str = util::strip(str);
|
||||
// WARNING order is important since some operator are prefix of others.
|
||||
if (str.empty() || is_char(str, VersionSpec::glob_suffix_token))
|
||||
if (str.empty() || equal_any(str, VersionSpec::all_free_strs))
|
||||
{
|
||||
return VersionPredicate::make_free();
|
||||
}
|
||||
|
@ -331,7 +332,7 @@ namespace mamba::specs
|
|||
{
|
||||
auto ver = Version::parse(str.substr(VersionSpec::compatible_str.size()));
|
||||
// in ``~=1.1`` level is assumed to be 1, in ``~=1.1.1`` level 2, etc.
|
||||
static constexpr std::size_t one = std::size_t(1); // MSVC
|
||||
static constexpr auto one = std::size_t(1); // MSVC
|
||||
const std::size_t level = std::max(ver.version().size(), one) - one;
|
||||
return VersionPredicate::make_compatible_with(std::move(ver), level);
|
||||
}
|
||||
|
@ -381,7 +382,7 @@ namespace mamba::specs
|
|||
if (util::ends_with(str, VersionSpec::glob_suffix_token))
|
||||
{
|
||||
// either ".*" or "*"
|
||||
static constexpr std::size_t one = std::size_t(1); // MSVC
|
||||
static constexpr auto one = std::size_t(1); // MSVC
|
||||
const std::size_t len = str.size() - std::max(glob_len, one);
|
||||
return VersionPredicate::make_starts_with(Version::parse(str.substr(0, len)));
|
||||
}
|
||||
|
@ -409,6 +410,15 @@ namespace mamba::specs
|
|||
|
||||
auto parser = util::InfixParser<VersionPredicate, util::BoolOperator>();
|
||||
str = util::lstrip(str);
|
||||
|
||||
// Explicit short-circuiting for "free" spec
|
||||
// This case would be handled anyway but we can avoid allocating a tree in this
|
||||
// likely case.
|
||||
if (str.empty() || equal_any(str, VersionSpec::all_free_strs))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
while (!str.empty())
|
||||
{
|
||||
if (str.front() == VersionSpec::and_token)
|
||||
|
@ -468,11 +478,16 @@ fmt::formatter<mamba::specs::VersionSpec>::format(
|
|||
format_context& ctx
|
||||
) -> decltype(ctx.out())
|
||||
{
|
||||
using VersionSpec = typename mamba::specs::VersionSpec;
|
||||
|
||||
auto out = ctx.out();
|
||||
if (spec.m_tree.empty())
|
||||
{
|
||||
return fmt::format_to(out, "{}", VersionSpec::prefered_free_str);
|
||||
}
|
||||
spec.m_tree.infix_for_each(
|
||||
[&](const auto& token)
|
||||
{
|
||||
using VersionSpec = typename mamba::specs::VersionSpec;
|
||||
using tree_type = typename VersionSpec::tree_type;
|
||||
using Token = std::decay_t<decltype(token)>;
|
||||
if constexpr (std::is_same_v<Token, tree_type::LeftParenthesis>)
|
||||
|
|
|
@ -122,6 +122,7 @@ TEST_SUITE("specs::version_spec")
|
|||
{
|
||||
auto spec = VersionSpec();
|
||||
CHECK(spec.contains(Version()));
|
||||
CHECK_EQ(spec.str(), "=*");
|
||||
}
|
||||
|
||||
SUBCASE("<2.0|(>2.3,<=2.8.0)")
|
||||
|
@ -168,6 +169,9 @@ TEST_SUITE("specs::version_spec")
|
|||
CHECK(""_vs.contains("1.6"_v));
|
||||
CHECK(""_vs.contains("0.6+0.7"_v));
|
||||
|
||||
CHECK("*"_vs.contains("1.4"_v));
|
||||
CHECK("=*"_vs.contains("1.4"_v));
|
||||
|
||||
CHECK("1.7"_vs.contains("1.7"_v));
|
||||
CHECK("1.7"_vs.contains("1.7.0.0"_v));
|
||||
CHECK_FALSE("1.7"_vs.contains("1.6"_v));
|
||||
|
|
|
@ -550,6 +550,8 @@ namespace mambapy
|
|||
.def_readonly_static("or_token", &VersionSpec::or_token)
|
||||
.def_readonly_static("left_parenthesis_token", &VersionSpec::left_parenthesis_token)
|
||||
.def_readonly_static("right_parenthesis_token", &VersionSpec::right_parenthesis_token)
|
||||
.def_readonly_static("prefered_free_str", &VersionSpec::prefered_free_str)
|
||||
.def_readonly_static("all_free_strs", &VersionSpec::all_free_strs)
|
||||
.def_readonly_static("starts_with_str", &VersionSpec::starts_with_str)
|
||||
.def_readonly_static("equal_str", &VersionSpec::equal_str)
|
||||
.def_readonly_static("not_equal_str", &VersionSpec::not_equal_str)
|
||||
|
|
|
@ -635,6 +635,8 @@ def test_VersionSpec():
|
|||
assert isinstance(VersionSpec.or_token, str)
|
||||
assert isinstance(VersionSpec.left_parenthesis_token, str)
|
||||
assert isinstance(VersionSpec.right_parenthesis_token, str)
|
||||
assert isinstance(VersionSpec.prefered_free_str, str)
|
||||
assert isinstance(VersionSpec.all_free_strs, list)
|
||||
assert isinstance(VersionSpec.starts_with_str, str)
|
||||
assert isinstance(VersionSpec.equal_str, str)
|
||||
assert isinstance(VersionSpec.not_equal_str, str)
|
||||
|
|
Loading…
Reference in New Issue