11#!/usr/bin/env python3
22
3+ from gzip import GzipFile
4+ import hashlib
35import json
46from os .path import (
57 dirname , join , isfile , realpath ,
68 relpath , split , exists , basename
79)
8- from os import listdir , makedirs , remove
10+ from os import environ , listdir , makedirs , remove
911import os
1012import shlex
1113import shutil
@@ -161,16 +163,25 @@ def select(fn):
161163 return False
162164 return not is_blacklist (fn )
163165
166+ def clean (tinfo ):
167+ """cleaning function (for reproducible builds)"""
168+ tinfo .uid = tinfo .gid = 0
169+ tinfo .uname = tinfo .gname = ''
170+ tinfo .mtime = 0
171+ return tinfo
172+
164173 # get the files and relpath file of all the directory we asked for
165174 files = []
166175 for sd in source_dirs :
167176 sd = realpath (sd )
168177 compile_dir (sd , optimize_python = optimize_python )
169178 files += [(x , relpath (realpath (x ), sd )) for x in listfiles (sd )
170179 if select (x )]
180+ files .sort () # deterministic
171181
172182 # create tar.gz of thoses files
173- tf = tarfile .open (tfn , 'w:gz' , format = tarfile .USTAR_FORMAT )
183+ gf = GzipFile (tfn , 'wb' , mtime = 0 ) # deterministic
184+ tf = tarfile .open (None , 'w' , gf , format = tarfile .USTAR_FORMAT )
174185 dirs = []
175186 for fn , afn in files :
176187 dn = dirname (afn )
@@ -189,8 +200,9 @@ def select(fn):
189200 tf .addfile (tinfo )
190201
191202 # put the file
192- tf .add (fn , afn )
203+ tf .add (fn , afn , filter = clean )
193204 tf .close ()
205+ gf .close ()
194206
195207
196208def compile_dir (dfn , optimize_python = True ):
@@ -521,9 +533,18 @@ def make_package(args):
521533 versioned_name = versioned_name )
522534
523535 # String resources:
536+ timestamp = time .time ()
537+ if 'SOURCE_DATE_EPOCH' in environ :
538+ # for reproducible builds
539+ timestamp = int (environ ['SOURCE_DATE_EPOCH' ])
540+ private_version = "{} {} {}" .format (
541+ args .version ,
542+ args .numeric_version ,
543+ timestamp
544+ )
524545 render_args = {
525546 "args" : args ,
526- "private_version" : str ( time . time () )
547+ "private_version" : hashlib . sha1 ( private_version . encode ()). hexdigest ( )
527548 }
528549 if get_bootstrap_name () == "sdl2" :
529550 render_args ["url_scheme" ] = url_scheme
0 commit comments