From ecd14f0ad99f254c43d8b7a463aa98082fe40200 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 20 Jan 2025 10:21:32 +0100 Subject: [PATCH] archive.py: fix include_parent_directories=True with path_to_name (#48570) --- lib/spack/spack/test/util/archive.py | 32 ++++++++++++++++++++++++++++ lib/spack/spack/util/archive.py | 4 ++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/spack/spack/test/util/archive.py b/lib/spack/spack/test/util/archive.py index 70133c13818..b0993f7eb85 100644 --- a/lib/spack/spack/test/util/archive.py +++ b/lib/spack/spack/test/util/archive.py @@ -154,3 +154,35 @@ def test_gzip_compressed_tarball_is_reproducible(tmpdir): == spack.util.crypto.checksum_stream(hashlib.sha256, f) == spack.util.crypto.checksum_stream(hashlib.sha256, g) ) + + +def test_reproducible_tarfile_from_prefix_path_to_name(tmp_path: Path): + prefix = tmp_path / "example" + prefix.mkdir() + (prefix / "file1").write_bytes(b"file") + (prefix / "file2").write_bytes(b"file") + + def map_prefix(path: str) -> str: + """maps / to some/common/prefix/""" + p = PurePath(path) + assert p.parts[: len(prefix.parts)] == prefix.parts, f"{path} is not under {prefix}" + return PurePath("some", "common", "prefix", *p.parts[len(prefix.parts) :]).as_posix() + + with tarfile.open(tmp_path / "example.tar", "w") as tar: + reproducible_tarfile_from_prefix( + tar, + str(tmp_path / "example"), + include_parent_directories=True, + path_to_name=map_prefix, + ) + + with tarfile.open(tmp_path / "example.tar", "r") as tar: + assert [t.name for t in tar.getmembers() if t.isdir()] == [ + "some", + "some/common", + "some/common/prefix", + ] + assert [t.name for t in tar.getmembers() if t.isfile()] == [ + "some/common/prefix/file1", + "some/common/prefix/file2", + ] diff --git a/lib/spack/spack/util/archive.py b/lib/spack/spack/util/archive.py index 20b78dd495e..1088bf89727 100644 --- a/lib/spack/spack/util/archive.py +++ b/lib/spack/spack/util/archive.py @@ -172,10 +172,10 @@ def reproducible_tarfile_from_prefix( hardlink_to_tarinfo_name: Dict[Tuple[int, int], str] = dict() if include_parent_directories: - parent_dirs = reversed(pathlib.Path(prefix).parents) + parent_dirs = reversed(pathlib.PurePosixPath(path_to_name(prefix)).parents) next(parent_dirs) # skip the root: slices are supported from python 3.10 for parent_dir in parent_dirs: - dir_info = tarfile.TarInfo(path_to_name(str(parent_dir))) + dir_info = tarfile.TarInfo(str(parent_dir)) dir_info.type = tarfile.DIRTYPE dir_info.mode = 0o755 tar.addfile(dir_info)