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

Handle .tar.gz in pkg url #3640

Merged
merged 3 commits into from
Dec 6, 2024
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
3 changes: 2 additions & 1 deletion libmamba/include/mamba/specs/archive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ namespace mamba::specs
{
inline static constexpr auto ARCHIVE_EXTENSIONS = std::array{ std::string_view(".tar.bz2"),
std::string_view(".conda"),
std::string_view(".whl") };
std::string_view(".whl"),
std::string_view(".tar.gz") };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are a number of other potential formats: https://docs.python.org/3.10/distutils/sourcedist.html

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Thanks for the pointer :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will implement them in dedicated PRs if their support is requested.


/** Detect if the package path has one of the known archive extension. */
template <typename Str, std::enable_if_t<std::is_convertible_v<Str, std::string_view>, bool> = true>
Expand Down
1 change: 1 addition & 0 deletions libmamba/include/mamba/specs/package_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace mamba::specs
Unknown,
Conda,
Wheel,
TarGz,
};

class PackageInfo
Expand Down
125 changes: 105 additions & 20 deletions libmamba/src/specs/package_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ namespace mamba::specs
{
return PackageType::Wheel;
}
else if (util::ends_with(spec, ".tar.gz"))
{
return PackageType::TarGz;
}
return PackageType::Conda;
}

Expand All @@ -40,7 +44,6 @@ namespace mamba::specs
return make_unexpected_parse("Missing filename extension.");
}


auto out = PackageInfo();
// TODO decide on the best way to group filename/channel/subdir/package_url all at once
out.package_url = util::path_or_url_to_url(spec);
Expand All @@ -58,37 +61,119 @@ namespace mamba::specs
out.filename = url.package();
url.clear_package();

// The filename format depends on the package_type:
out.package_type = parse_extension(spec);
// PackageType::Conda (.tar.bz2 or .conda):
// {pkg name}-{version}-{build string}.{tar.bz2, conda}
if (out.package_type == PackageType::Conda)
{
out.platform = url.platform_name();
url.clear_platform();
out.channel = util::rstrip(url.str(), '/');
}

// Build string
auto [head, tail] = util::rsplit_once(strip_archive_extension(out.filename), '-');
out.build_string = tail;
// Note that we use `rsplit...` instead of `split...`
// because the package name may contain '-'.
// Build string
auto [head, tail] = util::rsplit_once(strip_archive_extension(out.filename), '-');
out.build_string = tail;
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing name and version in filename "{}".)", out.filename)
);
}

if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing name and version in filename "{}".)", out.filename)
);
}
// Version
std::tie(head, tail) = util::rsplit_once(head.value(), '-');
out.version = tail;
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing name in filename "{}".)", out.filename)
);
}

// Version
std::tie(head, tail) = util::rsplit_once(head.value(), '-');
out.version = tail;
if (!head.has_value())
// Name
out.name = head.value(); // There may be '-' in the name
}
// PackageType::Wheel (.whl):
// {pkg name}-{version}-{build tag (optional)}-{python tag}-{abi tag}-{platform tag}.whl
// cf.
// https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/
else if (out.package_type == PackageType::Wheel)
{
return make_unexpected_parse(
fmt::format(R"(Missing name in filename "{}".)", out.filename)
);
// Platform tag
auto [head, tail] = util::rsplit_once(strip_archive_extension(out.filename), '-');
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing tags in filename "{}".)", out.filename)
);
}
// Abi tag
std::tie(head, tail) = util::rsplit_once(head.value(), '-');
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing tags in filename "{}".)", out.filename)
);
}
// Python tag
std::tie(head, tail) = util::rsplit_once(head.value(), '-');
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing tags in filename "{}".)", out.filename)
);
}
// Build tag or version
std::tie(head, tail) = util::rsplit_once(head.value(), '-');
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing tags in filename "{}".)", out.filename)
);
}
if (util::contains(tail, '.'))
{
// The tail is the version
out.version = tail;
// The head is the name
out.name = head.value(); // There may be '-' in the name
}
else
{
// The previous tail is the optional build tag
std::tie(head, tail) = util::rsplit_once(head.value(), '-');
// The tail is the version
out.version = tail;
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing name in filename "{}".)", out.filename)
);
}

// Name
out.name = head.value(); // There may be '-' in the name
}
}
// PackageType::TarGz (.tar.gz): {pkg name}-{version}.tar.gz
else if (out.package_type == PackageType::TarGz)
{
// Version
auto [head, tail] = util::rsplit_once(strip_archive_extension(out.filename), '-');
out.version = tail;
if (!head.has_value())
{
return make_unexpected_parse(
fmt::format(R"(Missing name in filename "{}".)", out.filename)
);
}

// Name
out.name = head.value(); // There may be '-' in the name
// Name
out.name = head.value(); // There may be '-' in the name
}

return out;
}
Expand Down
2 changes: 1 addition & 1 deletion libmambapy/tests/test_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def test_ParseError():


def test_archive_extension():
assert libmambapy.specs.archive_extensions() == [".tar.bz2", ".conda", ".whl"]
assert libmambapy.specs.archive_extensions() == [".tar.bz2", ".conda", ".whl", ".tar.gz"]

assert libmambapy.specs.has_archive_extension("pkg.conda")
assert not libmambapy.specs.has_archive_extension("conda.pkg")
Expand Down
Loading
Loading