]> git.donarmstrong.com Git - debbugs.git/blobdiff - Debbugs/Packages.pm
Merge remote-tracking branch 'origin/master' into database
[debbugs.git] / Debbugs / Packages.pm
index 482938da9310a672ddf36dc37fce57768789f64f..877466f91d2b4ce7f64c489546b0c34b79344a74 100644 (file)
@@ -12,7 +12,7 @@ package Debbugs::Packages;
 use warnings;
 use strict;
 
-use base qw(Exporter);
+use Exporter qw(import);
 use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS @EXPORT);
 
 use Carp;
@@ -37,9 +37,9 @@ use Fcntl qw(O_RDONLY);
 use MLDBM qw(DB_File Storable);
 use Storable qw(dclone);
 use Params::Validate qw(validate_with :types);
-use Debbugs::Common qw(make_list globify_scalar);
+use Debbugs::Common qw(make_list globify_scalar sort_versions);
 
-use List::Util qw(min max);
+use List::AllUtils qw(min max);
 
 use IO::File;
 
@@ -72,13 +72,14 @@ our $_pkgcomponent;
 our $_srcpkg;
 sub getpkgsrc {
     return $_pkgsrc if $_pkgsrc;
-    return {} unless defined $Debbugs::Packages::gPackageSource;
+    return {} unless defined $config{package_source} and
+       length $config{package_source};
     my %pkgsrc;
     my %pkgcomponent;
     my %srcpkg;
 
     my $fh = IO::File->new($config{package_source},'r')
-       or die("Unable to open $config{package_source} for reading: $!");
+       or croak("Unable to open $config{package_source} for reading: $!");
     while(<$fh>) {
        next unless m/^(\S+)\s+(\S+)\s+(\S.*\S)\s*$/;
        my ($bin,$cmp,$src)=($1,$2,$3);
@@ -186,12 +187,15 @@ sub binary_to_source{
                                         cache => {type => HASHREF,
                                                   default => {},
                                                  },
+                                        schema => {type => OBJECT,
+                                                   optional => 1,
+                                                  },
                                        },
                             );
 
     # TODO: This gets hit a lot, especially from buggyversion() - probably
     # need an extra cache for speed here.
-    return () unless defined $gBinarySourceMap;
+    return () unless defined $gBinarySourceMap or defined $param{schema};
 
     if ($param{scalar_only} or not wantarray) {
        $param{source_only} = 1;
@@ -203,6 +207,59 @@ sub binary_to_source{
     my @versions = grep {defined $_} make_list(exists $param{version}?$param{version}:[]);
     my @archs = grep {defined $_} make_list(exists $param{arch}?$param{arch}:[]);
     return () unless @binaries;
+
+    # any src:foo is source package foo with unspecified version
+    @source = map {/^src:(.+)$/?
+                      [$1,'']:()} @binaries;
+    @binaries = grep {$_ !~ /^src:/} @binaries;
+    if ($param{schema}) {
+       if ($param{source_only}) {
+           @source = map {$_->[0]} @source;
+           my $src_rs = $param{schema}->resultset('SrcPkg')->
+               search_rs({'binpkg.pkg' => [@binaries],
+                          @versions?('bin_vers.ver'    => [@versions]):(),
+                          @archs?('arch.arch' => [@archs]):(),
+                         },
+                        {join => {'src_vers'=>
+                                 {'bin_vers'=> ['arch','bin_pkg']}
+                                 },
+                         distinct => 1,
+                        },
+                        );
+           push @source,
+               map {$_->pkg} $src_rs->all;
+           if ($param{scalar_only}) {
+               return join(',',@source);
+           }
+           return @source;
+
+       }
+       my $src_rs = $param{schema}->resultset('SrcVer')->
+           search_rs({'bin_pkg.pkg' => [@binaries],
+                      @versions?('bin_vers.ver' => [@versions]):(),
+                      @archs?('arch.arch' => [@archs]):(),
+                     },
+                    {join => ['src_pkg',
+                             {'bin_vers' => ['arch','binpkg']},
+                             ],
+                     distinct => 1,
+                    },
+                    );
+       push @source,
+           map {[$_->get_column('src_pkg.pkg'),
+                 $_->get_column('src_ver.ver'),
+                ]} $src_rs->all;
+       if (not @source and not @versions and not @archs) {
+           $src_rs = $param{schema}->resultset('SrcPkg')->
+               search_rs({pkg => [@binaries]},
+                        {distinct => 1},
+                        );
+           push @source,
+               map {[$_->pkg,
+                    ]} $src_rs->all;
+       }
+       return @source;
+    }
     my $cache_key = join("\1",
                         join("\0",@binaries),
                         join("\0",@versions),
@@ -213,18 +270,14 @@ sub binary_to_source{
            @{$param{cache}{$cache_key}};
     }
     for my $binary (@binaries) {
-       if ($binary =~ m/^src:(.+)$/) {
-           push @source,[$1,''];
-           next;
-       }
        if (not tied %_binarytosource) {
            tie %_binarytosource, MLDBM => $config{binary_source_map}, O_RDONLY or
                die "Unable to open $config{binary_source_map} for reading";
        }
        # avoid autovivification
        my $bin = $_binarytosource{$binary};
+       next unless defined $bin;
        if (not @versions) {
-           next unless defined $bin;
            for my $ver (keys %{$bin}) {
                for my $ar (keys %{$bin->{$ver}}) {
                    my $src = $bin->{$ver}{$ar};
@@ -234,7 +287,6 @@ sub binary_to_source{
            }
        }
        else {
-           my $found_one_version = 0;
            for my $version (@versions) {
                next unless exists $bin->{$version};
                if (exists $bin->{$version}{all}) {
@@ -283,6 +335,9 @@ sub binary_to_source{
     if ($param{source_only}) {
        my %uniq;
        for my $s (@source) {
+           # we shouldn't need to do this, but do this temporarily to
+           # stop the warning.
+           next unless defined $s->[0];
            $uniq{$s->[0]} = 1;
        }
        @result = sort keys %uniq;
@@ -390,6 +445,11 @@ may change in the future, so if you care, please code accordingly.)
 =item return_archs -- returns a version=>[archs] hash indicating which
 architectures are at which versions.
 
+=item largest_source_version_only -- if there is more than one source
+version in a particular distribution, discards all versions but the
+largest in that distribution. Defaults to 1, as this used to be the
+way that the Debian archive worked.
+
 =back
 
 When called in scalar context, this function will return hashrefs or
@@ -423,6 +483,9 @@ sub get_versions{
                                           return_archs => {type => BOOLEAN,
                                                            default => 0,
                                                           },
+                                          largest_source_version_only => {type => BOOLEAN,
+                                                                      default => 1,
+                                                                         },
                                          },
                               );
      my $versions;
@@ -444,6 +507,10 @@ sub get_versions{
      }
      my %versions;
      for my $package (make_list($param{package})) {
+         my $source_only = 0;
+         if ($package =~ s/^src://) {
+              $source_only = 1;
+         }
          my $version = $versions->{$package};
          next unless defined $version;
          for my $dist (make_list($param{dist})) {
@@ -451,12 +518,18 @@ sub get_versions{
                             make_list($param{arch}):
                             (grep {not $param{no_source_arch} or
                                        $_ ne 'source'
-                                   } keys %{$version->{$dist}})) {
+                                   } $source_only?'source':keys %{$version->{$dist}})) {
                    next unless defined $version->{$dist}{$arch};
-                   for my $ver (ref $version->{$dist}{$arch} ?
-                                keys %{$version->{$dist}{$arch}} :
-                                $version->{$dist}{$arch}
-                               ) {
+                   my @vers = ref $version->{$dist}{$arch} eq 'HASH' ?
+                       keys %{$version->{$dist}{$arch}} :
+                           make_list($version->{$dist}{$arch});
+                   if ($param{largest_source_version_only} and
+                       $arch eq 'source' and @vers > 1) {
+                       # order the versions, then pick the biggest version number
+                       @vers = sort_versions(@vers);
+                       @vers = $vers[-1];
+                   }
+                   for my $ver (@vers) {
                         my $f_ver = $ver;
                         if ($param{source}) {
                              ($f_ver) = make_source_versions(package => $package,
@@ -509,7 +582,6 @@ sub makesourceversions {
                           arch    => 'source',
                           versions => '0.1.1',
                           guess_source => 1,
-                          debug    => \$debug,
                           warnings => \$warnings,
                          );
 
@@ -552,7 +624,6 @@ sub make_source_versions {
                                        },
                             );
     my ($warnings) = globify_scalar(exists $param{warnings}?$param{warnings}:undef);
-    my ($debug)    = globify_scalar(exists $param{debug}   ?$param{debug}   :undef);
 
     my @packages = grep {defined $_ and length $_ } make_list($param{package});
     my @archs    = grep {defined $_ } make_list ($param{arch});
@@ -589,7 +660,7 @@ sub make_source_versions {
                    my @bin_versions = sourcetobinary($1,$version);
                    if (not @bin_versions or
                        @{$bin_versions[0]} != 3) {
-                       print {$warnings} "The source $1 and version $2 do not appear to match any binary packages\n";
+                       print {$warnings} "The source '$1' and version '$version' do not appear to match any binary packages\n";
                    }
                    next;
                }