Source: dh-python Version: 1.20150705-1 Severity: wishlist Tags: patch User: reproducible-bui...@lists.alioth.debian.org Usertags: toolchain X-Debbugs-Cc: reproducible-bui...@lists.alioth.debian.org
Hi, While working on the "reproducible builds" effort [1], we have noticed that dh-python can output Debhelper autoscript snippets for private directories in a non-determinstic order. This results in, for example, a postinst that will vary between builds: if which pycompile >/dev/null 2>&1; then - pycompile -p mate-menu /usr/lib/mate-menu -V 2.4- + pycompile -p mate-menu /usr/share/mate-menu -V 2.4- fi if which pycompile >/dev/null 2>&1; then - pycompile -p mate-menu /usr/share/mate-menu -V 2.4- + pycompile -p mate-menu /usr/lib/mate-menu -V 2.4- fi This appears to be because it iterates over the 'private_dirs' dict, calling dh.autoscript(...) on each member. Whilst the latter does append determinstically to a data structure prior to eventual serialisation, the former dict iteration is non-deterministic and therefore the whole process is. An alternative might appear to be to attack the serialisation, re-ordering the args *just* before output. For example: for tpl_name, args in templates.items(): - for i in args: + for i in sorted(args): .. in debhelper.py. This has the advantage of doing this in one place. However I have a hunch we do not want to be re-ordering things at this point - for example, we probably do want to byte-compile / remove / etc. the "main" modules before we attack the private ones or for some vaguely-similar reason and thus changing the order could have weird effects. It also seems to violate the "promise" of appending to a list that it will end up in that order. If I'm wrong about this then, of course, feel free to use this simpler change. [1]: https://wiki.debian.org/ReproducibleBuilds Regards, -- ,''`. : :' : Chris Lamb `. `'` la...@debian.org / chris-lamb.co.uk `-
diff --git a/dh_pypy b/dh_pypy index 3d07789..6a290f1 100755 --- a/dh_pypy +++ b/dh_pypy @@ -199,7 +199,7 @@ def main(): dh.autoscript(package, 'postinst', 'postinst-pypycompile', args) dh.autoscript(package, 'prerm', 'prerm-pypyclean', '') pypyclean_added = True - for pdir, details in stats['private_dirs'].items(): + for pdir, details in sorted(stats['private_dirs'].items()): if not details.get('compile'): continue if not pypyclean_added: diff --git a/dh_python2 b/dh_python2 index 6124423..ff32b36 100755 --- a/dh_python2 +++ b/dh_python2 @@ -441,7 +441,7 @@ def main(): dh.autoscript(package, 'prerm', 'prerm-pyclean', '') pyclean_added = True - for pdir, details in stats['private_dirs'].items(): + for pdir, details in sorted(stats['private_dirs'].items()): if not details.get('compile'): continue if not pyclean_added: diff --git a/dh_python3 b/dh_python3 index e201dd2..8c62c87 100755 --- a/dh_python3 +++ b/dh_python3 @@ -200,7 +200,7 @@ def main(): dh.autoscript(package, 'postinst', 'postinst-py3compile', args) dh.autoscript(package, 'prerm', 'prerm-py3clean', '') pyclean_added = True - for pdir, details in stats['private_dirs'].items(): + for pdir, details in sorted(stats['private_dirs'].items()): if not details.get('compile'): continue if not pyclean_added: