11#!/usr/bin/env python3
22import argparse
3+ import gzip
34import os .path
45import shutil
56import 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+
2735def 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