Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[micromamba] [mamba] Fix wrong download url for custom channels #2596

Merged
merged 5 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions libmamba/include/mamba/core/util_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,15 @@ namespace mamba
{
return hex_string(buffer, buffer.size());
}

/**
* Return the common parts of two strings by blocks located between the given sep,
* and considering that these common parts would be located at the end of str1 (search from
* left to right).
* str1 is considered smaller than (or equal to) str2.
* cf. Channels use case.
*/
std::string get_common_parts(std::string_view str1, std::string_view str2, std::string_view sep);
}

#endif
18 changes: 15 additions & 3 deletions libmamba/src/core/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,22 @@ namespace mamba
// of the channel (e.g. -c testchannel/mylabel/xyz)
// needs to result in `name = private/testchannel/mylabel/xyz`
std::string combined_name = it->second.name();
if (name != combined_name && name.find('/') != std::string::npos)
if (combined_name != name)
{
combined_name += "/";
combined_name += name.substr(name.find('/') + 1, std::string::npos);
// Find common string between `name` and `combined_name`
auto common_str = get_common_parts(combined_name, name, "/");
// Combine names properly
if (common_str.empty())
{
combined_name += "/" + name;
}
else
{
// NOTE We assume that the `common_str`, if not empty, is necessarily at the
// beginning of `name` and at the end of `combined_name` (I don't know about
// other use cases for now)
combined_name += name.substr(common_str.size());
}
}

return Channel(
Expand Down
43 changes: 43 additions & 0 deletions libmamba/src/core/util_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,4 +641,47 @@ namespace mamba
}

}

/********************************************************
* Implementation of Channels use case util function *
*******************************************************/

std::string get_common_parts(std::string_view str1, std::string_view str2, std::string_view sep)
{
std::string common_str{ str1 };
while ((str2.find(common_str) == std::string::npos))
{
if (common_str.find(sep) != std::string::npos)
{
common_str = common_str.substr(common_str.find(sep) + 1);
}
else
{
return "";
}
}

// Case of non empty common_str
// Check that subparts of common_str are not substrings of elements between the sep
auto vec1 = split(common_str, sep);
auto vec2 = split(str2, sep);
std::vector<std::string> res_vec;
for (std::size_t idx = 0; idx < vec1.size(); ++idx)
{
auto it = std::find(vec2.begin(), vec2.end(), vec1.at(idx));
if (it != vec2.end())
{
res_vec.emplace_back(vec1.at(idx));
}
else
{
if (idx != 0)
{
return join(sep, res_vec);
}
}
}

return join(sep, res_vec);
}
}
17 changes: 17 additions & 0 deletions libmamba/tests/src/core/test_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ namespace mamba
auto& ctx = Context::instance();
ctx.custom_channels = {
{ "test_channel", "https://server.com/private/channels" },
{ "random/test_channel", "https://server.com/random/channels" },
};
ChannelContext channel_context;

Expand Down Expand Up @@ -381,6 +382,22 @@ namespace mamba
CHECK_EQ(c.urls(), exp_urls);
}

{
std::string value = "random/test_channel/pkg";
const Channel& c = channel_context.make_channel(value);
CHECK_EQ(c.scheme(), "https");
CHECK_EQ(c.location(), "server.com/random/channels");
CHECK_EQ(c.name(), "random/test_channel/pkg");
CHECK_EQ(c.canonical_name(), "random/test_channel/pkg");
CHECK_EQ(c.platforms(), std::vector<std::string>({ platform, "noarch" }));
std::vector<std::string> exp_urls(
{ std::string("https://server.com/random/channels/random/test_channel/pkg/")
+ platform,
std::string("https://server.com/random/channels/random/test_channel/pkg/noarch") }
);
CHECK_EQ(c.urls(), exp_urls);
}

ctx.channel_alias = "https://conda.anaconda.org";
ctx.custom_channels.clear();
}
Expand Down
32 changes: 32 additions & 0 deletions libmamba/tests/src/core/test_util_string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,38 @@ namespace mamba
{
CHECK_EQ(concat("aa", std::string("bb"), std::string_view("cc"), 'd'), "aabbccd");
}

TEST_CASE("get_common_parts")
{
CHECK_EQ(get_common_parts("", "", "/"), "");
CHECK_EQ(get_common_parts("", "test", "/"), "");
CHECK_EQ(get_common_parts("test", "test", "/"), "test");
CHECK_EQ(get_common_parts("test/chan", "test/chan", "/"), "test/chan");
CHECK_EQ(get_common_parts("st/ch", "test/chan", "/"), "");
CHECK_EQ(get_common_parts("st/chan", "test/chan", "/"), "chan");
CHECK_EQ(get_common_parts("st/chan/abc", "test/chan/abc", "/"), "chan/abc");
CHECK_EQ(get_common_parts("test/ch", "test/chan", "/"), "test");
CHECK_EQ(get_common_parts("test/an/abc", "test/chan/abc", "/"), "abc");
CHECK_EQ(get_common_parts("test/chan/label", "label/abcd/xyz", "/"), "label");
CHECK_EQ(get_common_parts("test/chan/label", "chan/label/abcd", "/"), "chan/label");
CHECK_EQ(get_common_parts("test/chan/label", "abcd/chan/label", "/"), "chan/label");
CHECK_EQ(get_common_parts("test", "abcd", "/"), "");
CHECK_EQ(get_common_parts("test", "abcd/xyz", "/"), "");
CHECK_EQ(get_common_parts("test/xyz", "abcd/xyz", "/"), "xyz");
CHECK_EQ(get_common_parts("test/xyz", "abcd/gef", "/"), "");
CHECK_EQ(get_common_parts("abcd/test", "abcd/xyz", "/"), "");

CHECK_EQ(get_common_parts("", "", "."), "");
CHECK_EQ(get_common_parts("", "test", "."), "");
CHECK_EQ(get_common_parts("test", "test", "."), "test");
CHECK_EQ(get_common_parts("test.chan", "test.chan", "."), "test.chan");
CHECK_EQ(get_common_parts("test.chan.label", "chan.label.abcd", "."), "chan.label");
CHECK_EQ(get_common_parts("test/chan/label", "chan/label/abcd", "."), "");
CHECK_EQ(get_common_parts("st/ch", "test/chan", "."), "");
CHECK_EQ(get_common_parts("st.ch", "test.chan", "."), "");

CHECK_EQ(get_common_parts("test..chan", "test..chan", ".."), "test..chan");
}
}

} // namespace mamba
3 changes: 2 additions & 1 deletion mamba/mamba/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ def get_base_url(url, name=None):
tmp = url.rsplit("/", 1)[0]
if name:
if tmp.endswith(name):
return tmp.rsplit("/", 1)[0]
# Return base url stripped from name
return tmp[: -(len(name) + 1)]
return tmp

api_ctx.channel_alias = str(
Expand Down