use warnings;
use strict;
-use base qw(Exporter);
+use Exporter qw(import);
use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS @EXPORT);
use Carp;
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);
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;
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),
@{$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};
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;
=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
return_archs => {type => BOOLEAN,
default => 0,
},
+ largest_source_version_only => {type => BOOLEAN,
+ default => 1,
+ },
},
);
my $versions;
$_ ne 'source'
} $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,
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;
}