]> git.donarmstrong.com Git - debbugs.git/blobdiff - Debbugs/Collection/Package.pm
Resolve issues with get_source_versions{,_distributions}
[debbugs.git] / Debbugs / Collection / Package.pm
index 0459b1e04f31f6e50b7ca1921dacbea6d008530e..09d4bed90b26a82740e9f237bfd6034fc8f86296 100644 (file)
@@ -12,6 +12,10 @@ Debbugs::Collection::Package -- Package generation factory
 
 =head1 SYNOPSIS
 
+This collection extends L<Debbugs::Collection> and contains members of
+L<Debbugs::Package>. Useful for any field which contains one or more package or
+tracking lists of packages
+
 
 =head1 DESCRIPTION
 
@@ -21,57 +25,265 @@ Debbugs::Collection::Package -- Package generation factory
 
 use Mouse;
 use strictures 2;
+use v5.10; # for state
 use namespace::autoclean;
-use Debbugs::Common qw(make_list);
+
+use Carp;
+use Debbugs::Common qw(make_list hash_slice);
+use Debbugs::Config qw(:config);
 use Debbugs::OOTypes;
-use Debbugs::Status qw(get_bug_statuses);
+use Debbugs::Package;
+
+use List::AllUtils qw(part);
+
+use Debbugs::Version::Binary;
+use Debbugs::Collection::Version;
+use Debbugs::Collection::Correspondent;
+use Debbugs::VersionTree;
 
 extends 'Debbugs::Collection';
 
-has '+members' => (isa => 'ArrayRef[Package]');
+=head1 Object Creation
+
+=head2 my $packages = Debbugs::Collection::Package->new(%params|$param)
+
+Parameters in addition to those defined by L<Debbugs::Collection>
+
+=over
+
+=item correspondent_collection
+
+Optional L<Debbugs::Collection::Correspondent> which is used to look up correspondents
+
+
+=item versiontree
+
+Optional L<Debbugs::VersionTree> which contains known package source versions
+
+=back
+
+=head1 Methods
+
+=head2 correspondent_collection
+
+     $packages->correspondent_collection
+
+Returns the L<Debbugs::Collection::Correspondent> for this package collection
+
+=head2 versiontree
+
+Returns the L<Debbugs::VersionTree> for this package collection
+
+=cut
 
