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:

Reply via email to