X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Debbugs%2FStatus.pm;h=797bbdde1d87695547af231e98effc25ea7d279a;hb=e70cd2221904f79524d0e60e30506e13b6fc9cfa;hp=9d047a40b053a6867d4b10b24d0486c88e6c8a1e;hpb=53c435119200ab9b1c2538a96b8374c51a078855;p=debbugs.git diff --git a/Debbugs/Status.pm b/Debbugs/Status.pm index 9d047a4..797bbdd 100644 --- a/Debbugs/Status.pm +++ b/Debbugs/Status.pm @@ -63,6 +63,7 @@ BEGIN{ @EXPORT = (); %EXPORT_TAGS = (status => [qw(splitpackages get_bug_status buggy bug_archiveable), qw(isstrongseverity bug_presence split_status_fields), + qw(get_bug_statuses), ], read => [qw(readbug read_bug lockreadbug lockreadbugmerge), qw(lock_read_all_merged_bugs), @@ -964,20 +965,24 @@ Returns undef on failure. # This will eventually need to be fixed before we start using mod_perl our $version_cache = {}; sub bug_archiveable{ + state $spec = {bug => {type => SCALAR, + regex => qr/^\d+$/, + }, + status => {type => HASHREF, + optional => 1, + }, + days_until => {type => BOOLEAN, + default => 0, + }, + ignore_time => {type => BOOLEAN, + default => 0, + }, + schema => {type => OBJECT, + optional => 1, + }, + }; my %param = validate_with(params => \@_, - spec => {bug => {type => SCALAR, - regex => qr/^\d+$/, - }, - status => {type => HASHREF, - optional => 1, - }, - days_until => {type => BOOLEAN, - default => 0, - }, - ignore_time => {type => BOOLEAN, - default => 0, - }, - }, + spec => $spec, ); # This is what we return if the bug cannot be archived. my $cannot_archive = $param{days_until}?-1:0; @@ -1009,16 +1014,16 @@ sub bug_archiveable{ # If we just are checking if the bug can be archived, we'll not even bother # checking the versioning information if the bug has been -done for less than 28 days. my $log_file = getbugcomponent($param{bug},'log'); - if (not defined $log_file) { + if (not defined $log_file or not -e $log_file) { print STDERR "Cannot archive $param{bug} because the log doesn't exist\n" if $DEBUG; return $cannot_archive; } - my $max_log_age = max(map {$config{remove_age} - -M $_} - $log_file, map {my $log = getbugcomponent($_,'log'); + my @log_files = $log_file, (map {my $log = getbugcomponent($_,'log'); defined $log ? ($log) : (); } - split / /, $status->{mergedwith} - ); + split / /, $status->{mergedwith}); + my $max_log_age = max(map {-e $_?($config{remove_age} - -M _):0} + @log_files); if (not $param{days_until} and not $param{ignore_time} and $max_log_age > 0 ) { @@ -1062,6 +1067,7 @@ sub bug_archiveable{ my @sourceversions = get_versions(package => $status->{package}, dist => [keys %dists], source => 1, + hash_slice(%param,'schema'), ); @source_versions{@sourceversions} = (1) x @sourceversions; # If the bug has not been fixed in the versions actually @@ -1072,6 +1078,7 @@ sub bug_archiveable{ fixed => $status->{fixed_versions}, version_cache => $version_cache, package => $status->{package}, + hash_slice(%param,'schema'), )) { print STDERR "Cannot archive $param{bug} because it's found\n" if $DEBUG; return $cannot_archive; @@ -1092,6 +1099,7 @@ sub bug_archiveable{ dist => [keys %dists], source => 1, time => 1, + hash_slice(%param,'schema'), ); for my $version (sort {$time_versions{$b} <=> $time_versions{$a}} keys %time_versions) { my $buggy = buggy(bug => $param{bug}, @@ -1100,6 +1108,7 @@ sub bug_archiveable{ fixed => $status->{fixed_versions}, version_cache => $version_cache, package => $status->{package}, + hash_slice(%param,'schema'), ); last if $buggy eq 'found'; $min_fixed_time = min($time_versions{$version},$min_fixed_time); @@ -1269,117 +1278,159 @@ sub get_bug_status { if (defined $param{bug_index} and exists $param{bug_index}{$param{bug}}) { - %status = %{ $param{bug_index}{$param{bug}} }; - $status{pending} = $status{ status }; - $status{id} = $param{bug}; - return \%status; - } - if (defined $param{status}) { - %status = %{$param{status}}; + %status = %{ $param{bug_index}{$param{bug}} }; + $status{pending} = $status{ status }; + $status{id} = $param{bug}; + return \%status; } - elsif (defined $param{schema}) { - my $b = $param{schema}->resultset('Bug')-> - search_rs({'me.id' => $param{bug}}, - {prefetch => [{'bug_tags'=>'tag'}, - 'severity', - {'bug_binpackages'=> 'bin_pkg'}, - {'bug_srcpackages'=> 'src_pkg'}, - {'bug_user_tags'=>{'user_tag'=>'correspondent'}}, - {owner => 'correspondent_full_names'}, - {submitter => 'correspondent_full_names'}, - 'bug_merged_bugs', - 'bug_mergeds_merged', - 'bug_blocks_blocks', - 'bug_blocks_bugs', - {'bug_vers' => ['src_pkg','src_ver']}, - ], - '+columns' => [qw(subject log_modified creation last_modified)], - collapse => 1, - result_class => 'DBIx::Class::ResultClass::HashRefInflator', - })->first(); - $status{keywords} = - join(' ',map {$_->{tag}{tag}} @{$b->{bug_tags}}); - $status{tags} = $status{keywords}; - $status{subject} = $b->{subject}; - $status{bug_num} = $b->{id}; - $status{severity} = $b->{severity}{severity}; - $status{package} = - join(' ', - (map {$_->{bin_pkg}{pkg}} @{$b->{bug_binpackages}//[]}), - (map {$_->{src_pkg}{pkg}} @{$b->{bug_srcpackages}//[]})); - $status{originator} = $b->{submitter_full}; - $status{log_modified} = - DateTime::Format::Pg->parse_datetime($b->{log_modified})->epoch; - $status{date} = - DateTime::Format::Pg->parse_datetime($b->{creation})->epoch; - $status{last_modified} = - DateTime::Format::Pg->parse_datetime($b->{last_modified})->epoch; - $status{blocks} = - join(' ', - uniq(sort(map {$_->{block}} - @{$b->{bug_blocks_block}}, - ))); - $status{blockedby} = - join(' ', - uniq(sort(map {$_->{bug}} - @{$b->{bug_blocks_bug}}, - ))); - $status{mergedwith} = - join(' ',uniq(sort(map {$_->{bug},$_->{merged}} - @{$b->{bug_merged_bugs}}, - @{$b->{bug_mergeds_merged}}, - ))); - $status{fixed_versions} = - [map {$_->{found}?():$_->{ver_string}} @{$b->{bug_vers}}]; - $status{found_versions} = - [map {$_->{found}?$_->{ver_string}:()} @{$b->{bug_vers}}]; + my $statuses = get_bug_statuses(@_); + if (exists $statuses->{$param{bug}}) { + return $statuses->{$param{bug}}; + } else { + return {}; } - else { - my $location = getbuglocation($param{bug}, 'summary'); - return {} if not defined $location or not length $location; - %status = %{ readbug( $param{bug}, $location ) }; - } - $status{id} = $param{bug}; +} - if (defined $param{bugusertags}{$param{bug}}) { - $status{keywords} = "" unless defined $status{keywords}; - $status{keywords} .= " " unless $status{keywords} eq ""; - $status{keywords} .= join(" ", @{$param{bugusertags}{$param{bug}}}); +sub get_bug_statuses { + state $spec = + {bug => {type => SCALAR|ARRAYREF, + }, + status => {type => HASHREF, + optional => 1, + }, + bug_index => {type => OBJECT, + optional => 1, + }, + version => {type => SCALAR|ARRAYREF, + optional => 1, + }, + dist => {type => SCALAR|ARRAYREF, + optional => 1, + }, + arch => {type => SCALAR|ARRAYREF, + optional => 1, + }, + bugusertags => {type => HASHREF, + optional => 1, + }, + sourceversions => {type => ARRAYREF, + optional => 1, + }, + indicatesource => {type => BOOLEAN, + default => 1, + }, + binary_to_source_cache => {type => HASHREF, + optional => 1, + }, + schema => {type => OBJECT, + optional => 1, + }, + }; + my %param = validate_with(params => \@_, + spec => $spec, + ); + my $bin_to_src_cache = {}; + if (defined $param{binary_to_source_cache}) { + $bin_to_src_cache = $param{binary_to_source_cache}; } - $status{tags} = $status{keywords}; - my %tags = map { $_ => 1 } split ' ', $status{tags}; - - $status{package} = '' if not defined $status{package}; - $status{"package"} =~ s/\s*$//; - - $status{source} = binary_to_source(binary=>[split /\s*,\s*/, $status{package}], - source_only => 1, - exists $param{binary_to_source_cache}? - (cache =>$param{binary_to_source_cache}):(), - ); - - $status{"package"} = 'unknown' if ($status{"package"} eq ''); - $status{"severity"} = 'normal' if (not defined $status{severity} or $status{"severity"} eq ''); - - $status{"pending"} = 'pending'; - $status{"pending"} = 'forwarded' if (length($status{"forwarded"})); - $status{"pending"} = 'pending-fixed' if ($tags{pending}); - $status{"pending"} = 'fixed' if ($tags{fixed}); - + my %status; + my %statuses; + if (defined $param{schema}) { + my @bug_statuses = + $param{schema}->resultset('BugStatus')-> + search_rs({id => [make_list($param{bug})]}, + {result_class => 'DBIx::Class::ResultClass::HashRefInflator'})-> + all(); + for my $bug_status (@bug_statuses) { + $statuses{$bug_status->{bug_num}} = + $bug_status; + for my $field (qw(blocks blockedby done), + qw(tags mergedwith affects) + ) { + $bug_status->{$field} //=''; + } + $bug_status->{keywords} = + $bug_status->{tags}; + $bug_status->{location} = $bug_status->{archived}?'archive':'db-h'; + for my $field (qw(found_versions fixed_versions found_date fixed_date)) { + $bug_status->{$field} = [split ' ', $bug_status->{$field} // '']; + } + for my $field (qw(found fixed)) { + # create the found/fixed hashes which indicate when a + # particular version was marked found or marked fixed. + @{$bug_status->{$field}}{@{$bug_status->{"${field}_versions"}}} = + (('') x (@{$bug_status->{"${field}_versions"}} - + @{$bug_status->{"${field}_date"}}), + @{$bug_status->{"${field}_date"}}); + } + $bug_status->{id} = $bug_status->{bug_num}; + } + } else { + for my $bug (make_list($param{bug})) { + if (defined $param{bug_index} and + exists $param{bug_index}{$bug}) { + my %status = %{$param{bug_index}{$bug}}; + $status{pending} = $status{status}; + $status{id} = $bug; + $statuses{$bug} = \%status; + } + elsif (defined $param{status} and + $param{status}{bug_num} == $bug + ) { + $statuses{$bug} = {%{$param{status}}}; + } else { + my $location = getbuglocation($bug, 'summary'); + next if not defined $location or not length $location; + my %status = %{ readbug( $bug, $location ) }; + $status{id} = $bug; + $statuses{$bug} = \%status; + } + } + } + for my $bug (keys %statuses) { + my $status = $statuses{$bug}; - my $presence = bug_presence(status => \%status, - map{(exists $param{$_})?($_,$param{$_}):()} - qw(bug sourceversions arch dist version found fixed package) - ); - if (defined $presence) { - if ($presence eq 'fixed') { - $status{pending} = 'done'; - } - elsif ($presence eq 'absent') { - $status{pending} = 'absent'; - } + if (defined $param{bugusertags}{$param{bug}}) { + $status->{keywords} = "" unless defined $status->{keywords}; + $status->{keywords} .= " " unless $status->{keywords} eq ""; + $status->{keywords} .= join(" ", @{$param{bugusertags}{$param{bug}}}); + } + $status->{tags} = $status->{keywords}; + my %tags = map { $_ => 1 } split ' ', $status->{tags}; + + $status->{package} = '' if not defined $status->{package}; + $status->{"package"} =~ s/\s*$//; + + $status->{source} = binary_to_source(binary=>[split /\s*,\s*/, $status->{package}], + source_only => 1, + cache => $bin_to_src_cache, + defined $param{schema}? + (schema => $param{schema}):(), + ); + + $status->{"package"} = 'unknown' if ($status->{"package"} eq ''); + $status->{"severity"} = 'normal' if (not defined $status->{severity} or $status->{"severity"} eq ''); + + $status->{"pending"} = 'pending'; + $status->{"pending"} = 'forwarded' if (length($status->{"forwarded"})); + $status->{"pending"} = 'pending-fixed' if ($tags{pending}); + $status->{"pending"} = 'fixed' if ($tags{fixed}); + + + my $presence = bug_presence(status => $status, + bug => $bug, + map{(exists $param{$_})?($_,$param{$_}):()} + qw(sourceversions arch dist version found fixed package) + ); + if (defined $presence) { + if ($presence eq 'fixed') { + $status->{pending} = 'done'; + } elsif ($presence eq 'absent') { + $status->{pending} = 'absent'; + } + } } - return \%status; + return \%statuses; } =head2 bug_presence @@ -1601,6 +1652,9 @@ sub max_buggy{ version_cache => {type => HASHREF, default => {}, }, + schema => {type => OBJECT, + optional => 1, + }, }, ); # Resolve bugginess states (we might be looking at multiple @@ -1663,6 +1717,9 @@ sub buggy { }, version => {type => SCALAR, }, + schema => {type => OBJECT, + optional => 1, + }, }, ); my @found = @{$param{found}}; @@ -1697,8 +1754,10 @@ sub buggy { my $version_fh = IO::File->new("$config{version_packages_dir}/$srchash/$source", 'r'); if (not defined $version_fh) { # We only want to warn if it's a package which actually has a maintainer - my $maints = getmaintainers(); - next if not exists $maints->{$source}; + my @maint = package_maintainer(source => $source, + hash_slice(%param,'schema'), + ); + next unless @maint; warn "Bug $param{bug}: unable to open $config{version_packages_dir}/$srchash/$source: $!"; next; }