-around BUILDARGS => sub {
+has '+members' => (isa => 'ArrayRef[Debbugs::Package]');
+
+sub BUILD {
+    my $self = shift;
+    my $args = shift;
+    if (exists $args->{packages}) {
+        $self->
+            add($self->_member_constructor(packages =>
+                                           $args->{packages}));
+    }
+}
+
+around add_by_key => sub {
     my $orig = shift;
-    my $class = shift;
+    my $self = shift;
+    my @members =
+        $self->_member_constructor(packages => [@_]);
+    return $self->$orig(@members);
+};
 
-    my %args;
-    if (@_==1 and ref($_[0]) eq 'HASH') {
-        %args = %{$_[0]};
-    } else {
-        %args = @_;
+sub _member_constructor {
+    # handle being called $self->_member_constructor;
+    my $self = shift;
+    my %args = @_;
+    my $schema;
+    if ($self->has_schema) {
+        $schema = $self->schema;
     }
-    $args{members} //= [];
-    if (exists $args{packages}) {
-        if (exists $args{schema}) {
-            my $statuses = get_bug_statuses(bug => [make_list($args{bugs})],
-                                            schema => $args{schema},
-                                           );
-            while (my ($bug, $status) = each %{$statuses}) {
-                push @{$args{members}},
-                    Debbugs::Bug->new(bug=>$bug,
-                                      status=>$status,
-                                      schema=>$args{schema},
-                                      @{$args{constructor_args}//[]},
+    my @return;
+    if (defined $schema) {
+        if (not ref($args{packages}) or @{$args{packages}} == 1 and
+            $self->universe->count() > 0
+           ) {
+            carp("Likely inefficiency; member_constructor called with one argument");
+        }
+        my $packages =
+            Debbugs::Package::_get_valid_version_info_from_db(packages => $args{packages},
+                                                              schema => $schema,
+                                                             );
+        for my $package (keys %{$packages}) {
+            push @return,
+                Debbugs::Package->new(%{$packages->{$package}},
+                                      schema => $schema,
+                                      package_collection => $self->universe,
+                                      correspondent_collection =>
+                                      $self->correspondent_collection->universe,
                                      );
-            }
-        } else {
-            for my $bug (make_list($args{bugs})) {
-                push @{$args{members}},
-                    Debbugs::Bug->new(bug => $bug,
-                                      @{$args{constructor_args}//[]},
+        }
+    } else {
+        carp "No schema\n";
+        for my $package (make_list($args{packages})) {
+            push @return,
+                Debbugs::Package->new(name => $package,
+                                      package_collection => $self->universe,
+                                      correspondent_collection =>
+                                      $self->correspondent_collection->universe,
                                      );
-            }
         }
-        delete $args{bugs};
     }
-    return $class->$orig(%args);
-};
+    return @return;
+}
+
+sub add_packages_and_versions {
+    my $self = shift;
+    $self->add($self->_member_constructor(packages => \@_));
+}
+
 
 sub member_key {
-    return $_[1]->bug;
+    return $_[1]->qualified_name;
+}
+
+has 'correspondent_collection' =>
+    (is => 'ro',
+     isa => 'Debbugs::Collection::Correspondent',
+     default => sub {Debbugs::Collection::Correspondent->new()},
+    );
+
+has 'versiontree' =>
+    (is => 'ro',
+     isa => 'Debbugs::VersionTree',
+     lazy => 1,
+     builder => '_build_versiontree',
+    );
+
+sub _build_versiontree {
+    my $self = shift;
+    return Debbugs::VersionTree->new($self->has_schema?(schema => $self->schema):());
 }
 
+=head2 get_source_versions_distributions
+
+     $packages->get_source_versions_distributions('unstable')
+
+Given a list of distributions or suites, returns a
+L<Debbugs::Collection::Version> of all of the versions in this package
+collection which are known to match.
+
+Effectively, this calls L<Debbugs::Package/get_source_version_distribution> for
+each package in the collection and merges the results and returns them
+
+=cut
+
+sub get_source_versions_distributions {
+    my $self = shift;
+    my @return;
+    push @return,
+        $self->map(sub {$_->get_source_version_distribution(@_)});
+    if (@return > 1) {
+        return $return[0]->combine($return[1..$#return]);
+    }
+    return @return;
+}
+
+
+=head2 get_source_versions
+
+    $packages->get_source_versions('1.2.3-1','foo/1.2.3-5')
+
+Given a list of binary versions or src/versions, returns a
+L<Debbugs::Collection::Version> of all of the versions in this package
+collection which are known to match.
+
+If you give a binary version ('1.2.3-1'), you must have already loaded source
+packages into this package collection for it to find an appropriate match.
+
+If no package is known to match, an version which is invalid will be returned
+
+For fully qualified versions this loads the appropriate source package into the
+universe of this collection and calls L<Debbugs::Package/get_source_version>.
+For unqualified versions, calls L<Debbugs::Package/get_source_version>; if no
+valid versions are returned, creates an invalid version.
+
+=cut
+
+sub get_source_versions {
+    my $self = shift;
+    my @return;
+    for my $ver (@_) {
+        my $sv;
+        if ($ver =~ m{(?<src>.+?)/(?<ver>.+)$}) {
+            my $sp = $self->universe->
+                get_or_add_by_key('src:'.$+{src});
+            push @return,
+                $sp->get_source_version($+{ver});
+           next;
+        } else {
+            my $found_valid = 0;
+            for my $p ($self->members) {
+                local $_;
+                my @vs =
+                    grep {$_->is_valid}
+                    $p->get_source_version($ver);
+                if (@vs) {
+                    $found_valid = 1;
+                    push @return,@vs;
+                    next;
+                }
+            }
+            if (not $found_valid) {
+                push @return,
+                    Debbugs::Version::Binary->new(version => $ver,
+                                                  package_collection => $self->universe,
+                                                  valid => 0,
+                                                  $self->schema_argument,
+                                                 );
+            }
+        }
+    }
+    return
+        Debbugs::Collection::Version->new(members => \@return,
+                                          $self->schema_argument,
+                                          package_collection => $self->universe,
+                                         );
+}
+
+=head2 source_names
+
+     $packages->source_names()
+
+Returns a unique list of source names from all members of this collection by
+calling L<Debbugs::Package/source_names> on each member.
+
+=cut
+
+sub source_names {
+    my $self = shift;
+    local $_;
+    return uniq map {$_->source_names} $self->members;
+}
+
+=head2 sources
+
+     $packages->sources()
+
+Returns a L<Debbugs::Collection::Package> limited to source packages
+corresponding to all packages in this collection
+
+=cut
+
+sub sources {
+    my $self = shift;
+    return $self->universe->limit($self->source_names);
+}
+
+
 __PACKAGE__->meta->make_immutable;
+no Mouse;
 
 1;