Forráskód Böngészése

Dpkg::Deps: Make the dependency comparison deep

We have to check the whole dependency tree, and not only compare the
first alternative from a Dpkg::Deps::Multiple. This allows sorting
them in a reproducible way.

Closes: #792491
Based-on-patch-by: Chris Lamb <lamby@debian.org>
Signed-off-by: Guillem Jover <guillem@debian.org>
Guillem Jover 11 éve
szülő
commit
411de2793a
3 módosított fájl, 29 hozzáadás és 21 törlés
  1. 3 0
      debian/changelog
  2. 24 19
      scripts/Dpkg/Deps.pm
  3. 2 2
      scripts/t/Dpkg_Deps.t

+ 3 - 0
debian/changelog

@@ -62,6 +62,9 @@ dpkg (1.18.2) UNRELEASED; urgency=low
     - Future-proof tar invocations in Dpkg::Source::Archive for options that
       might become positional in the future, and by always placing function
       options first.
+    - Make the dependency comparison deep by comparing not only the first
+      dependency alternative, to get them sorted in a reproducible way.
+      Based on a patch by Chris Lamb <lamby@debian.org>. Closes: #792491
   * Test suite:
     - Set SIGINT, SIGTERM and SIGPIPE to their default actions to get
       deterministic behavior.

+ 24 - 19
scripts/Dpkg/Deps.pm

@@ -366,26 +366,31 @@ 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 ($aref, $bref) = @_;
+
+    my (@as, @bs);
+    deps_iterate($aref, sub { push @as, @_ });
+    deps_iterate($bref, sub { push @bs, @_ });
+
+    while (1) {
+        my ($a, $b) = (shift @as, shift @bs);
+        my $aundef = not defined $a or $a->is_empty();
+        my $bundef = not defined $b or $b->is_empty();
+
+        return  0 if $aundef and $bundef;
+        return -1 if $aundef;
+        return  1 if $bundef;
+
+        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));
 }
 
 

+ 2 - 2
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');