fix(venv): group venv prefixes by path component, not raw path (#3333)
When files overlap between packages, and dist-info directories are
present, it results in a prefix list like `foo foo-bar foo/bar`. When
sorted as raw strings, hyphen sorts before slash, so the continuity of
path prefixes is violated and they are grouped separately. An error then
occurs because both `foo/` and `foo/bar` are created, but the latter is
a sub-path of the former.
To fix, change the sort key to a tuple of path components. This makes
`foo foo-bar foo/bar` sort as `(foo,) (foo, bar), (foo-bar, )`,
resulting in the correct order.
Fixes https://github.com/bazel-contrib/rules_python/issues/3204
diff --git a/python/private/venv_runfiles.bzl b/python/private/venv_runfiles.bzl
index 291920b..9fbe97a 100644
--- a/python/private/venv_runfiles.bzl
+++ b/python/private/venv_runfiles.bzl
@@ -138,7 +138,9 @@
"""
# Sort so order is top-down, ensuring grouping by short common prefix
- entries = sorted(entries, key = lambda e: e.venv_path)
+ # Split it into path components so `foo foo-bar foo/bar` sorts as
+ # `foo foo/bar foo-bar`
+ entries = sorted(entries, key = lambda e: tuple(e.venv_path.split("/")))
groups = []
current_group = None
diff --git a/tests/venv_site_packages_libs/app_files_building/app_files_building_tests.bzl b/tests/venv_site_packages_libs/app_files_building/app_files_building_tests.bzl
index 0a0265e..68e1716 100644
--- a/tests/venv_site_packages_libs/app_files_building/app_files_building_tests.bzl
+++ b/tests/venv_site_packages_libs/app_files_building/app_files_building_tests.bzl
@@ -61,6 +61,7 @@
def _test_conflict_merging_impl(env, _):
entries = [
_entry("a", "+pypi_a/site-packages/a", ["a.txt"]),
+ _entry("a-1.0.dist-info", "+pypi_a/site-packages/a-1.0.dist-info", ["METADATA"]),
_entry("a/b", "+pypi_a_b/site-packages/a/b", ["b.txt"]),
_entry("x", "_main/src/x", ["x.txt"]),
_entry("x/p", "_main/src-dev/x/p", ["p.txt"]),
@@ -72,6 +73,7 @@
actual = build_link_map(_ctx(), entries)
expected_libs = {
+ "a-1.0.dist-info": "+pypi_a/site-packages/a-1.0.dist-info",
"a/a.txt": _file("../+pypi_a/site-packages/a/a.txt"),
"a/b/b.txt": _file("../+pypi_a_b/site-packages/a/b/b.txt"),
"duplicate/d.py": _file("../+dupe_a/site-packages/duplicate/d.py"),