Source: dpkg-dev
Version: 1.18.1
Severity: wishlist
Tags: patch
User: reproducible-builds@lists.alioth.debian.org
Usertags: toolchain
X-Debbugs-Cc: reproducible-builds@lists.alioth.debian.org

Hi,

While working on the "reproducible builds" effort [1], we have noticed
that dpkg-dev doesn't sort some dependencies deterministically.

This results in the output ofdpkg-shlibdeps non-reproducible, flapping
between, for example:

  - pkga | pkgb, pkga | pkgc
  + pkga | pkgc, pkga | pkgb

This can (currently) be seen in pyopencl:

  https://reproducible.debian.net/rb-pkg/unstable/amd64/pyopencl.html

This is caused by deps_compare only comparing the "left"-most dependency
of a Dpkg::Deps::Multiple. The attached patch ensures that all
dependencies
of such an object are checked, including an addition to the testsuite.

 [1]: https://wiki.debian.org/ReproducibleBuilds


Regards,

-- 
      ,''`.
     : :'  :     Chris Lamb
     `. `'`      la...@debian.org / chris-lamb.co.uk
       `-
diff --git a/scripts/Dpkg/Deps.pm b/scripts/Dpkg/Deps.pm
index 1823340..4b10a96 100644
--- a/scripts/Dpkg/Deps.pm
+++ b/scripts/Dpkg/Deps.pm
@@ -367,25 +367,22 @@ my %relation_ordering = (
 
 sub deps_compare {
     my ($a, $b) = @_;
-    return -1 if $a->is_empty();
-    return 1 if $b->is_empty();
-    while ($a->isa('Dpkg::Deps::Multiple')) {
-       return -1 if $a->is_empty();
-       my @deps = $a->get_deps();
-       $a = $deps[0];
+    my (@as, @bs) = (), ();
+    deps_iterate($a, sub { push @as, @_ });
+    deps_iterate($b, sub { push @bs, @_ });
+    while (1) {
+        my $a = shift @as // return -1;
+        my $b = shift @bs // return 1;
+        my $ar = $a->{relation} // 'undef';
+        my $br = $b->{relation} // 'undef';
+        my $av = $a->{version} // '';
+        my $bv = $b->{version} // '';
+        my $res = (($a->{package} cmp $b->{package}) ||
+                ($relation_ordering{$ar} <=> $relation_ordering{$br}) ||
+                ($av cmp $bv));
+        return $res if $res <=> 0;
     }
-    while ($b->isa('Dpkg::Deps::Multiple')) {
-       return 1 if $b->is_empty();
-       my @deps = $b->get_deps();
-       $b = $deps[0];
-    }
-    my $ar = $a->{relation} // 'undef';
-    my $br = $b->{relation} // 'undef';
-    my $av = $a->{version} // '';
-    my $bv = $a->{version} // '';
-    return (($a->{package} cmp $b->{package}) ||
-           ($relation_ordering{$ar} <=> $relation_ordering{$br}) ||
-           ($av cmp $bv));
+    return 0;
 }
 
 
diff --git a/scripts/t/Dpkg_Deps.t b/scripts/t/Dpkg_Deps.t
index db4b187..5579e12 100644
--- a/scripts/t/Dpkg_Deps.t
+++ b/scripts/t/Dpkg_Deps.t
@@ -40,9 +40,9 @@ my $dep_multiline = deps_parse($field_multiline);
 $dep_multiline->sort();
 is($dep_multiline->output(), $field_multiline_sorted, 'Parse, sort and 
output');
 
-my $dep_sorted = deps_parse('pkgz, pkgz | pkga, pkga (>= 1.0), pkgz (<= 2.0)');
+my $dep_sorted = deps_parse('pkgz, pkgz | pkgb, pkgz | pkga, pkga (>= 1.0), 
pkgz (<= 2.0)');
 $dep_sorted->sort();
-is($dep_sorted->output(), 'pkga (>= 1.0), pkgz, pkgz | pkga, pkgz (<= 2.0)', 
'Check sort() algorithm');
+is($dep_sorted->output(), 'pkga (>= 1.0), pkgz, pkgz | pkga, pkgz | pkgb, pkgz 
(<= 2.0)', 'Check sort() algorithm');
 
 my $dep_subset = deps_parse('libatk1.0-0 (>> 1.10), libc6, libcairo2');
 is($dep_multiline->implies($dep_subset), 1, 'Dep implies subset of itself');
_______________________________________________
Reproducible-builds mailing list
Reproducible-builds@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reproducible-builds

Reply via email to