]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 396558: Dependency change e-mails should only include status changes that happene...
authorFrédéric Buclin <LpSolit@gmail.com>
Wed, 28 Jul 2010 17:02:32 +0000 (19:02 +0200)
committerFrédéric Buclin <LpSolit@gmail.com>
Wed, 28 Jul 2010 17:02:32 +0000 (19:02 +0200)
r/a=mkanat

Bugzilla/Bug.pm
Bugzilla/BugMail.pm
Bugzilla/User.pm
template/en/default/email/newchangedmail.txt.tmpl

index fce2a1634ca1a6a5c98edc6517961a76b764b72c..6638573c6a3f0a4a1b1b90693df33f4f254a894a 100644 (file)
@@ -1154,14 +1154,22 @@ sub send_changes {
 
     # If there were changes in dependencies, we need to notify those
     # dependencies.
-    my %notify_deps;
     if ($changes->{'bug_status'}) {
         my ($old_status, $new_status) = @{ $changes->{'bug_status'} };
 
         # If this bug has changed from opened to closed or vice-versa,
         # then all of the bugs we block need to be notified.
         if (is_open_state($old_status) ne is_open_state($new_status)) {
-            $notify_deps{$_} = 1 foreach (@{ $self->blocked });
+            my $params = { forced   => { changer => $user },
+                           type     => 'dep',
+                           dep_only => 1,
+                           blocker  => $self,
+                           changes  => $changes };
+
+            foreach my $id (@{ $self->blocked }) {
+                $params->{id} = $id;
+                _send_bugmail($params, $vars);
+            }
         }
     }
 
@@ -1177,8 +1185,7 @@ sub send_changes {
     # an error later.
     delete $changed_deps{''};
 
-    my %all_dep_changes = (%notify_deps, %changed_deps);
-    foreach my $id (sort { $a <=> $b } (keys %all_dep_changes)) {
+    foreach my $id (sort { $a <=> $b } (keys %changed_deps)) {
         _send_bugmail({ forced => { changer => $user }, type => "dep",
                          id => $id }, $vars);
     }
@@ -1188,7 +1195,7 @@ sub _send_bugmail {
     my ($params, $vars) = @_;
 
     my $results = 
-        Bugzilla::BugMail::Send($params->{'id'}, $params->{'forced'});
+        Bugzilla::BugMail::Send($params->{'id'}, $params->{'forced'}, $params);
 
     if (Bugzilla->usage_mode == USAGE_MODE_BROWSER) {
         my $template = Bugzilla->template;
index b2482858a8cc65b7637e2f140d205d9de88957de..3e97b4457bbd4d2257a4fdfd8e25144855d4d4f8 100644 (file)
@@ -109,14 +109,12 @@ sub relationships {
 # All the names are email addresses, not userids
 # values are scalars, except for cc, which is a list
 sub Send {
-    my ($id, $forced) = (@_);
+    my ($id, $forced, $params) = @_;
+    $params ||= {};
 
     my $dbh = Bugzilla->dbh;
     my $bug = new Bugzilla::Bug($id);
 
-    # Only used for headers in bugmail for new bugs
-    my @fields = Bugzilla->get_fields({obsolete => 0, mailhead => 1});
-
     my $start = $bug->lastdiffed;
     my $end   = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
 
@@ -146,142 +144,21 @@ sub Send {
         }
     }
     
-    my @args = ($bug->id);
-
-    # If lastdiffed is NULL, then we don't limit the search on time.
-    my $when_restriction = '';
-    if ($start) {
-        $when_restriction = ' AND bug_when > ? AND bug_when <= ?';
-        push @args, ($start, $end);
-    }
-    
-    my $diffs = $dbh->selectall_arrayref(
-           "SELECT profiles.login_name, profiles.realname, fielddefs.description,
-                   bugs_activity.bug_when, bugs_activity.removed, 
-                   bugs_activity.added, bugs_activity.attach_id, fielddefs.name,
-                   bugs_activity.comment_id
-              FROM bugs_activity
-        INNER JOIN fielddefs
-                ON fielddefs.id = bugs_activity.fieldid
-        INNER JOIN profiles
-                ON profiles.userid = bugs_activity.who
-             WHERE bugs_activity.bug_id = ?
-                   $when_restriction
-          ORDER BY bugs_activity.bug_when", undef, @args);
-
-    my @new_depbugs;
-    my $difftext = "";
-    my $diffheader = "";
-    my @diffparts;
-    my $lastwho = "";
-    my $fullwho;
-    my @changedfields;
-    foreach my $ref (@$diffs) {
-        my ($who, $whoname, $what, $when, $old, $new, $attachid, $fieldname, $comment_id) = (@$ref);
-        my $diffpart = {};
-        if ($who ne $lastwho) {
-            $lastwho = $who;
-            $fullwho = $whoname ? "$whoname <$who>" : $who;
-            $diffheader = "\n$fullwho changed:\n\n";
-            $diffheader .= three_columns("What    ", "Removed", "Added");
-            $diffheader .= ('-' x 76) . "\n";
-        }
-        $what =~ s/^(Attachment )?/Attachment #$attachid / if $attachid;
-        if( $fieldname eq 'estimated_time' ||
-            $fieldname eq 'remaining_time' ) {
-            $old = format_time_decimal($old);
-            $new = format_time_decimal($new);
-        }
-        if ($fieldname eq 'dependson') {
-            push(@new_depbugs, grep {$_ =~ /^\d+$/} split(/[\s,]+/, $new));
-        }
-        if ($attachid) {
-            ($diffpart->{'isprivate'}) = $dbh->selectrow_array(
-                'SELECT isprivate FROM attachments WHERE attach_id = ?',
-                undef, ($attachid));
-        }
-        if ($fieldname eq 'longdescs.isprivate') {
-            my $comment = Bugzilla::Comment->new($comment_id);
-            my $comment_num = $comment->count;
-            $what =~ s/^(Comment )?/Comment #$comment_num /;
-            $diffpart->{'isprivate'} = $new;
-        }
-        $difftext = three_columns($what, $old, $new);
-        $diffpart->{'header'} = $diffheader;
-        $diffpart->{'fieldname'} = $fieldname;
-        $diffpart->{'text'} = $difftext;
-        push(@diffparts, $diffpart);
-        push(@changedfields, $what);
-    }
-
-    my @depbugs;
-    my $deptext = "";
-    # Do not include data about dependent bugs when they have just been added.
-    # Completely skip checking for dependent bugs on bug creation as all
-    # dependencies bugs will just have been added.
-    if ($start) {
-        my $dep_restriction = "";
-        if (scalar @new_depbugs) {
-            $dep_restriction = "AND bugs_activity.bug_id NOT IN (" .
-                               join(", ", @new_depbugs) . ")";
-        }
-
-        my $dependency_diffs = $dbh->selectall_arrayref(
-           "SELECT bugs_activity.bug_id, bugs.short_desc, fielddefs.name, 
-                   fielddefs.description, bugs_activity.removed,
-                   bugs_activity.added
-              FROM bugs_activity
-        INNER JOIN bugs
-                ON bugs.bug_id = bugs_activity.bug_id
-        INNER JOIN dependencies
-                ON bugs_activity.bug_id = dependencies.dependson
-        INNER JOIN fielddefs
-                ON fielddefs.id = bugs_activity.fieldid
-             WHERE dependencies.blocked = ?
-               AND (fielddefs.name = 'bug_status'
-                    OR fielddefs.name = 'resolution')
-                   $when_restriction
-                   $dep_restriction
-          ORDER BY bugs_activity.bug_when, bugs.bug_id", undef, @args);
-
-        my $thisdiff = "";
-        my $lastbug = "";
-        my $interestingchange = 0;
-        foreach my $dependency_diff (@$dependency_diffs) {
-            my ($depbug, $summary, $fieldname, $what, $old, $new) = @$dependency_diff;
-
-            if ($depbug ne $lastbug) {
-                if ($interestingchange) {
-                    $deptext .= $thisdiff;
-                }
-                $lastbug = $depbug;
-                $thisdiff =
-                  "\nBug $id depends on bug $depbug, which changed state.\n\n" .
-                  "Bug $depbug Summary: $summary\n" .
-                  correct_urlbase() . "show_bug.cgi?id=$depbug\n\n";
-                $thisdiff .= three_columns("What    ", "Old Value", "New Value");
-                $thisdiff .= ('-' x 76) . "\n";
-                $interestingchange = 0;
-            }
-            $thisdiff .= three_columns($what, $old, $new);
-            if ($fieldname eq 'bug_status'
-                && is_open_state($old) ne is_open_state($new))
-            {
-                $interestingchange = 1;
-            }
-            push(@depbugs, $depbug);
-        }
-
-        if ($interestingchange) {
-            $deptext .= $thisdiff;
-        }
-        $deptext = trim($deptext);
-
-        if ($deptext) {
-            my $diffpart = {};
-            $diffpart->{'text'} = "\n" . trim($deptext);
-            push(@diffparts, $diffpart);
-        }
+    my ($diffparts, $changedfields, $diffs) =
+      $params->{dep_only} ? ([], [], []) : _get_diffs($bug, $end);
+
+    if ($params->{dep_only} && $start) {
+        my $blocker_id = $params->{blocker}->id;
+        my $deptext =
+          "\nBug " . $bug->id . " depends on bug $blocker_id, which changed state.\n\n" .
+          "Bug $blocker_id Summary: " . $params->{blocker}->short_desc . "\n" .
+          correct_urlbase() . "show_bug.cgi?id=$blocker_id\n\n";
+        $deptext .= three_columns("What    ", "Old Value", "New Value");
+        $deptext .= ('-' x 76) . "\n";
+        $deptext .= three_columns('Status', @{$params->{changes}->{bug_status}});
+        $deptext .= three_columns('Resolution', @{$params->{changes}->{resolution}});
+
+        push(@$diffparts, {text => $deptext});
     }
 
     my $comments = $bug->comments({ after => $start, to => $end });
@@ -374,6 +251,9 @@ sub Send {
     my @sent;
     my @excluded;
 
+    # Only used for headers in bugmail for new bugs
+    my @fields = $start ? () : Bugzilla->get_fields({obsolete => 0, mailhead => 1});
+
     foreach my $user_id (keys %recipients) {
         my %rels_which_want;
         my $sent_mail = 0;
@@ -389,7 +269,7 @@ sub Send {
                                           $relationship, 
                                           $diffs, 
                                           $comments,
-                                          $deptext,
+                                          $params->{dep_only},
                                           $changer,
                                           !$start))
                 {
@@ -403,16 +283,12 @@ sub Send {
             # So the user exists, can see the bug, and wants mail in at least
             # one role. But do we want to send it to them?
 
-            # We shouldn't send mail if this is a dependency mail (i.e. there 
-            # is something in @depbugs), and any of the depending bugs are not 
-            # visible to the user. This is to avoid leaking the summaries of 
-            # confidential bugs.
+            # We shouldn't send mail if this is a dependency mail and the
+            # depending bug is not visible to the user.
+            # This is to avoid leaking the summary of a confidential bug.
             my $dep_ok = 1;
-            foreach my $dep_id (@depbugs) {
-                if (!$user->can_see_bug($dep_id)) {
-                   $dep_ok = 0;
-                   last;
-                }
+            if ($params->{dep_only}) {
+                $dep_ok = $user->can_see_bug($params->{blocker}->id) ? 1 : 0;
             }
 
             # Make sure the user isn't in the nomail list, and the insider and 
@@ -425,12 +301,13 @@ sub Send {
                       bug      => $bug,
                       comments => $comments,
                       is_new   => !$start,
+                      delta_ts => $params->{dep_only} ? $end : undef,
                       changer  => $changer,
                       watchers => exists $watching{$user_id} ?
                                   $watching{$user_id} : undef,
-                      diff_parts      => \@diffparts,
+                      diff_parts      => $diffparts,
                       rels_which_want => \%rels_which_want,
-                      changed_fields  => \@changedfields,
+                      changed_fields  => $changedfields,
                     });
             }
         }
@@ -442,10 +319,15 @@ sub Send {
             push(@excluded, $user->login); 
         } 
     }
-    
-    $dbh->do('UPDATE bugs SET lastdiffed = ? WHERE bug_id = ?',
-             undef, ($end, $id));
-    $bug->{lastdiffed} = $end;
+
+    # When sending bugmail about a blocker being reopened or resolved,
+    # we say nothing about changes in the bug being blocked, so we must
+    # not update lastdiffed in this case.
+    if (!$params->{dep_only}) {
+        $dbh->do('UPDATE bugs SET lastdiffed = ? WHERE bug_id = ?',
+                 undef, ($end, $id));
+        $bug->{lastdiffed} = $end;
+    }
 
     return {'sent' => \@sent, 'excluded' => \@excluded};
 }
@@ -458,6 +340,7 @@ sub sendMail {
     my $bug    = $params->{bug};
     my @send_comments = @{ $params->{comments} };
     my $isnew   = $params->{is_new};
+    my $delta_ts = $params->{delta_ts};
     my $changer = $params->{changer};
     my $watchingRef = $params->{watchers};
     my @diffparts   = @{ $params->{diff_parts} };
@@ -558,6 +441,7 @@ sub sendMail {
 
     my $vars = {
         isnew => $isnew,
+        delta_ts => $delta_ts,
         to_user => $user,
         bug => $bug,
         changedfields => \@changed_fields,
@@ -581,4 +465,74 @@ sub sendMail {
     return 1;
 }
 
+sub _get_diffs {
+    my ($bug, $end) = @_;
+    my $dbh = Bugzilla->dbh;
+
+    my @args = ($bug->id);
+    # If lastdiffed is NULL, then we don't limit the search on time.
+    my $when_restriction = '';
+    if ($bug->lastdiffed) {
+        $when_restriction = ' AND bug_when > ? AND bug_when <= ?';
+        push @args, ($bug->lastdiffed, $end);
+    }
+
+    my $diffs = $dbh->selectall_arrayref(
+           "SELECT profiles.login_name, profiles.realname, fielddefs.description,
+                   bugs_activity.bug_when, bugs_activity.removed,
+                   bugs_activity.added, bugs_activity.attach_id, fielddefs.name,
+                   bugs_activity.comment_id
+              FROM bugs_activity
+        INNER JOIN fielddefs
+                ON fielddefs.id = bugs_activity.fieldid
+        INNER JOIN profiles
+                ON profiles.userid = bugs_activity.who
+             WHERE bugs_activity.bug_id = ?
+                   $when_restriction
+          ORDER BY bugs_activity.bug_when", undef, @args);
+
+    my $difftext = "";
+    my $diffheader = "";
+    my @diffparts;
+    my $lastwho = "";
+    my $fullwho;
+    my @changedfields;
+    foreach my $ref (@$diffs) {
+        my ($who, $whoname, $what, $when, $old, $new, $attachid, $fieldname, $comment_id) = @$ref;
+        my $diffpart = {};
+        if ($who ne $lastwho) {
+            $lastwho = $who;
+            $fullwho = $whoname ? "$whoname <$who>" : $who;
+            $diffheader = "\n$fullwho changed:\n\n";
+            $diffheader .= three_columns("What    ", "Removed", "Added");
+            $diffheader .= ('-' x 76) . "\n";
+        }
+        $what =~ s/^(Attachment )?/Attachment #$attachid / if $attachid;
+        if( $fieldname eq 'estimated_time' ||
+            $fieldname eq 'remaining_time' ) {
+            $old = format_time_decimal($old);
+            $new = format_time_decimal($new);
+        }
+        if ($attachid) {
+            ($diffpart->{'isprivate'}) = $dbh->selectrow_array(
+                'SELECT isprivate FROM attachments WHERE attach_id = ?',
+                undef, ($attachid));
+        }
+        if ($fieldname eq 'longdescs.isprivate') {
+            my $comment = Bugzilla::Comment->new($comment_id);
+            my $comment_num = $comment->count;
+            $what =~ s/^(Comment )?/Comment #$comment_num /;
+            $diffpart->{'isprivate'} = $new;
+        }
+        $difftext = three_columns($what, $old, $new);
+        $diffpart->{'header'} = $diffheader;
+        $diffpart->{'fieldname'} = $fieldname;
+        $diffpart->{'text'} = $difftext;
+        push(@diffparts, $diffpart);
+        push(@changedfields, $what);
+    }
+
+    return (\@diffparts, \@changedfields, $diffs);
+}
+
 1;
index 09af233ecf2ba069f821480c8f8154701da6e2bd..2bbe6310187b38d6ea3f8b16882fc70b2d5c0660 100644 (file)
@@ -1513,7 +1513,7 @@ our %names_to_events = (
 # Note: the "+" signs before the constants suppress bareword quoting.
 sub wants_bug_mail {
     my $self = shift;
-    my ($bug_id, $relationship, $fieldDiffs, $comments, $dependencyText,
+    my ($bug_id, $relationship, $fieldDiffs, $comments, $dep_mail,
         $changer, $bug_is_new) = @_;
 
     # Make a list of the events which have happened during this bug change,
@@ -1572,7 +1572,7 @@ sub wants_bug_mail {
     
     # Dependent changed bugmails must have an event to ensure the bugmail is
     # emailed.
-    if ($dependencyText ne '') {
+    if ($dep_mail) {
         $events{+EVT_DEPEND_BLOCK} = 1;
     }
 
index 5a6e90ae11e3e2be3d84ee98bcc0a05cc0934f91..90dba211f670c1d95ccbd099782d9a4b3e1cdf12 100644 (file)
@@ -24,7 +24,7 @@
 From: [% Param('mailfrom') %]
 To: [% to_user.email %]
 Subject: [[% terms.Bug %] [%+ bug.id %]] [% 'New: ' IF isnew %][%+ bug.short_desc %]
-Date: [% bug.delta_ts FILTER time("%a, %d %b %Y %T %z", to_user.timezone) %]
+Date: [% delta_ts || bug.delta_ts FILTER time("%a, %d %b %Y %T %z", to_user.timezone) %]
 X-Bugzilla-Reason: [% reasonsheader %]
 X-Bugzilla-Type: [% isnew ? 'new' : 'changed' %]
 X-Bugzilla-Watch-Reason: [% reasonswatchheader %]