mirror of https://github.com/mamba-org/mamba.git
Pool channel match (#3122)
* Add Match return type to Channel::contains_package * Simplify channel specific matchspec in Pool * (Dirty) fix force reinstall
This commit is contained in:
parent
f72364d404
commit
8ab10efa07
|
@ -107,13 +107,20 @@ namespace mamba::specs
|
||||||
auto clear_display_name() -> std::string;
|
auto clear_display_name() -> std::string;
|
||||||
void set_display_name(std::string display_name);
|
void set_display_name(std::string display_name);
|
||||||
|
|
||||||
|
enum struct Match
|
||||||
|
{
|
||||||
|
No,
|
||||||
|
InOtherPlatform,
|
||||||
|
Full,
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] auto url_equivalent_with(const Channel& other) const -> bool;
|
[[nodiscard]] auto url_equivalent_with(const Channel& other) const -> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto is_equivalent_to(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 contains_equivalent(const Channel& other) const -> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto contains_package(const CondaURL& pkg) const -> bool;
|
[[nodiscard]] auto contains_package(const CondaURL& pkg) const -> Match;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -140,37 +140,28 @@ namespace mamba
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
enum struct ChannelMatch
|
auto
|
||||||
|
channel_match(const std::vector<specs::Channel>& ms_channels, const specs::CondaURL& pkg_url)
|
||||||
|
-> specs::Channel::Match
|
||||||
{
|
{
|
||||||
None,
|
auto match = specs::Channel::Match::No;
|
||||||
ChannelOnly,
|
// More than one element means the channel spec was a custom_multi_channel
|
||||||
ChannelAndSubdir,
|
for (const auto& chan : ms_channels)
|
||||||
};
|
|
||||||
|
|
||||||
auto channel_match(
|
|
||||||
const std::vector<specs::Channel>& repo_channels,
|
|
||||||
const std::vector<specs::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)
|
|
||||||
{
|
{
|
||||||
// More than one element means the channel spec was a custom_multi_channel.
|
switch (chan.contains_package(pkg_url))
|
||||||
// We need to add any repo that matches.
|
|
||||||
for (const auto& cand_chan : candidate_channels)
|
|
||||||
{
|
{
|
||||||
if (repo_chan.url_equivalent_with(cand_chan))
|
case specs::Channel::Match::Full:
|
||||||
{
|
return specs::Channel::Match::Full;
|
||||||
if (util::set_is_subset_of(repo_chan.platforms(), cand_chan.platforms()))
|
case specs::Channel::Match::InOtherPlatform:
|
||||||
{
|
// Keep looking for full matches
|
||||||
return ChannelMatch::ChannelAndSubdir;
|
match = specs::Channel::Match::InOtherPlatform;
|
||||||
}
|
break;
|
||||||
return ChannelMatch::ChannelOnly;
|
case specs::Channel::Match::No:
|
||||||
}
|
// No overriding potential InOtherPlatform match
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ChannelMatch::None;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,7 +189,7 @@ namespace mamba
|
||||||
ms.conda_build_form().c_str()
|
ms.conda_build_form().c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
auto ms_channel = channel_context.make_channel(*ms.channel());
|
auto ms_channels = channel_context.make_channel(*ms.channel());
|
||||||
|
|
||||||
solv::ObjQueue selected_pkgs = {};
|
solv::ObjQueue selected_pkgs = {};
|
||||||
auto other_subdir_match = std::string();
|
auto other_subdir_match = std::string();
|
||||||
|
@ -206,28 +197,32 @@ namespace mamba
|
||||||
match,
|
match,
|
||||||
[&](solv::ObjSolvableViewConst s)
|
[&](solv::ObjSolvableViewConst s)
|
||||||
{
|
{
|
||||||
|
if (s.installed())
|
||||||
|
{
|
||||||
|
// This will have the effect that channel-specific MatchSpec will always be
|
||||||
|
// reinstalled.
|
||||||
|
// This is not the intended behaviour but an historical artifact on which
|
||||||
|
// ``--force-reinstall`` currently rely.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(ms.channel().has_value());
|
assert(ms.channel().has_value());
|
||||||
// TODO this does not work with s.url(), we need to proper channel class
|
const auto match = channel_match(ms_channels, specs::CondaURL::parse(s.url()));
|
||||||
// to properly manage this.
|
|
||||||
auto repo = solv::ObjRepoView(*s.raw()->repo);
|
|
||||||
const auto match = channel_match(
|
|
||||||
channel_context.make_channel(repo.url()),
|
|
||||||
ms_channel
|
|
||||||
);
|
|
||||||
switch (match)
|
switch (match)
|
||||||
{
|
{
|
||||||
case (ChannelMatch::ChannelAndSubdir):
|
case (specs::Channel::Match::Full):
|
||||||
{
|
{
|
||||||
selected_pkgs.push_back(s.id());
|
selected_pkgs.push_back(s.id());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (ChannelMatch::ChannelOnly):
|
case (specs::Channel::Match::InOtherPlatform):
|
||||||
{
|
{
|
||||||
other_subdir_match = s.subdir();
|
other_subdir_match = s.subdir();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (ChannelMatch::None):
|
case (specs::Channel::Match::No):
|
||||||
{
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,26 +155,27 @@ namespace mamba::specs
|
||||||
{
|
{
|
||||||
if (other.is_package())
|
if (other.is_package())
|
||||||
{
|
{
|
||||||
return contains_package(other.url());
|
return contains_package(other.url()) == Match::Full;
|
||||||
}
|
}
|
||||||
return url_equivalent_with(other) && util::set_is_superset_of(platforms(), other.platforms());
|
return url_equivalent_with(other) && util::set_is_superset_of(platforms(), other.platforms());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Channel::contains_package(const CondaURL& pkg) const -> bool
|
auto Channel::contains_package(const CondaURL& pkg) const -> Match
|
||||||
{
|
{
|
||||||
if (is_package())
|
if (is_package())
|
||||||
{
|
{
|
||||||
return url_equivalent_with_impl(url(), pkg);
|
return url_equivalent_with_impl(url(), pkg) ? Match::Full : Match::No;
|
||||||
}
|
|
||||||
if (!platforms().contains(std::string(pkg.platform_name())))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pkg_repo = pkg;
|
auto pkg_repo = pkg;
|
||||||
pkg_repo.clear_platform();
|
const auto plat = std::string(pkg_repo.platform_name());
|
||||||
pkg_repo.clear_package();
|
pkg_repo.clear_package();
|
||||||
return url_equivalent_with_impl(url(), pkg_repo);
|
pkg_repo.clear_platform();
|
||||||
|
if (url_equivalent_with_impl(url(), pkg_repo))
|
||||||
|
{
|
||||||
|
return platforms().contains(plat) ? Match::Full : Match::InOtherPlatform;
|
||||||
|
}
|
||||||
|
return Match::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
|
|
|
@ -182,34 +182,48 @@ TEST_SUITE("specs::channel")
|
||||||
SUBCASE("Contains package")
|
SUBCASE("Contains package")
|
||||||
{
|
{
|
||||||
using namespace conda_url_literals;
|
using namespace conda_url_literals;
|
||||||
|
using Match = Channel::Match;
|
||||||
|
|
||||||
SUBCASE("https://repo.mamba.pm/")
|
SUBCASE("https://repo.mamba.pm/")
|
||||||
{
|
{
|
||||||
auto chan = Channel("https://repo.mamba.pm/"_cu, "conda-forge", { "linux-64" });
|
auto chan = Channel("https://repo.mamba.pm/"_cu, "conda-forge", { "linux-64" });
|
||||||
CHECK(chan.contains_package("https://repo.mamba.pm/linux-64/pkg.conda"_cu));
|
CHECK_EQ(
|
||||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu));
|
chan.contains_package("https://repo.mamba.pm/linux-64/pkg.conda"_cu),
|
||||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu));
|
Match::Full
|
||||||
|
);
|
||||||
|
CHECK_EQ(
|
||||||
|
chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu),
|
||||||
|
Match::InOtherPlatform
|
||||||
|
);
|
||||||
|
CHECK_EQ(
|
||||||
|
chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu),
|
||||||
|
Match::InOtherPlatform
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("https://repo.mamba.pm/osx-64/foo.tar.gz")
|
SUBCASE("https://repo.mamba.pm/osx-64/foo.tar.gz")
|
||||||
{
|
{
|
||||||
auto chan = Channel("https://repo.mamba.pm/osx-64/foo.tar.bz2"_cu, "", {});
|
auto chan = Channel("https://repo.mamba.pm/osx-64/foo.tar.bz2"_cu, "", {});
|
||||||
CHECK(chan.contains_package(chan.url()));
|
CHECK_EQ(chan.contains_package(chan.url()), Match::Full);
|
||||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu));
|
CHECK_EQ(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu), Match::No);
|
||||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu));
|
CHECK_EQ(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu), Match::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("https://user:pass@repo.mamba.pm/conda-forge/win-64/")
|
SUBCASE("https://user:pass@repo.mamba.pm/conda-forge/")
|
||||||
{
|
{
|
||||||
auto chan = Channel(
|
auto chan = Channel(
|
||||||
"https://user:pass@repo.mamba.pm/conda-forge/"_cu,
|
"https://user:pass@repo.mamba.pm/conda-forge/"_cu,
|
||||||
"conda-forge",
|
"conda-forge",
|
||||||
{ "win-64" }
|
{ "win-64" }
|
||||||
);
|
);
|
||||||
CHECK(chan.contains_package(chan.url() / "win-64/pkg.conda"));
|
CHECK_EQ(chan.contains_package(chan.url() / "win-64/pkg.conda"), Match::Full);
|
||||||
CHECK(chan.contains_package("https://repo.mamba.pm/conda-forge/win-64/pkg.conda"_cu));
|
CHECK_EQ(
|
||||||
CHECK_FALSE(
|
chan.contains_package("https://repo.mamba.pm/conda-forge/win-64/pkg.conda"_cu),
|
||||||
chan.contains_package("https://repo.mamba.pm/conda-forge/osx-64/pkg.conda"_cu)
|
Match::Full
|
||||||
|
);
|
||||||
|
CHECK_EQ(
|
||||||
|
chan.contains_package("https://repo.mamba.pm/conda-forge/osx-64/pkg.conda"_cu),
|
||||||
|
Match::InOtherPlatform
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,6 +424,13 @@ namespace mambapy
|
||||||
.def("__copy__", ©<BasicHTTPAuthentication>)
|
.def("__copy__", ©<BasicHTTPAuthentication>)
|
||||||
.def("__deepcopy__", &deepcopy<BasicHTTPAuthentication>, py::arg("memo"));
|
.def("__deepcopy__", &deepcopy<BasicHTTPAuthentication>, py::arg("memo"));
|
||||||
|
|
||||||
|
py::enum_<Channel::Match>(py_channel, "Match")
|
||||||
|
.value("No", Channel::Match::No)
|
||||||
|
.value("InOtherPlatform", Channel::Match::InOtherPlatform)
|
||||||
|
.value("Full", Channel::Match::Full)
|
||||||
|
.def(py::init(&enum_from_str<Channel::Match>));
|
||||||
|
py::implicitly_convertible<py::str, Channel::Match>();
|
||||||
|
|
||||||
py_channel //
|
py_channel //
|
||||||
.def_property_readonly_static(
|
.def_property_readonly_static(
|
||||||
"ChannelMap",
|
"ChannelMap",
|
||||||
|
|
|
@ -433,6 +433,7 @@ def test_ChannelResolveParams():
|
||||||
|
|
||||||
def test_Channel():
|
def test_Channel():
|
||||||
Channel = libmambapy.specs.Channel
|
Channel = libmambapy.specs.Channel
|
||||||
|
Match = libmambapy.specs.Channel.Match
|
||||||
CondaURL = libmambapy.specs.CondaURL
|
CondaURL = libmambapy.specs.CondaURL
|
||||||
|
|
||||||
url_1 = CondaURL.parse("https://repo.anaconda.com/conda-forge")
|
url_1 = CondaURL.parse("https://repo.anaconda.com/conda-forge")
|
||||||
|
@ -487,8 +488,8 @@ def test_Channel():
|
||||||
assert chan.contains_equivalent(chan)
|
assert chan.contains_equivalent(chan)
|
||||||
assert other.contains_equivalent(chan)
|
assert other.contains_equivalent(chan)
|
||||||
assert not chan.contains_equivalent(other)
|
assert not chan.contains_equivalent(other)
|
||||||
assert chan.contains_package(chan.url / "noarch/pkg.conda")
|
assert chan.contains_package(chan.url / "noarch/pkg.conda") == Match.Full
|
||||||
assert not chan.contains_package(chan.url / "win-64/pkg.conda")
|
assert chan.contains_package(chan.url / "win-64/pkg.conda") == Match.InOtherPlatform
|
||||||
|
|
||||||
|
|
||||||
def test_Channel_resolve():
|
def test_Channel_resolve():
|
||||||
|
|
Loading…
Reference in New Issue