From 604cd181ca81a802a2ab5d7021d1b42b9e8568b4 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 5 Nov 2025 11:15:58 +0100 Subject: [PATCH] remote tinfo for reproducible tgz files --- conan/internal/api/uploader.py | 10 +++++++++- test/unittests/client/remote_manager_test.py | 16 ++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/conan/internal/api/uploader.py b/conan/internal/api/uploader.py index 4a8f90aca91..024fbbbc011 100644 --- a/conan/internal/api/uploader.py +++ b/conan/internal/api/uploader.py @@ -288,11 +288,19 @@ def compress_files(files, name, dest_dir, compresslevel=None, ref=None, recursiv tgz_path = os.path.join(dest_dir, name) if ref: ConanOutput(scope=str(ref) if ref else None).info(f"Compressing {name}") + + def myfilter(tinfo): + tinfo.uid = tinfo.gid = 0 + tinfo.uname = tinfo.gname = "conan" + tinfo.mtime = 0 + tinfo.mode = 0 + return tinfo + with set_dirty_context_manager(tgz_path), open(tgz_path, "wb") as tgz_handle: tgz = gzopen_without_timestamps(name, fileobj=tgz_handle, compresslevel=compresslevel) for filename, abs_path in sorted(files.items()): # recursive is False by default in case it is a symlink to a folder - tgz.add(abs_path, filename, recursive=recursive) + tgz.add(abs_path, filename, recursive=recursive, filter=myfilter) tgz.close() duration = time.time() - t1 diff --git a/test/unittests/client/remote_manager_test.py b/test/unittests/client/remote_manager_test.py index cbad3cba042..dfd4c9c26ad 100644 --- a/test/unittests/client/remote_manager_test.py +++ b/test/unittests/client/remote_manager_test.py @@ -1,10 +1,9 @@ import os -import pytest from conan.internal.api.uploader import compress_files from conan.internal.paths import PACKAGE_TGZ_NAME from conan.test.utils.test_files import temp_folder -from conan.internal.util.files import save +from conan.internal.util.files import save, check_with_algorithm_sum class TestRemoteManager: @@ -23,3 +22,16 @@ def test_compress_files(self): assert os.path.exists(path) expected_path = os.path.join(folder, PACKAGE_TGZ_NAME) assert path == expected_path + + def test_compress_files_checksums(self): + folder = temp_folder() + save(os.path.join(folder, "one_file.txt"), "The contents") + save(os.path.join(folder, "Two_file.txt"), "Two contents") + + files = { + "one_file.txt": os.path.join(folder, "one_file.txt"), + "Two_file.txt": os.path.join(folder, "Two_file.txt"), + } + + path = compress_files(files, PACKAGE_TGZ_NAME, dest_dir=folder) + check_with_algorithm_sum("sha1", path, "0bc8b45f526421437d204762ab7424aa644ab7e3")