Skip to content

Commit 9f2f405

Browse files
authored
Merge pull request #1915 from pre-commit/reproducible-tar
make tarfile creation reproducible
2 parents 7266936 + c2108d6 commit 9f2f405

File tree

4 files changed

+26
-10
lines changed

4 files changed

+26
-10
lines changed

pre_commit/resources/rbenv.tar.gz

-2.06 KB
Binary file not shown.
-6.06 KB
Binary file not shown.
-262 Bytes
Binary file not shown.

testing/make-archives

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python3
22
import argparse
3+
import gzip
34
import os.path
45
import shutil
56
import subprocess
@@ -24,15 +25,14 @@ REPOS = (
2425
)
2526

2627

28+
def reset(tarinfo: tarfile.TarInfo) -> tarfile.TarInfo:
29+
tarinfo.uid = tarinfo.gid = 0
30+
tarinfo.uname = tarinfo.gname = 'root'
31+
tarinfo.mtime = 0
32+
return tarinfo
33+
34+
2735
def make_archive(name: str, repo: str, ref: str, destdir: str) -> str:
28-
"""Makes an archive of a repository in the given destdir.
29-
30-
:param text name: Name to give the archive. For instance foo. The file
31-
that is created will be called foo.tar.gz.
32-
:param text repo: Repository to clone.
33-
:param text ref: Tag/SHA/branch to check out.
34-
:param text destdir: Directory to place archives in.
35-
"""
3636
output_path = os.path.join(destdir, f'{name}.tar.gz')
3737
with tempfile.TemporaryDirectory() as tmpdir:
3838
# this ensures that the root directory has umask permissions
@@ -47,8 +47,24 @@ def make_archive(name: str, repo: str, ref: str, destdir: str) -> str:
4747
# runtime
4848
shutil.rmtree(os.path.join(gitdir, '.git'))
4949

50-
with tarfile.open(output_path, 'w|gz') as tf:
51-
tf.add(gitdir, name)
50+
arcs = [(name, gitdir)]
51+
for root, dirs, filenames in os.walk(gitdir):
52+
for filename in dirs + filenames:
53+
abspath = os.path.abspath(os.path.join(root, filename))
54+
relpath = os.path.relpath(abspath, gitdir)
55+
arcs.append((os.path.join(name, relpath), abspath))
56+
arcs.sort()
57+
58+
with gzip.GzipFile(output_path, 'wb', mtime=0) as gzipf:
59+
# https://github.com/python/typeshed/issues/5491
60+
with tarfile.open(fileobj=gzipf, mode='w') as tf: # type: ignore
61+
for arcname, abspath in arcs:
62+
tf.add(
63+
abspath,
64+
arcname=arcname,
65+
recursive=False,
66+
filter=reset,
67+
)
5268

5369
return output_path
5470

0 commit comments

Comments
 (0)