The following commit has been merged in the master branch:
commit d55bfa219c903bb5a68d5028411c935f1345911a
Author: RaphaĆ«l Hertzog <[email protected]>
Date:   Fri Apr 1 17:13:12 2011 +0200

    Dpkg::Deps: Fix dependency evaluation logic to use arch qualifier
    
    This required adding the Architecture and Multi-Arch values in
    Dpkg::Deps::KnownFacts and is thus an API extension.

diff --git a/scripts/Dpkg/Deps.pm b/scripts/Dpkg/Deps.pm
index 0ec4c3e..9635cc2 100644
--- a/scripts/Dpkg/Deps.pm
+++ b/scripts/Dpkg/Deps.pm
@@ -256,9 +256,8 @@ Set to 0 to completely ignore that information.
 
 =item host_arch (defaults to the current architecture)
 
-Define the host architecture. Needed only if the reduce_arch option is
-set to 1. By default it uses Dpkg::Arch::get_host_arch() to identify
-the proper architecture.
+Define the host architecture. By default it uses
+Dpkg::Arch::get_host_arch() to identify the proper architecture.
 
 =item reduce_arch (defaults to 0)
 
@@ -292,7 +291,8 @@ sub deps_parse {
     foreach my $dep_and (split(/\s*,\s*/m, $dep_line)) {
         my @or_list = ();
         foreach my $dep_or (split(/\s*\|\s*/m, $dep_and)) {
-           my $dep_simple = Dpkg::Deps::Simple->new($dep_or);
+           my $dep_simple = Dpkg::Deps::Simple->new($dep_or, host_arch =>
+                                                    $options{host_arch});
            if (not defined $dep_simple->{package}) {
                warning(_g("can't parse dependency %s"), $dep_or);
                return undef;
@@ -532,11 +532,12 @@ use Dpkg::Gettext;
 use base qw(Dpkg::Interface::Storable);
 
 sub new {
-    my ($this, $arg) = @_;
+    my ($this, $arg, %opts) = @_;
     my $class = ref($this) || $this;
     my $self = {};
     bless $self, $class;
     $self->reset();
+    $self->{host_arch} = $opts{host_arch} || Dpkg::Arch::get_host_arch();
     $self->parse_string($arg) if defined($arg);
     return $self;
 }
@@ -734,31 +735,7 @@ sub has_arch_restriction {
 sub get_evaluation {
     my ($self, $facts) = @_;
     return undef if not defined $self->{package};
-    my ($check, $param) = $facts->check_package($self->{package});
-    if ($check) {
-       if (defined $self->{relation}) {
-           if (ref($param)) {
-               # Provided packages
-               # XXX: Once support for versioned provides is in place,
-               # this part must be adapted
-               return 0;
-           } else {
-               if (defined($param)) {
-                   if (version_compare_relation($param, $self->{relation},
-                                                $self->{version})) {
-                       return 1;
-                   } else {
-                       return 0;
-                   }
-               } else {
-                   return undef;
-               }
-           }
-       } else {
-           return 1;
-       }
-    }
-    return 0;
+    return $facts->_evaluate_simple_dep($self);
 }
 
 sub simplify_deps {
@@ -1187,6 +1164,8 @@ Creates a new object.
 use strict;
 use warnings;
 
+use Dpkg::Version;
+
 sub new {
     my $this = shift;
     my $class = ref($this) || $this;
@@ -1195,17 +1174,28 @@ sub new {
     return $self;
 }
 
-=item $facts->add_installed_package($package, $version)
+=item $facts->add_installed_package($package, $version, $arch, $multiarch)
 
-Records that the given version of the package is installed. If $version is
-undefined we know that the package is installed but we don't know which
-version it is.
+Records that the given version of the package is installed. If
+$version/$arch is undefined we know that the package is installed but we
+don't know which version/architecture it is. $multiarch is the Multi-Arch
+field of the package. If $multiarch is undef, it will be equivalent to
+"Multi-Arch: no".
+
+Note that $multiarch is only used if $arch is provided.
 
 =cut
 
 sub add_installed_package {
-    my ($self, $pkg, $ver) = @_;
-    $self->{pkg}{$pkg} = $ver;
+    my ($self, $pkg, $ver, $arch, $multiarch) = @_;
+    my $p = {
+       "package" => $pkg,
+       "version" => $ver,
+       "architecture" => $arch,
+       "multi-arch" => $multiarch || "no",
+    };
+    $self->{pkg}{"$pkg:$arch"} = $p if defined $arch;
+    push @{$self->{pkg}{$pkg}}, $p;
 }
 
 =item $facts->add_provided_package($virtual, $relation, $version, $by)
@@ -1231,6 +1221,10 @@ contains the version. For a virtual package, $param 
contains an array
 reference containing the list of packages that provide it (each package is
 listed as [ $provider, $relation, $version ]).
 
+This function is obsolete and should not be used. Dpkg::Deps::KnownFacts
+is only meant to be filled with data and then passed to Dpkg::Deps
+methods where appropriate, but it should not be directly queried.
+
 =back
 
 =cut
@@ -1238,7 +1232,7 @@ listed as [ $provider, $relation, $version ]).
 sub check_package {
     my ($self, $pkg) = @_;
     if (exists $self->{pkg}{$pkg}) {
-       return (1, $self->{pkg}{$pkg});
+       return (1, $self->{pkg}{$pkg}[0]{version});
     }
     if (exists $self->{virtualpkg}{$pkg}) {
        return (1, $self->{virtualpkg}{$pkg});
@@ -1246,6 +1240,63 @@ sub check_package {
     return (0, undef);
 }
 
+## The functions below are private to Dpkg::Deps
+
+sub _find_package {
+    my ($self, $dep, $lackinfos) = @_;
+    my ($pkg, $archqual) = ($dep->{package}, $dep->{archqual});
+    return undef if not exists $self->{pkg}{$pkg};
+    my $host_arch = $dep->{host_arch};
+    foreach my $p (@{$self->{pkg}{$pkg}}) {
+       my $a = $p->{"architecture"};
+       my $ma = $p->{"multi-arch"};
+       if (not defined $a) {
+           $$lackinfos = 1;
+           next;
+       }
+       return $p if $ma eq "foreign";
+       if (not defined $archqual) {
+           return $p if $a eq $host_arch or $a eq "all";
+       } elsif ($archqual eq "any") {
+           return $p if $ma eq "allowed";
+           return $p if $a eq $host_arch or $a eq "all";
+       }
+    }
+    return undef;
+}
+
+sub _find_virtual_packages {
+    my ($self, $pkg) = @_;
+    return () if not exists $self->{virtualpkg}{$pkg};
+    return @{$self->{virtualpkg}{$pkg}};
+}
+
+sub _evaluate_simple_dep {
+    my ($self, $dep) = @_;
+    my ($lackinfos, $pkg) = (0, $dep->{package});
+    my $p = $self->_find_package($dep, \$lackinfos);
+    if ($p) {
+       if (defined $dep->{relation}) {
+           if (defined $p->{version}) {
+               return 1 if version_compare_relation($p->{version},
+                                          $dep->{relation}, $dep->{version});
+           } else {
+               $lackinfos = 1;
+           }
+       } else {
+           return 1;
+       }
+    }
+    foreach my $virtpkg ($self->_find_virtual_packages($pkg)) {
+       # XXX: Adapt when versioned provides are allowed
+       next if defined $virtpkg->[1];
+       next if defined $dep->{relation}; # Provides don't satisfy versioned 
deps
+       return 1;
+    }
+    return undef if $lackinfos;
+    return 0;
+}
+
 =head1 CHANGES
 
 =head2 Version 1.01
@@ -1257,6 +1308,12 @@ sub check_package {
 =item * Dpkg::Deps::Simple now recognizes the arch qualifier "any" and
 stores it in the "archqual" property when present.
 
+=item * Dpkg::Deps::KnownFacts->add_installed_package() now accepts 2
+supplementary parameters ($arch and $multiarch).
+
+=item * Dpkg::Deps::KnownFacts->check_package() is obsolete, it should
+not have been part of the public API.
+
 =back
 
 =cut
diff --git a/scripts/dpkg-checkbuilddeps.pl b/scripts/dpkg-checkbuilddeps.pl
index 017e16e..93af92e 100755
--- a/scripts/dpkg-checkbuilddeps.pl
+++ b/scripts/dpkg-checkbuilddeps.pl
@@ -123,7 +123,10 @@ sub parse_status {
        
                my ($package) = /^Package: (.*)$/m;
                my ($version) = /^Version: (.*)$/m;
-               $facts->add_installed_package($package, $version);
+               my ($arch) = /^Architecture: (.*)$/m;
+               my ($multiarch) = /^Multi-Arch: (.*)$/m;
+               $facts->add_installed_package($package, $version, $arch,
+                                             $multiarch);
        
                if (/^Provides: (.*)$/m) {
                        my $provides = deps_parse($1, reduce_arch => 1, union 
=> 1);
diff --git a/scripts/dpkg-gencontrol.pl b/scripts/dpkg-gencontrol.pl
index 1cf6945..be30cc8 100755
--- a/scripts/dpkg-gencontrol.pl
+++ b/scripts/dpkg-gencontrol.pl
@@ -225,7 +225,8 @@ $fields->{'Version'} = $forceversion if 
defined($forceversion);
 # initialized.
 
 my $facts = Dpkg::Deps::KnownFacts->new();
-$facts->add_installed_package($fields->{'Package'}, $fields->{'Version'});
+$facts->add_installed_package($fields->{'Package'}, $fields->{'Version'},
+                              $fields->{'Architecture'}, 
$fields->{'Multi-Arch'});
 if (exists $pkg->{"Provides"}) {
     my $provides = deps_parse($substvars->substvars($pkg->{"Provides"}, 
no_warn => 1),
                               reduce_arch => 1, union => 1);
diff --git a/scripts/t/400_Dpkg_Deps.t b/scripts/t/400_Dpkg_Deps.t
index 34ccc49..932d113 100644
--- a/scripts/t/400_Dpkg_Deps.t
+++ b/scripts/t/400_Dpkg_Deps.t
@@ -18,6 +18,7 @@ use Test::More tests => 20;
 use strict;
 use warnings;
 
+use Dpkg::Arch qw(get_host_arch);
 use_ok('Dpkg::Deps');
 
 my $field_multiline = " , , libgtk2.0-common (= 2.10.13-1)  , libatk1.0-0 (>=
@@ -59,14 +60,21 @@ is($dep_hurd->output(), "libc0.1", "Arch reduce 3/3");
 
 
 my $facts = Dpkg::Deps::KnownFacts->new();
-$facts->add_installed_package("mypackage", "1.3.4-1");
+$facts->add_installed_package("mypackage", "1.3.4-1", get_host_arch(), "no");
+$facts->add_installed_package("mypackage2", "1.3.4-1", "somearch", "no");
+$facts->add_installed_package("pkg-ma-foreign", "1.3.4-1", "somearch", 
"foreign");
+$facts->add_installed_package("pkg-ma-foreign2", "1.3.4-1", get_host_arch(), 
"foreign");
+$facts->add_installed_package("pkg-ma-allowed", "1.3.4-1", "somearch", 
"allowed");
+$facts->add_installed_package("pkg-ma-allowed2", "1.3.4-1", "somearch", 
"allowed");
+$facts->add_installed_package("pkg-ma-allowed3", "1.3.4-1", get_host_arch(), 
"allowed");
 $facts->add_provided_package("myvirtual", undef, undef, "mypackage");
 
 my $field_duplicate = "libc6 (>= 2.3), libc6 (>= 2.6-1), mypackage (>=
-1.3), myvirtual | something, python (>= 2.5)";
+1.3), myvirtual | something, python (>= 2.5), mypackage2, pkg-ma-foreign,
+pkg-ma-foreign2, pkg-ma-allowed:any, pkg-ma-allowed2, pkg-ma-allowed3";
 my $dep_dup = deps_parse($field_duplicate);
 $dep_dup->simplify_deps($facts, $dep_opposite);
-is($dep_dup->output(), "libc6 (>= 2.6-1)", "Simplify deps");
+is($dep_dup->output(), "libc6 (>= 2.6-1), mypackage2, pkg-ma-allowed2", 
"Simplify deps");
 
 my $field_dup_union = "libc6 (>> 2.3), libc6 (>= 2.6-1), fake (<< 2.0),
 fake(>> 3.0), fake (= 2.5), python (<< 2.5), python (= 2.4)";

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to