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;
|
||||
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 is_equivalent_to(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:
|
||||
|
||||
|
|
|
@ -140,37 +140,28 @@ namespace mamba
|
|||
|
||||
namespace
|
||||
{
|
||||
enum struct ChannelMatch
|
||||
auto
|
||||
channel_match(const std::vector<specs::Channel>& ms_channels, const specs::CondaURL& pkg_url)
|
||||
-> specs::Channel::Match
|
||||
{
|
||||
None,
|
||||
ChannelOnly,
|
||||
ChannelAndSubdir,
|
||||
};
|
||||
|
||||
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)
|
||||
auto match = specs::Channel::Match::No;
|
||||
// More than one element means the channel spec was a custom_multi_channel
|
||||
for (const auto& chan : ms_channels)
|
||||
{
|
||||
// More than one element means the channel spec was a custom_multi_channel.
|
||||
// We need to add any repo that matches.
|
||||
for (const auto& cand_chan : candidate_channels)
|
||||
switch (chan.contains_package(pkg_url))
|
||||
{
|
||||
if (repo_chan.url_equivalent_with(cand_chan))
|
||||
{
|
||||
if (util::set_is_subset_of(repo_chan.platforms(), cand_chan.platforms()))
|
||||
{
|
||||
return ChannelMatch::ChannelAndSubdir;
|
||||
}
|
||||
return ChannelMatch::ChannelOnly;
|
||||
}
|
||||
case specs::Channel::Match::Full:
|
||||
return specs::Channel::Match::Full;
|
||||
case specs::Channel::Match::InOtherPlatform:
|
||||
// Keep looking for full matches
|
||||
match = specs::Channel::Match::InOtherPlatform;
|
||||
break;
|
||||
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()
|
||||
);
|
||||
|
||||
auto ms_channel = channel_context.make_channel(*ms.channel());
|
||||
auto ms_channels = channel_context.make_channel(*ms.channel());
|
||||
|
||||
solv::ObjQueue selected_pkgs = {};
|
||||
auto other_subdir_match = std::string();
|
||||
|
@ -206,28 +197,32 @@ namespace mamba
|
|||
match,
|
||||
[&](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());
|
||||
// TODO this does not work with s.url(), we need to proper channel class
|
||||
// to properly manage this.
|
||||
auto repo = solv::ObjRepoView(*s.raw()->repo);
|
||||
const auto match = channel_match(
|
||||
channel_context.make_channel(repo.url()),
|
||||
ms_channel
|
||||
);
|
||||
const auto match = channel_match(ms_channels, specs::CondaURL::parse(s.url()));
|
||||
switch (match)
|
||||
{
|
||||
case (ChannelMatch::ChannelAndSubdir):
|
||||
case (specs::Channel::Match::Full):
|
||||
{
|
||||
selected_pkgs.push_back(s.id());
|
||||
break;
|
||||
}
|
||||
case (ChannelMatch::ChannelOnly):
|
||||
case (specs::Channel::Match::InOtherPlatform):
|
||||
{
|
||||
other_subdir_match = s.subdir();
|
||||
break;
|
||||
}
|
||||
case (ChannelMatch::None):
|
||||
case (specs::Channel::Match::No):
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,26 +155,27 @@ namespace mamba::specs
|
|||
{
|
||||
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());
|
||||
}
|
||||
|
||||
auto Channel::contains_package(const CondaURL& pkg) const -> bool
|
||||
auto Channel::contains_package(const CondaURL& pkg) const -> Match
|
||||
{
|
||||
if (is_package())
|
||||
{
|
||||
return url_equivalent_with_impl(url(), pkg);
|
||||
}
|
||||
if (!platforms().contains(std::string(pkg.platform_name())))
|
||||
{
|
||||
return false;
|
||||
return url_equivalent_with_impl(url(), pkg) ? Match::Full : Match::No;
|
||||
}
|
||||
|
||||
auto pkg_repo = pkg;
|
||||
pkg_repo.clear_platform();
|
||||
const auto plat = std::string(pkg_repo.platform_name());
|
||||
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")
|
||||
{
|
||||
using namespace conda_url_literals;
|
||||
using Match = Channel::Match;
|
||||
|
||||
SUBCASE("https://repo.mamba.pm/")
|
||||
{
|
||||
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_FALSE(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu));
|
||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu));
|
||||
CHECK_EQ(
|
||||
chan.contains_package("https://repo.mamba.pm/linux-64/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")
|
||||
{
|
||||
auto chan = Channel("https://repo.mamba.pm/osx-64/foo.tar.bz2"_cu, "", {});
|
||||
CHECK(chan.contains_package(chan.url()));
|
||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu));
|
||||
CHECK_FALSE(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu));
|
||||
CHECK_EQ(chan.contains_package(chan.url()), Match::Full);
|
||||
CHECK_EQ(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu), Match::No);
|
||||
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(
|
||||
"https://user:pass@repo.mamba.pm/conda-forge/"_cu,
|
||||
"conda-forge",
|
||||
{ "win-64" }
|
||||
);
|
||||
CHECK(chan.contains_package(chan.url() / "win-64/pkg.conda"));
|
||||
CHECK(chan.contains_package("https://repo.mamba.pm/conda-forge/win-64/pkg.conda"_cu));
|
||||
CHECK_FALSE(
|
||||
chan.contains_package("https://repo.mamba.pm/conda-forge/osx-64/pkg.conda"_cu)
|
||||
CHECK_EQ(chan.contains_package(chan.url() / "win-64/pkg.conda"), Match::Full);
|
||||
CHECK_EQ(
|
||||
chan.contains_package("https://repo.mamba.pm/conda-forge/win-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("__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 //
|
||||
.def_property_readonly_static(
|
||||
"ChannelMap",
|
||||
|
|
|
@ -433,6 +433,7 @@ def test_ChannelResolveParams():
|
|||
|
||||
def test_Channel():
|
||||
Channel = libmambapy.specs.Channel
|
||||
Match = libmambapy.specs.Channel.Match
|
||||
CondaURL = libmambapy.specs.CondaURL
|
||||
|
||||
url_1 = CondaURL.parse("https://repo.anaconda.com/conda-forge")
|
||||
|
@ -487,8 +488,8 @@ def test_Channel():
|
|||
assert chan.contains_equivalent(chan)
|
||||
assert other.contains_equivalent(chan)
|
||||
assert not chan.contains_equivalent(other)
|
||||
assert chan.contains_package(chan.url / "noarch/pkg.conda")
|
||||
assert not chan.contains_package(chan.url / "win-64/pkg.conda")
|
||||
assert chan.contains_package(chan.url / "noarch/pkg.conda") == Match.Full
|
||||
assert chan.contains_package(chan.url / "win-64/pkg.conda") == Match.InOtherPlatform
|
||||
|
||||
|
||||
def test_Channel_resolve():
|
||||
|
|
Loading…
Reference in New Issue