]> git.donarmstrong.com Git - debbugs.git/blobdiff - Debbugs/Control.pm
* use 1foo instead of foo to avoid "version must start with number" error
[debbugs.git] / Debbugs / Control.pm
index 3d94feea60b39bb29f1cc50b6186790b9674d08f..4ec2a101ae878272f90646d489acbfeb5e7ecd15 100644 (file)
@@ -106,8 +106,8 @@ BEGIN{
 }
 
 use Debbugs::Config qw(:config);
-use Debbugs::Common qw(:lock buglog :misc get_hashname);
-use Debbugs::Status qw(bug_archiveable :read :hook writebug splitpackages split_status_fields);
+use Debbugs::Common qw(:lock buglog :misc get_hashname sort_versions);
+use Debbugs::Status qw(bug_archiveable :read :hook writebug splitpackages split_status_fields get_bug_status);
 use Debbugs::CGI qw(html_escape);
 use Debbugs::Log qw(:misc);
 use Debbugs::Recipients qw(:add);
@@ -319,10 +319,10 @@ sub set_blocks {
            join(', ',grep {$_ !~ /^\d+$/} make_list($param{block}));
     }
     my $mode = 'set';
-    if (exists $param{add}) {
+    if ($param{add}) {
        $mode = 'add';
     }
-    elsif (exists $param{remove}) {
+    elsif ($param{remove}) {
        $mode = 'remove';
     }
 
@@ -351,7 +351,7 @@ sub set_blocks {
            $ok_blockers{$blocker} = 1;
            my @merged_bugs;
            push @merged_bugs, make_list($data->{mergedwith});
-           $ok_blockers{@merged_bugs} = (1) x @merged_bugs if @merged_bugs;
+           @ok_blockers{@merged_bugs} = (1) x @merged_bugs if @merged_bugs;
        }
        else {
            $bad_blockers{$blocker} = 1;
@@ -436,11 +436,11 @@ sub set_blocks {
            print {$transcript} "Was blocked by: $data->{blockedby}\n";
        }
        my @changed;
-       push @changed, 'added blocking bug(s) '.english_join([keys %added_blockers]) if keys %added_blockers;
-       push @changed, 'removed blocking bug(s) '.english_join([keys %removed_blockers]) if keys %removed_blockers;
+       push @changed, 'added blocking bug(s) of '.$data->{bug_num}.': '.english_join([keys %added_blockers]) if keys %added_blockers;
+       push @changed, 'removed blocking bug(s) of '.$data->{bug_num}.': '.english_join([keys %removed_blockers]) if keys %removed_blockers;
        $action = ucfirst(join ('; ',@changed)) if @changed;
        if (not @changed) {
-           print {$transcript} "Ignoring request to alter tags of bug #$data->{bug_num} to the same tags previously set\n"
+           print {$transcript} "Ignoring request to alter blocking bugs of bug #$data->{bug_num} to the same blocks previously set\n"
                unless __internal_request();
            next;
        }
@@ -482,8 +482,9 @@ sub set_blocks {
            for my $data (@blocking_data) {
                my $old_data = dclone($data);
                my %blocks;
-               %blocks = split ' ', $data->{blocks};
-               my @blocks;
+               my @blocks = split ' ', $data->{blocks};
+               @blocks{@blocks} = (1) x @blocks;
+               @blocks = ();
                for my $bug (@bugs) {
                    if ($add_remove eq 'remove') {
                        next unless exists $blocks{$bug};
@@ -497,7 +498,7 @@ sub set_blocks {
                }
                $data->{blocks} = join(' ',sort keys %blocks);
                my $action = ($add_remove eq 'add'?'Added':'Removed').
-                   " indication that bug $data->{bug_num} blocks".
+                   " indication that bug $data->{bug_num} blocks ".
                    join(',',@blocks);
                append_action_to_log(bug => $data->{bug_num},
                                     command => 'block',
@@ -508,6 +509,7 @@ sub set_blocks {
                                                                   action => $action
                                                                   )
                                    );
+               writebug($data->{bug_num},$data);
            }
            __handle_affected_packages(%param,data=>\@blocking_data);
            add_recipients(recipients => $param{recipients},
@@ -615,7 +617,7 @@ sub set_tag {
        my %tag_added = ();
        my %tag_removed = ();
        my %fixed_removed = ();
-       my @old_tags = split /\,\s*/, $data->{keywords};
+       my @old_tags = split /\,?\s+/, $data->{keywords};
        my %tags;
        @tags{@old_tags} = (1) x @old_tags;
        my $reopened = 0;
@@ -657,7 +659,7 @@ sub set_tag {
            print {$transcript} "Unknown tag(s): ".join(', ',@bad_tags).".\n";
            print {$transcript} "These tags are recognized: ".join(', ',@{$config{tags}}).".\n";
        }
-       $data->{keywords} = join(', ',keys %tags); # double check this
+       $data->{keywords} = join(' ',keys %tags);
 
        my @changed;
        push @changed, 'added tag(s) '.english_join([keys %tag_added]) if keys %tag_added;
@@ -1420,11 +1422,11 @@ sub set_found {
                # We only care about reopening the bug if the bug is
                # not done
                if (defined $data->{done} and length $data->{done}) {
-                   my @svers_order = sort {Debbugs::Versions::Dpkg::vercmp($a,$b);}
-                       map {m{([^/]+)$}; $1;} @svers;
+                   my @svers_order = sort_versions(map {m{([^/]+)$}; $1;}
+                                                   @svers);
                    # determine if we need to reopen
-                   my @fixed_order = sort {Debbugs::Versions::Dpkg::vercmp($a,$b);}
-                       map {m{([^/]+)$}; $1;} keys %fixed_versions;
+                   my @fixed_order = sort_versions(map {m{([^/]+)$}; $1;}
+                                                   keys %fixed_versions);
                    if (not @fixed_order or
                        (Debbugs::Versions::Dpkg::vercmp($svers_order[-1],$fixed_order[-1]) >= 0)) {
                        $reopened = 1;
@@ -1947,12 +1949,14 @@ sub summary {
              }
              # skip a paragraph if it looks like it's control or
              # pseudo-headers
-             if ($line =~ m{^\s*(?:(?:Package|Source|Version)\:| #pseudo headers
-                                (?:package|(?:no|)owner|severity|tag|summary| #control
-                                     reopen|close|(?:not|)(?:fixed|found)|clone|
-                                     (?:force|)merge|user(?:category|tag|)
-                                )
-                           )\s+\S}x) {
+             if ($line =~ m{^\s*(?:Package|Source|Version|User|Tag|Severity)\:\s+\S}xi or #pseudo headers
+                 $line =~ m{^(?:package:?|(?:no|)owner|severity|tags?|summary| #control
+                                \#|reopen|close|(?:not|)(?:fixed|found)|clone|
+                                debug|(?:not|)forwarded|priority|
+                                (?:un|)block|limit|(?:un|)archive|
+                                reassign|retitle|affects|wrongpackage
+                                (?:un|force|)merge|user(?:category|tags?|)
+                            )\s+\S}xis) {
                   if (not length $paragraph) {
                        print {$debug} "Found control/pseudo-headers and skiping them\n";
                        $in_pseudoheaders = 1;
@@ -2585,7 +2589,7 @@ C<__PACKAGE__>.
 sub __internal_request{
     my ($l) = @_;
     $l = 0 if not defined $l;
-    if (defined +(caller(2+$l))[0] and +(caller(2+$l))[0] eq __PACKAGE__) {
+    if (defined((caller(1+$l))[0]) and (caller(1+$l))[0] eq __PACKAGE__) {
        return 1;
     }
     return 0;
@@ -2684,8 +2688,16 @@ sub __begin_control {
     if (not @data) {
        die "Unable to read any bugs successfully.";
     }
+    if (not $param{archived}) {
+       for my $data (@data) {
+           if ($data->{archived}) {
+               die "Not altering archived bugs; see unarchive.";
+           }
+       }
+    }
     if (not __check_limit(data => \@data,
                          exists $param{limit}?(limit => $param{limit}):(),
+                         transcript => $transcript,
                         )) {
        die "limit failed for bugs: ".join(', ',map {$_->{bug_num}} @data);
     }
@@ -2702,7 +2714,7 @@ sub __begin_control {
                   recipients => $param{recipients},
                   (exists $param{command}?(actions_taken => {$param{command} => 1}):()),
                   debug      => $debug,
-                  transcript => $transcript,
+                  (__internal_request()?(transcript => $transcript):()),
                  );
 
     print {$debug} "$param{bug} read done\n";
@@ -2773,6 +2785,9 @@ sub __check_limit{
                                                  },
                                         limit => {type => HASHREF|UNDEF,
                                                  },
+                                        transcript  => {type => SCALARREF|HANDLE,
+                                                        optional => 1,
+                                                       },
                                        },
                             );
     my @data = make_list($param{data});
@@ -2781,21 +2796,31 @@ sub __check_limit{
        not keys %{$param{limit}}) {
        return 1;
     }
+    my $transcript = globify_scalar(exists $param{transcript}?$param{transcript}:undef);
+    my $going_to_fail = 0;
     for my $data (@data) {
+       $data = split_status_fields(get_bug_status(bug => $data->{bug_num},
+                                                  status => dclone($data),
+                                                 ));
        for my $field (keys %{$param{limit}}) {
            next unless exists $param{limit}{$field};
            my $match = 0;
-           for my $limit (make_list($param{limit}{$field})) {
+           my @data_fields = make_list($data->{$field});
+LIMIT:     for my $limit (make_list($param{limit}{$field})) {
                if (not ref $limit) {
-                   if ($data->{$field} eq $limit) {
-                       $match = 1;
-                       last;
+                   for my $data_field (@data_fields) {
+                       if ($data_field eq $limit) {
+                           $match = 1;
+                           last LIMIT;
+                       }
                    }
                }
                elsif (ref($limit) eq 'Regexp') {
-                   if ($data->{$field} =~ $limit) {
-                       $match = 1;
-                       last;
+                   for my $data_field (@data_fields) {
+                       if ($data_field =~ $limit) {
+                           $match = 1;
+                           last LIMIT;
+                       }
                    }
                }
                else {
@@ -2803,11 +2828,14 @@ sub __check_limit{
                }
            }
            if (not $match) {
-               return 0;
+               $going_to_fail = 1;
+               print {$transcript} qq($field: ).join(', ',map{qq("$_")} make_list($data->{$field})).
+                   "' does not match at least one of ".
+                   join(', ',map {ref($_)?'(regex)':qq("$_")} make_list($param{limit}{$field}))."\n";
            }
        }
     }
-    return 1;
+    return $going_to_fail?0:1;
 }