##// END OF EJS Templates
Avoid calling the input transformer twice in the execution stack....
Avoid calling the input transformer twice in the execution stack. This should allow to register input transformers that have side effects, at least in Notebooks. Right now there are sill multiple calls which may happen in the terminal on execution requests.

File last commit:

r25866:f380b53e
r25891:d5a8359c
Show More
retar.py
65 lines | 1.5 KiB | text/x-python | PythonLexer
"""
Un-targz and retargz a targz file to ensure reproducible build.
usage:
$ export SOURCE_DATE_EPOCH=$(date +%s)
...
$ python retar.py <tarfile.gz>
The process of creating an sdist can be non-reproducible:
- directory created during the process get a mtime of the creation date;
- gziping files embed the timestamp of fo zip creation.
This will untar-retar; ensuring that all mtime > SOURCE_DATE_EPOCH will be set
equal to SOURCE_DATE_EPOCH.
"""
import tarfile
import sys
import os
import gzip
import io
if len(sys.argv) > 2:
raise ValueError("Too many arguments")
timestamp = int(os.environ["SOURCE_DATE_EPOCH"])
old_buf = io.BytesIO()
with open(sys.argv[1], "rb") as f:
old_buf.write(f.read())
old_buf.seek(0)
old = tarfile.open(fileobj=old_buf, mode="r:gz")
buf = io.BytesIO()
new = tarfile.open(fileobj=buf, mode="w", format=tarfile.GNU_FORMAT)
for i, m in enumerate(old):
data = None
# mutation does not work, copy
if m.name.endswith('.DS_Store'):
continue
m2 = tarfile.TarInfo(m.name)
m2.mtime = min(timestamp, m.mtime)
m2.size = m.size
m2.type = m.type
m2.linkname = m.linkname
m2.mode = m.mode
if m.isdir():
new.addfile(m2)
else:
data = old.extractfile(m)
new.addfile(m2, data)
new.close()
old.close()
buf.seek(0)
with open(sys.argv[1], "wb") as f:
with gzip.GzipFile('', "wb", fileobj=f, mtime=timestamp) as gzf:
gzf.write(buf.read())
# checks the archive is valid.
archive = tarfile.open(sys.argv[1])
names = archive.getnames()