X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Debbugs%2FStatus.pm;h=55b29d5f3acdf986353a318ad0875b5c2f798544;hb=d71fc45879d5a0125f9e6d5ca1fe6fd78e028a54;hp=6b6fabd3654442c21be344740b31e578268a860e;hpb=ecc6d36288fd487ab084dc083cbe9d21df965639;p=debbugs.git diff --git a/Debbugs/Status.pm b/Debbugs/Status.pm index 6b6fabd..55b29d5 100644 --- a/Debbugs/Status.pm +++ b/Debbugs/Status.pm @@ -178,7 +178,7 @@ sub read_bug{ $log =~ s/\.summary$/.log/; ($location) = $status =~ m/(db-h|db|archive)/; } - my $status_fh = new IO::File $status, 'r' or + my $status_fh = IO::File->new($status, 'r') or warn "Unable to open $status for reading: $!" and return undef; my %data; @@ -193,7 +193,10 @@ sub read_bug{ } # Version 3 is the latest format version currently supported. - return undef if $version > 3; + if ($version > 3) { + warn "Unsupported status version '$version'"; + return undef; + } my %namemap = reverse %fields; for my $line (@lines) { @@ -226,6 +229,7 @@ sub read_bug{ # Add log last modified time $data{log_modified} = (stat($log))[9]; $data{location} = $location; + $data{bug_num} = $param{bug}; return \%data; } @@ -244,7 +248,7 @@ See readbug above for information on what this returns sub lockreadbug { my ($lref, $location) = @_; - &filelock("lock/$lref"); + &filelock("$config{spool_dir}/lock/$lref"); my $data = read_bug(bug => $lref, location => $location); &unfilelock unless defined $data; return $data; @@ -270,7 +274,7 @@ sub lockreadbugmerge { return (1,$data); } unfilelock(); - filelock('lock/merge'); + filelock("$config{spool_dir}/lock/merge"); $data = lockreadbug(@_); if (not defined $data) { unfilelock(); @@ -369,17 +373,17 @@ sub writebug { for my $version (keys %outputs) { next if defined $minversion and $version < $minversion; my $status = getbugcomponent($ref, $outputs{$version}, $location); - &quit("can't find location for $ref") unless defined $status; - open(S,"> $status.new") || &quit("opening $status.new: $!"); + die "can't find location for $ref" unless defined $status; + open(S,"> $status.new") || die "opening $status.new: $!"; print(S makestatus($data, $version)) || - &quit("writing $status.new: $!"); - close(S) || &quit("closing $status.new: $!"); + die "writing $status.new: $!"; + close(S) || die "closing $status.new: $!"; if (-e $status) { $change = 'change'; } else { $change = 'new'; } - rename("$status.new",$status) || &quit("installing new $status: $!"); + rename("$status.new",$status) || die "installing new $status: $!"; } # $disablebughook is a bit of a hack to let format migration scripts use @@ -529,24 +533,20 @@ sub removefixedversions { my $version = shift; my $isbinary = shift; return unless defined $version; - undef $package if $package =~ m[(?:\s|/)]; - my $source = $package; - - if (defined $package and $isbinary) { - my @srcinfo = binarytosource($package, $version, undef); - if (@srcinfo) { - # We know the source package(s). Use a fully-qualified version. - removefixedversions($data, $_->[0], $_->[1], '') foreach @srcinfo; - return; - } - # Otherwise, an unqualified version will have to do. - undef $source; - } foreach my $ver (split /[,\s]+/, $version) { - my $sver = defined($source) ? "$source/$ver" : ''; - @{$data->{fixed_versions}} = - grep { $_ ne $ver and $_ ne $sver } @{$data->{fixed_versions}}; + if ($ver =~ m{/}) { + # fully qualified version + @{$data->{fixed_versions}} = + grep {$_ ne $ver} + @{$data->{fixed_versions}}; + } + else { + # non qualified version; delete all matchers + @{$data->{fixed_versions}} = + grep {$_ !~ m[(?:^|/)\Q$ver\E$]} + @{$data->{fixed_versions}}; + } } } @@ -620,17 +620,44 @@ sub bug_archiveable{ my $status = $param{status}; if (not exists $param{status} or not defined $status) { $status = read_bug(bug=>$param{bug}); - return undef if not defined $status; + if (not defined $status) { + print STDERR "Cannot archive $param{bug} because it does not exist\n" if $DEBUG; + return undef; + } } # Bugs can be archived if they are # 1. Closed - return $cannot_archive if not defined $status->{done} or not length $status->{done}; + if (not defined $status->{done} or not length $status->{done}) { + print STDERR "Cannot archive $param{bug} because it is not done\n" if $DEBUG; + return $cannot_archive + } + # Check to make sure that the bug has none of the unremovable tags set + if (@{$config{removal_unremovable_tags}}) { + for my $tag (split ' ', ($status->{tags}||'')) { + if (grep {$tag eq $_} @{$config{removal_unremovable_tags}}) { + print STDERR "Cannot archive $param{bug} because it has an unremovable tag '$tag'\n" if $DEBUG; + return $cannot_archive; + } + } + } + # 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) { + 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'); + defined $log ? ($log) : (); + } + split / /, $status->{mergedwith} + ); if (not $param{days_until} and not $param{ignore_time} - and $config{remove_age} > - -M getbugcomponent($param{bug},'log') + and $max_log_age > 0 ) { + print STDERR "Cannot archive $param{bug} because of time\n" if $DEBUG; return $cannot_archive; } # At this point, we have to get the versioning information for this bug. @@ -638,6 +665,10 @@ sub bug_archiveable{ # tags set, we assume a default set, otherwise we use the tags the bug # has set. + # In cases where we are assuming a default set, if the severity + # is strong, we use the strong severity default; otherwise, we + # use the normal default. + # There must be fixed_versions for us to look at the versioning # information my $min_fixed_time = time; @@ -647,11 +678,20 @@ sub bug_archiveable{ @dist_tags{@{$config{removal_distribution_tags}}} = (1) x @{$config{removal_distribution_tags}}; my %dists; - @dists{@{$config{removal_default_distribution_tags}}} = - (1) x @{$config{removal_default_distribution_tags}}; for my $tag (split ' ', ($status->{tags}||'')) { - next unless $dist_tags{$tag}; - $dists{$tag} = 1; + next unless exists $config{distribution_aliases}{$tag}; + next unless $dist_tags{$config{distribution_aliases}{$tag}}; + $dists{$config{distribution_aliases}{$tag}} = 1; + } + if (not keys %dists) { + if (isstrongseverity($status->{severity})) { + @dists{@{$config{removal_strong_severity_default_distribution_tags}}} = + (1) x @{$config{removal_strong_severity_default_distribution_tags}}; + } + else { + @dists{@{$config{removal_default_distribution_tags}}} = + (1) x @{$config{removal_default_distribution_tags}}; + } } my %source_versions; my @sourceversions = get_versions(package => $status->{package}, @@ -668,6 +708,7 @@ sub bug_archiveable{ version_cache => $version_cache, package => $status->{package}, )) { + print STDERR "Cannot archive $param{bug} because it's found\n" if $DEBUG; return $cannot_archive; } # Since the bug has at least been fixed in the architectures @@ -698,15 +739,19 @@ sub bug_archiveable{ last if $buggy eq 'found'; $min_fixed_time = min($time_versions{$version},$min_fixed_time); } - $min_archive_days = max($min_archive_days,ceil($config{remove_age} - (time - $min_fixed_time)/(60*60*24))); + $min_archive_days = max($min_archive_days,ceil($config{remove_age} - (time - $min_fixed_time)/(60*60*24))) + # if there are no versions in the archive at all, then + # we can archive if enough days have passed + if @sourceversions; } # If $param{ignore_time}, then we should ignore time. if ($param{ignore_time}) { return $param{days_until}?0:1; } # 6. at least 28 days have passed since the last action has occured or the bug was closed - my $age = ceil($config{remove_age} - -M getbugcomponent($param{bug},'log')); + my $age = ceil($max_log_age); if ($age > 0 or $min_archive_days > 0) { + print STDERR "Cannot archive $param{bug} because not enough days have passed\n" if $DEBUG; return $param{days_until}?max($age,$min_archive_days):0; } else { @@ -739,12 +784,17 @@ currently not correctly implemented. =item arch -- optional architecture(s) to check package status at -=item usertags -- optional hashref of usertags +=item bugusertags -- optional hashref of bugusertags =item sourceversion -- optional arrayref of source/version; overrides dist, arch, and version. [The entries in this array must be in the "source/version" format.] Eventually this can be used to for caching. +=item indicatesource -- if true, indicate which source packages this +bug could belong to. Defaults to false. [Note that eventually we will +properly allow bugs that only affect a source package, and this will +become always on.] + =back Note: Currently the version information is cached; this needs to be @@ -775,12 +825,15 @@ sub get_bug_status { arch => {type => SCALAR|ARRAYREF, optional => 1, }, - usertags => {type => HASHREF, - optional => 1, - }, + bugusertags => {type => HASHREF, + optional => 1, + }, sourceversions => {type => ARRAYREF, optional => 1, }, + indicatesource => {type => BOOLEAN, + default => 0, + }, }, ); my %status; @@ -802,15 +855,21 @@ sub get_bug_status { } $status{id} = $param{bug}; - if (defined $param{usertags}{$param{bug}}) { + if (defined $param{bugusertags}{$param{bug}}) { $status{keywords} = "" unless defined $status{keywords}; $status{keywords} .= " " unless $status{keywords} eq ""; - $status{keywords} .= join(" ", @{$param{usertags}{$param{bug}}}); + $status{keywords} .= join(" ", @{$param{bugusertags}{$param{bug}}}); } $status{tags} = $status{keywords}; my %tags = map { $_ => 1 } split ' ', $status{tags}; $status{"package"} =~ s/\s*$//; + if ($param{indicatesource} and $status{package} ne '') { + $status{source} = join(', ',binarytosource($status{package})); + } + else { + $status{source} = 'unknown'; + } $status{"package"} = 'unknown' if ($status{"package"} eq ''); $status{"severity"} = 'normal' if ($status{"severity"} eq ''); @@ -904,9 +963,14 @@ sub bug_presence { } my @sourceversions; + my $pseudo_desc = getpseudodesc(); if (not exists $param{sourceversions}) { my %sourceversions; - if (defined $param{version}) { + # pseudopackages do not have source versions by definition. + if (exists $pseudo_desc->{$status{package}}) { + # do nothing. + } + elsif (defined $param{version}) { foreach my $arch (make_list($param{arch})) { for my $package (split /\s*,\s*/, $status{package}) { my @temp = makesourceversions($package, @@ -934,6 +998,7 @@ sub bug_presence { # TODO: This should probably be handled further out for efficiency and # for more ease of distinguishing between pkg= and src= queries. + # DLA: src= queries should just pass arch=source, and they'll be happy. @sourceversions = keys %sourceversions; } else { @@ -949,7 +1014,8 @@ sub bug_presence { version_cache => $version_cache, ); } - elsif (defined $param{dist}) { + elsif (defined $param{dist} and + not exists $pseudo_desc->{$status{package}}) { return 'absent'; } if (length($status{done}) and @@ -1076,23 +1142,31 @@ sub buggy { ); } if ($param{version} !~ m{/}) { - $param{version} = makesourceversions($param{package},undef, - $param{version} - ); + my ($version) = makesourceversions($param{package},undef, + $param{version} + ); + $param{version} = $version if defined $version; } # Figure out which source packages we need my %sources; @sources{map {m{(.+)/}; $1} @found} = (1) x @found; @sources{map {m{(.+)/}; $1} @fixed} = (1) x @fixed; - @sources{map {m{(.+)/}; $1} $param{version}} = 1; + @sources{map {m{(.+)/}; $1} $param{version}} = 1 if + $param{version} =~ m{/}; my $version; if (not defined $param{version_cache} or not exists $param{version_cache}{join(',',sort keys %sources)}) { $version = Debbugs::Versions->new(\&Debbugs::Versions::Dpkg::vercmp); foreach my $source (keys %sources) { my $srchash = substr $source, 0, 1; - my $version_fh = IO::File->new("$config{version_packages_dir}/$srchash/$source", 'r') or - warn "Unable to open $config{version_packages_dir}/$srchash/$source: $!" and next; + 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}; + warn "Bug $param{bug}: unable to open $config{version_packages_dir}/$srchash/$source: $!"; + next; + } $version->load($version_fh); } if (defined $param{version_cache}) { @@ -1174,7 +1248,7 @@ sub update_realtime { sub bughook_archive { my @refs = @_; - &filelock("debbugs.trace.lock"); + &filelock("$config{spool_dir}/debbugs.trace.lock"); &appendfile("debbugs.trace","archive ".join(',',@refs)."\n"); my %bugs = update_realtime("$config{spool_dir}/index.db.realtime", map{($_,'REMOVE')} @refs); @@ -1185,7 +1259,7 @@ sub bughook_archive { sub bughook { my ( $type, %bugs_temp ) = @_; - &filelock("debbugs.trace.lock"); + &filelock("$config{spool_dir}/debbugs.trace.lock"); my %bugs; for my $bug (keys %bugs_temp) {