From 7bca96784629c4482d6935ae38aff794820a4ca7 Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Mon, 22 Mar 2021 01:55:07 +0100 Subject: [PATCH] Use deterministic time for generated sdist files When generating setup.py and PKG-INFO files, ensure that generated files use a deterministic timestamp to enhance reproducibility of source distributions. --- poetry/core/masonry/builders/sdist.py | 7 ++++--- tests/masonry/builders/test_sdist.py | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/poetry/core/masonry/builders/sdist.py b/poetry/core/masonry/builders/sdist.py index add8dcd27..e0438cd10 100644 --- a/poetry/core/masonry/builders/sdist.py +++ b/poetry/core/masonry/builders/sdist.py @@ -2,7 +2,6 @@ import os import re import tarfile -import time from collections import defaultdict from contextlib import contextmanager @@ -97,14 +96,16 @@ def build(self, target_dir: Optional[Path] = None) -> Path: setup = self.build_setup() tar_info = tarfile.TarInfo(pjoin(tar_dir, "setup.py")) tar_info.size = len(setup) - tar_info.mtime = time.time() + tar_info.mtime = 0 + tar_info = self.clean_tarinfo(tar_info) tar.addfile(tar_info, BytesIO(setup)) pkg_info = self.build_pkg_info() tar_info = tarfile.TarInfo(pjoin(tar_dir, "PKG-INFO")) tar_info.size = len(pkg_info) - tar_info.mtime = time.time() + tar_info.mtime = 0 + tar_info = self.clean_tarinfo(tar_info) tar.addfile(tar_info, BytesIO(pkg_info)) finally: tar.close() diff --git a/tests/masonry/builders/test_sdist.py b/tests/masonry/builders/test_sdist.py index 3cb2a3b12..261e44738 100644 --- a/tests/masonry/builders/test_sdist.py +++ b/tests/masonry/builders/test_sdist.py @@ -1,5 +1,6 @@ import ast import gzip +import hashlib import shutil import tarfile @@ -250,6 +251,24 @@ def test_package(): assert "my-package-1.2.3/LICENSE" in tar.getnames() +def test_sdist_reproducibility(): + poetry = Factory().create_poetry(project("complete")) + + hashes = set() + + for _ in range(2): + builder = SdistBuilder(poetry) + builder.build() + + sdist = fixtures_dir / "complete" / "dist" / "my-package-1.2.3.tar.gz" + + assert sdist.exists() + + hashes.add(hashlib.sha256(sdist.read_bytes()).hexdigest()) + + assert len(hashes) == 1 + + def test_setup_py_context(): poetry = Factory().create_poetry(project("complete"))