]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 312197: Templatize sanitycheck.cgi - Patch by Frédéric Buclin <LpSolit@gmail...
authorlpsolit%gmail.com <>
Tue, 6 Mar 2007 00:33:37 +0000 (00:33 +0000)
committerlpsolit%gmail.com <>
Tue, 6 Mar 2007 00:33:37 +0000 (00:33 +0000)
Bugzilla/Template.pm
sanitycheck.cgi
skins/standard/admin.css
template/en/default/admin/sanitycheck/list.html.tmpl [new file with mode: 0644]
template/en/default/admin/sanitycheck/messages.html.tmpl [new file with mode: 0644]
template/en/default/global/messages.html.tmpl

index 800536cd513bcad60112aeaf2fa6882c8a12fade..42c45823e57d23a37a43d57b5d6d8a7fafe4c5a9 100644 (file)
@@ -187,22 +187,6 @@ sub getTemplateIncludePath {
     return Bugzilla->request_cache->{"template_include_path_$lang"};
 }
 
-sub put_header {
-    my $self = shift;
-    my $vars = {};
-    ($vars->{'title'}, $vars->{'h1'}, $vars->{'h2'}) = (@_);
-     
-    $self->process("global/header.html.tmpl", $vars)
-      || ThrowTemplateError($self->error());
-    $vars->{'header_done'} = 1;
-}
-
-sub put_footer {
-    my $self = shift;
-    $self->process("global/footer.html.tmpl")
-      || ThrowTemplateError($self->error());
-}
-
 sub get_format {
     my $self = shift;
     my ($template, $format, $ctype) = @_;
@@ -924,10 +908,6 @@ Bugzilla::Template - Wrapper around the Template Toolkit C<Template> object
 =head1 SYNOPSIS
 
   my $template = Bugzilla::Template->create;
-
-  $template->put_header($title, $h1, $h2);
-  $template->put_footer();
-
   my $format = $template->get_format("foo/bar",
                                      scalar($cgi->param('format')),
                                      scalar($cgi->param('ctype')));
@@ -960,24 +940,6 @@ Returns:     nothing
 
 =over
 
-=item C<put_header($title, $h1, $h2)>
-
- Description: Display the header of the page for non yet templatized .cgi files.
-
- Params:      $title - Page title.
-              $h1    - Main page header.
-              $h2    - Page subheader.
-
- Returns:     nothing
-
-=item C<put_footer()>
-
- Description: Display the footer of the page for non yet templatized .cgi files.
-
- Params:      none
-
- Returns:     nothing
-
 =item C<get_format($file, $format, $ctype)>
 
  Description: Construct a format object from URL parameters.
index bf8ba1980b0200e269f76949dcb179c2d53f4d9f..873432fb9ace048f50086be615f5ba5d93d6e181 100755 (executable)
@@ -32,77 +32,57 @@ use Bugzilla;
 use Bugzilla::Constants;
 use Bugzilla::Util;
 use Bugzilla::Error;
-use Bugzilla::User;
 
 ###########################################################################
 # General subs
 ###########################################################################
 
-sub Status {
-    my ($str) = (@_);
-    print "$str <p>\n";
-}
-
-sub Alert {
-    my ($str) = (@_);
-    Status("<font color=\"red\">$str</font>");
+sub get_string {
+    my ($san_tag, $vars) = @_;
+    $vars->{'san_tag'} = $san_tag;
+    return get_text('sanitycheck', $vars);
 }
 
-sub BugLink {
-    my ($id) = (@_);
-    return "<a href=\"show_bug.cgi?id=$id\">$id</a>";
-}
-
-#
-# Parameter is a list of bug ids.
-#
-# Return is a string containing a list of all the bugids, as hrefs,
-# followed by a link to them all as a buglist
-sub BugListLinks {
-    my @bugs = @_;
-
-    # Historically, GetBugLink() wasn't used here. I'm guessing this
-    # was because it didn't exist or is too performance heavy, or just
-    # plain unnecessary
-    my @bug_links = map(BugLink($_), @bugs);
-
-    return join(', ',@bug_links) . " <a href=\"buglist.cgi?bug_id=" .
-        join(',',@bugs) . "\">(as buglist)</a>";
+sub Status {
+    my ($san_tag, $vars, $alert) = @_;
+    my $start_tag = $alert ? '<p class="alert">' : '<p>';
+    print $start_tag . get_string($san_tag, $vars) . "</p>\n";
 }
 
 ###########################################################################
 # Start
 ###########################################################################
 
-Bugzilla->login(LOGIN_REQUIRED);
+my $user = Bugzilla->login(LOGIN_REQUIRED);
 
 my $cgi = Bugzilla->cgi;
 my $dbh = Bugzilla->dbh;
 my $template = Bugzilla->template;
-my $user = Bugzilla->user;
+my $vars = {};
+
+print $cgi->header();
 
 # Make sure the user is authorized to access sanitycheck.cgi.
 # As this script can now alter the group_control_map table, we no longer
 # let users with editbugs privs run it anymore.
 $user->in_group("editcomponents")
-  || ($user->in_group('editkeywords') && defined $cgi->param('rebuildkeywordcache'))
+  || ($user->in_group('editkeywords') && $cgi->param('rebuildkeywordcache'))
   || ThrowUserError("auth_failure", {group  => "editcomponents",
                                      action => "run",
                                      object => "sanity_check"});
 
-print $cgi->header();
-
-my @row;
-
-$template->put_header("Sanity Check");
+$template->process('admin/sanitycheck/list.html.tmpl', $vars)
+  || ThrowTemplateError($template->error());
 
 ###########################################################################
 # Users with 'editkeywords' privs only can only check keywords.
 ###########################################################################
 unless ($user->in_group('editcomponents')) {
     check_votes_or_keywords('keywords');
-    Status("Sanity check completed.");
-    $template->put_footer();
+    Status('checks_completed');
+
+    $template->process('global/footer.html.tmpl', $vars)
+        || ThrowTemplateError($template->error());
     exit;
 }
 
@@ -110,8 +90,8 @@ unless ($user->in_group('editcomponents')) {
 # Fix vote cache
 ###########################################################################
 
-if (defined $cgi->param('rebuildvotecache')) {
-    Status("OK, now rebuilding vote cache.");
+if ($cgi->param('rebuildvotecache')) {
+    Status('vote_cache_rebuild_start');
     $dbh->bz_lock_tables('bugs WRITE', 'votes READ');
     $dbh->do(q{UPDATE bugs SET votes = 0});
     my $sth_update = $dbh->prepare(q{UPDATE bugs 
@@ -124,16 +104,15 @@ if (defined $cgi->param('rebuildvotecache')) {
         $sth_update->execute($v, $id);
     }
     $dbh->bz_unlock_tables();
-    Status("Vote cache has been rebuilt.");
+    Status('vote_cache_rebuild_end');
 }
 
 ###########################################################################
 # Create missing group_control_map entries
 ###########################################################################
 
-if (defined $cgi->param('createmissinggroupcontrolmapentries')) {
-    Status(qq{OK, now creating <code>SHOWN</code> member control entries
-              for product/group combinations lacking one.});
+if ($cgi->param('createmissinggroupcontrolmapentries')) {
+    Status('group_control_map_entries_creation');
 
     my $na    = CONTROLMAPNA;
     my $shown = CONTROLMAPSHOWN;
@@ -180,29 +159,26 @@ if (defined $cgi->param('createmissinggroupcontrolmapentries')) {
 
         $counter++;
         if (defined($currentmembercontrol)) {
-            Status(qq{Updating <code>NA/<em>xxx</em></code> group control
-                      setting for group <em>$group_name</em> to
-                      <code>SHOWN/<em>xxx</em></code> in product
-                      <em>$product_name</em>.});
+            Status('group_control_map_entries_update',
+                   {group_name => $group_name, product_name => $product_name});
             $updatesth->execute($group_id, $product_id);
         }
         else {
-            Status(qq{Generating <code>SHOWN/NA</code> group control setting
-                      for group <em>$group_name</em> in product
-                      <em>$product_name</em>.});
+            Status('group_control_map_entries_generation',
+                   {group_name => $group_name, product_name => $product_name});
             $insertsth->execute($group_id, $product_id);
         }
     }
 
-    Status("Repaired $counter defective group control settings.");
+    Status('group_control_map_entries_repaired', {counter => $counter});
 }
 
 ###########################################################################
 # Fix missing creation date
 ###########################################################################
 
-if (defined $cgi->param('repair_creation_date')) {
-    Status("OK, now fixing missing bug creation dates");
+if ($cgi->param('repair_creation_date')) {
+    Status('bug_creation_date_start');
 
     my $bug_ids = $dbh->selectcol_arrayref('SELECT bug_id FROM bugs
                                             WHERE creation_ts IS NULL');
@@ -220,19 +196,19 @@ if (defined $cgi->param('repair_creation_date')) {
         my $date = $sth_getDate->fetchrow_array;
         $sth_UpdateDate->execute($date, $bugid);
     }
-    Status(scalar(@$bug_ids) . " bugs have been fixed.");
+    Status('bug_creation_date_fixed', {bug_count => scalar(@$bug_ids)});
 }
 
 ###########################################################################
 # Send unsent mail
 ###########################################################################
 
-if (defined $cgi->param('rescanallBugMail')) {
+if ($cgi->param('rescanallBugMail')) {
     require Bugzilla::BugMail;
 
-    Status("OK, now attempting to send unsent mail");
+    Status('send_bugmail_start');
     my $time = $dbh->sql_interval(30, 'MINUTE');
-    
+
     my $list = $dbh->selectcol_arrayref(qq{
                                         SELECT bug_id
                                           FROM bugs 
@@ -240,10 +216,9 @@ if (defined $cgi->param('rescanallBugMail')) {
                                                 OR lastdiffed < delta_ts)
                                            AND delta_ts < now() - $time
                                       ORDER BY bug_id});
-         
-    Status(scalar(@$list) . ' bugs found with possibly unsent mail.');
 
-    my $vars = {};
+    Status('send_bugmail_status', {bug_count => scalar(@$list)});
+
     # We cannot simply look at the bugs_activity table to find who did the
     # last change in a given bug, as e.g. adding a comment doesn't add any
     # entry to this table. And some other changes may be private
@@ -257,11 +232,10 @@ if (defined $cgi->param('rescanallBugMail')) {
         Bugzilla::BugMail::Send($bugid, $vars);
     }
 
-    if (scalar(@$list) > 0) {
-        Status("Unsent mail has been sent.");
-    }
+    Status('send_bugmail_end') if scalar(@$list);
 
-    $template->put_footer();
+    $template->process('global/footer.html.tmpl', $vars)
+        || ThrowTemplateError($template->error());
     exit;
 }
 
@@ -269,8 +243,8 @@ if (defined $cgi->param('rescanallBugMail')) {
 # Remove all references to deleted bugs
 ###########################################################################
 
-if (defined $cgi->param('remove_invalid_bug_references')) {
-    Status("OK, now removing all references to deleted bugs.");
+if ($cgi->param('remove_invalid_bug_references')) {
+    Status('bug_reference_deletion_start');
 
     $dbh->bz_lock_tables('attachments WRITE', 'bug_group_map WRITE',
                          'bugs_activity WRITE', 'cc WRITE',
@@ -297,15 +271,15 @@ if (defined $cgi->param('remove_invalid_bug_references')) {
     }
 
     $dbh->bz_unlock_tables();
-    Status("All references to deleted bugs have been removed.");
+    Status('bug_reference_deletion_end');
 }
 
 ###########################################################################
 # Remove all references to deleted attachments
 ###########################################################################
 
-if (defined $cgi->param('remove_invalid_attach_references')) {
-    Status("OK, now removing all references to deleted attachments.");
+if ($cgi->param('remove_invalid_attach_references')) {
+    Status('attachment_reference_deletion_start');
 
     $dbh->bz_lock_tables('attachments WRITE', 'attach_data WRITE');
 
@@ -322,10 +296,10 @@ if (defined $cgi->param('remove_invalid_attach_references')) {
     }
 
     $dbh->bz_unlock_tables();
-    Status("All references to deleted attachments have been removed.");
+    Status('attachment_reference_deletion_end');
 }
 
-print "OK, now running sanity checks.<p>\n";
+Status('checks_start');
 
 ###########################################################################
 # Perform referential (cross) checks
@@ -354,7 +328,7 @@ sub CrossCheck {
     my $field = shift @_;
     my $dbh = Bugzilla->dbh;
 
-    Status("Checking references to $table.$field");
+    Status('cross_check_to', {table => $table, field => $field});
 
     while (@_) {
         my $ref = shift @_;
@@ -363,8 +337,8 @@ sub CrossCheck {
         $exceptions ||= [];
         my %exceptions = map { $_ => 1 } @$exceptions;
 
-        Status("... from $refertable.$referfield");
-       
+        Status('cross_check_from', {table => $refertable, field => $referfield});
+
         my $query = qq{SELECT DISTINCT $refertable.$referfield} .
             ($keyname ? qq{, $refertable.$keyname } : q{}) .
                      qq{ FROM $refertable
@@ -372,7 +346,7 @@ sub CrossCheck {
                            ON $refertable.$referfield = $table.$field
                         WHERE $table.$field IS NULL
                           AND $refertable.$referfield IS NOT NULL};
-         
+
         my $sth = $dbh->prepare($query);
         $sth->execute;
 
@@ -380,26 +354,18 @@ sub CrossCheck {
 
         while (my ($value, $key) = $sth->fetchrow_array) {
             next if $exceptions{$value};
-            my $alert = "Bad value &quot;$value&quot; found in $refertable.$referfield";
-            if ($keyname) {
-                if ($keyname eq 'bug_id') {
-                    $alert .= ' (bug ' . BugLink($key) . ')';
-                } else {
-                    $alert .= " ($keyname == '$key')";
-                }
-            }
-            Alert($alert);
+            Status('cross_check_alert', {value => $value, table => $refertable,
+                                         field => $referfield, keyname => $keyname,
+                                         key => $key}, 'alert');
             $has_bad_references = 1;
         }
         # References to non existent bugs can be safely removed, bug 288461
         if ($table eq 'bugs' && $has_bad_references) {
-            print qq{<a href="sanitycheck.cgi?remove_invalid_bug_references=1">
-                     Remove invalid references to non existent bugs.</a><p>\n};
+            Status('cross_check_bug_has_references');
         }
         # References to non existent attachments can be safely removed.
         if ($table eq 'attachments' && $has_bad_references) {
-            print qq{<a href="sanitycheck.cgi?remove_invalid_attach_references=1">
-                     Remove invalid references to non existent attachments.</a><p>\n};
+            Status('cross_check_attachment_has_references');
         }
     }
 }
@@ -537,14 +503,16 @@ sub DoubleCrossCheck {
     my $field1 = shift @_;
     my $field2 = shift @_;
     my $dbh = Bugzilla->dbh;
-    Status("Checking references to $table.$field1 / $table.$field2");
+
+    Status('double_cross_check_to',
+           {table => $table, field1 => $field1, field2 => $field2});
+
     while (@_) {
         my $ref = shift @_;
         my ($refertable, $referfield1, $referfield2, $keyname) = @$ref;
-        Status("... from $refertable.$referfield1 / $refertable.$referfield2");
+
+        Status('double_cross_check_from',
+               {table => $refertable, field1 => $referfield1, field2 =>$referfield2});
 
         my $d_cross_check = $dbh->selectall_arrayref(qq{
                         SELECT DISTINCT $refertable.$referfield1, 
@@ -561,17 +529,11 @@ sub DoubleCrossCheck {
 
         foreach my $check (@$d_cross_check) {
             my ($value1, $value2, $key) = @$check;
-            my $alert = "Bad values &quot;$value1&quot;, &quot;$value2&quot; found in " .
-                "$refertable.$referfield1 / $refertable.$referfield2";
-            if ($keyname) {
-                if ($keyname eq 'bug_id') {
-                   $alert .= ' (bug ' . BugLink($key) . ')';
-                }
-                else {
-                    $alert .= " ($keyname == '$key')";
-                }
-            }
-            Alert($alert);
+            Status('double_cross_check_alert',
+                   {value1 => $value1, value2 => $value2,
+                    table => $refertable,
+                    field1 => $referfield1, field2 => $referfield2,
+                    keyname => $keyname, key => $key}, 'alert');
         }
     }
 }
@@ -595,26 +557,21 @@ DoubleCrossCheck("milestones", "product_id", "value",
 ###########################################################################
 # Perform login checks
 ###########################################################################
-Status("Checking profile logins");
+
+Status('profile_login_start');
 
 my $sth = $dbh->prepare(q{SELECT userid, login_name FROM profiles});
 $sth->execute;
 
 while (my ($id, $email) = $sth->fetchrow_array) {
     validate_email_syntax($email)
-      || Alert "Bad profile email address, id=$id,  &lt;$email&gt;.";
+      || Status('profile_login_alert', {id => $id, email => $email}, 'alert');
 }
 
 ###########################################################################
 # Perform vote/keyword cache checks
 ###########################################################################
 
-sub AlertBadVoteCache {
-    my ($id) = (@_);
-    Alert("Bad vote cache for bug " . BugLink($id));
-}
-
 check_votes_or_keywords();
 
 sub check_votes_or_keywords {
@@ -647,7 +604,7 @@ sub check_votes_or_keywords {
 sub _check_votes {
     my $votes = shift;
 
-    Status("Checking cached vote counts");
+    Status('vote_count_start');
     my $dbh = Bugzilla->dbh;
     my $sth = $dbh->prepare(q{SELECT bug_id, SUM(vote_count)
                                 FROM votes }.
@@ -658,29 +615,27 @@ sub _check_votes {
 
     while (my ($id, $v) = $sth->fetchrow_array) {
         if ($v <= 0) {
-            Alert("Bad vote sum for bug $id");
+            Status('vote_count_alert', {id => $id}, 'alert');
         } else {
             if (!defined $votes->{$id} || $votes->{$id} != $v) {
-                AlertBadVoteCache($id);
+                Status('vote_cache_alert', {id => $id}, 'alert');
                 $offer_votecache_rebuild = 1;
             }
             delete $votes->{$id};
         }
     }
     foreach my $id (keys %$votes) {
-        AlertBadVoteCache($id);
+        Status('vote_cache_alert', {id => $id}, 'alert');
         $offer_votecache_rebuild = 1;
     }
 
-    if ($offer_votecache_rebuild) {
-        print qq{<a href="sanitycheck.cgi?rebuildvotecache=1">Click here to rebuild the vote cache</a><p>\n};
-    }
+    Status('vote_cache_rebuild_fix') if $offer_votecache_rebuild;
 }
 
 sub _check_keywords {
     my $keyword = shift;
 
-    Status("Checking keywords table");
+    Status('keyword_check_start');
     my $dbh = Bugzilla->dbh;
     my $cgi = Bugzilla->cgi;
 
@@ -691,11 +646,11 @@ sub _check_keywords {
     foreach (@$keywords) {
         my ($id, $name) = @$_;
         if ($keywordids{$id}) {
-            Alert("Duplicate entry in keyworddefs for id $id");
+            Status('keyword_check_alert', {id => $id}, 'alert');
         }
         $keywordids{$id} = 1;
         if ($name =~ /[\s,]/) {
-            Alert("Bogus name in keyworddefs for id $id");
+            Status('keyword_check_invalid_name', {id => $id}, 'alert');
         }
     }
 
@@ -707,18 +662,18 @@ sub _check_keywords {
     my $lastk;
     while (my ($id, $k) = $sth->fetchrow_array) {
         if (!$keywordids{$k}) {
-            Alert("Bogus keywordids $k found in keywords table");
+            Status('keyword_check_invalid_id', {id => $k}, 'alert');
         }
         if (defined $lastid && $id eq $lastid && $k eq $lastk) {
-            Alert("Duplicate keyword ids found in bug " . BugLink($id));
+            Status('keyword_check_duplicated_ids', {id => $id}, 'alert');
         }
         $lastid = $id;
         $lastk = $k;
     }
 
-    Status("Checking cached keywords");
+    Status('keyword_cache_start');
 
-    if (defined $cgi->param('rebuildkeywordcache')) {
+    if ($cgi->param('rebuildkeywordcache')) {
         $dbh->bz_lock_tables('bugs write', 'keywords read', 'keyworddefs read');
     }
 
@@ -764,15 +719,13 @@ sub _check_keywords {
     }
     if (@badbugs) {
         @badbugs = sort {$a <=> $b} @badbugs;
-        Alert(scalar(@badbugs) . " bug(s) found with incorrect keyword cache: " .
-              BugListLinks(@badbugs));
 
-        my $sth_update = $dbh->prepare(q{UPDATE bugs
-                                            SET keywords = ?
-                                          WHERE bug_id = ?});
+        if ($cgi->param('rebuildkeywordcache')) {
+            my $sth_update = $dbh->prepare(q{UPDATE bugs
+                                                SET keywords = ?
+                                              WHERE bug_id = ?});
 
-        if (defined $cgi->param('rebuildkeywordcache')) {
-            Status("OK, now fixing keyword cache.");
+            Status('keyword_cache_fixing');
             foreach my $b (@badbugs) {
                 my $k = '';
                 if (exists($realk{$b})) {
@@ -780,13 +733,14 @@ sub _check_keywords {
                 }
                 $sth_update->execute($k, $b);
             }
-            Status("Keyword cache fixed.");
+            Status('keyword_cache_fixed');
         } else {
-            print qq{<a href="sanitycheck.cgi?rebuildkeywordcache=1">Click here to rebuild the keyword cache</a><p>\n};
+            Status('keyword_cache_alert', {badbugs => \@badbugs}, 'alert');
+            Status('keyword_cache_rebuild');
         }
     }
 
-    if (defined $cgi->param('rebuildkeywordcache')) {
+    if ($cgi->param('rebuildkeywordcache')) {
         $dbh->bz_unlock_tables();
     }
 }
@@ -795,7 +749,7 @@ sub _check_keywords {
 # Check for flags being in incorrect products and components
 ###########################################################################
 
-Status('Checking for flags being in the wrong product/component');
+Status('flag_check_start');
 
 my $invalid_flags = $dbh->selectall_arrayref(
        'SELECT DISTINCT flags.id, flags.bug_id, flags.attach_id
@@ -824,22 +778,22 @@ push(@invalid_flags, @$invalid_flags);
 
 if (scalar(@invalid_flags)) {
     if ($cgi->param('remove_invalid_flags')) {
-        Status("OK, now deleting invalid flags.");
+        Status('flag_deletion_start');
         my @flag_ids = map {$_->[0]} @invalid_flags;
         $dbh->bz_lock_tables('flags WRITE');
         # Silently delete these flags, with no notification to requesters/setters.
         $dbh->do('DELETE FROM flags WHERE id IN (' . join(',', @flag_ids) .')');
         $dbh->bz_unlock_tables();
-        Status("Invalid flags deleted.");
+        Status('flag_deletion_end');
     }
     else {
         foreach my $flag (@$invalid_flags) {
             my ($flag_id, $bug_id, $attach_id) = @$flag;
-            Alert("Invalid flag $flag_id for " .
-                  ($attach_id ? "attachment $attach_id in bug " : "bug ") . BugLink($bug_id));
+            Status('flag_alert',
+                   {flag_id => $flag_id, attach_id => $attach_id, bug_id => $bug_id},
+                   'alert');
         }
-        print qq{<a href="sanitycheck.cgi?remove_invalid_flags=1">Click
-                 here to delete invalid flags</a><p>\n};
+        Status('flag_fix');
     }
 }
 
@@ -856,57 +810,58 @@ sub BugCheck {
                                             ORDER BY bugs.bug_id});
 
     if (scalar(@$badbugs)) {
-        Alert("$errortext: " . BugListLinks(@$badbugs));
+        Status('bug_check_alert',
+               {errortext => get_string($errortext), badbugs => $badbugs},
+               'alert');
+
         if ($repairparam) {
-            $repairtext ||= 'Repair these bugs';
-            print qq{<a href="sanitycheck.cgi?$repairparam=1">$repairtext</a>.},
-                  '<p>';
+            $repairtext ||= 'repair_bugs';
+            Status('bug_check_repair',
+                   {param => $repairparam, text => get_string($repairtext)});
         }
     }
 }
 
-Status("Checking for bugs with no creation date (which makes them invisible)");
+Status('bug_check_creation_date');
 
-BugCheck("bugs WHERE creation_ts IS NULL", "Bugs with no creation date",
-         "repair_creation_date", "Repair missing creation date for these bugs");
+BugCheck("bugs WHERE creation_ts IS NULL", 'bug_check_creation_date_error_text',
+         'repair_creation_date', 'bug_check_creation_date_repair_text');
 
-Status("Checking resolution/duplicates");
+Status('bug_check_res_dupl');
 
 BugCheck("bugs INNER JOIN duplicates ON bugs.bug_id = duplicates.dupe " .
-         "WHERE bugs.resolution != 'DUPLICATE'",
-         "Bug(s) found on duplicates table that are not marked duplicate");
+         "WHERE bugs.resolution != 'DUPLICATE'", 'bug_check_res_dupl_error_text');
 
 BugCheck("bugs LEFT JOIN duplicates ON bugs.bug_id = duplicates.dupe WHERE " .
          "bugs.resolution = 'DUPLICATE' AND " .
-         "duplicates.dupe IS NULL",
-         "Bug(s) found marked resolved duplicate and not on duplicates table");
+         "duplicates.dupe IS NULL", 'bug_check_res_dupl_error_text2');
 
-Status("Checking statuses/resolutions");
+Status('bug_check_status_res');
 
 my @open_states = map($dbh->quote($_), BUG_STATE_OPEN);
 my $open_states = join(', ', @open_states);
 
 BugCheck("bugs WHERE bug_status IN ($open_states) AND resolution != ''",
-         "Bugs with open status and a resolution");
+         'bug_check_status_res_error_text');
 BugCheck("bugs WHERE bug_status NOT IN ($open_states) AND resolution = ''",
-         "Bugs with non-open status and no resolution");
+         'bug_check_status_res_error_text2');
 
-Status("Checking statuses/everconfirmed");
+Status('bug_check_status_everconfirmed');
 
 BugCheck("bugs WHERE bug_status = 'UNCONFIRMED' AND everconfirmed = 1",
-         "Bugs that are UNCONFIRMED but have everconfirmed set");
+         'bug_check_status_everconfirmed_error_text');
 # The below list of resolutions is hardcoded because we don't know if future
 # resolutions will be confirmed, unconfirmed or maybeconfirmed.  I suspect
 # they will be maybeconfirmed, e.g. ASLEEP and REMIND.  This hardcoding should
 # disappear when we have customised statuses.
 BugCheck("bugs WHERE bug_status IN ('NEW', 'ASSIGNED', 'REOPENED') AND everconfirmed = 0",
-         "Bugs with confirmed status but don't have everconfirmed set"); 
+         'bug_check_status_everconfirmed_error_text2');
 
-Status("Checking votes/everconfirmed");
+Status('bug_check_votes_everconfirmed');
 
 BugCheck("bugs INNER JOIN products ON bugs.product_id = products.id " .
          "WHERE everconfirmed = 0 AND votestoconfirm <= votes",
-         "Bugs that have enough votes to be confirmed but haven't been");
+         'bug_check_votes_everconfirmed_error_text');
 
 ###########################################################################
 # Control Values
@@ -914,7 +869,7 @@ BugCheck("bugs INNER JOIN products ON bugs.product_id = products.id " .
 
 # Checks for values that are invalid OR
 # not among the 9 valid combinations
-Status("Checking for bad values in group_control_map");
+Status('bug_check_control_values');
 my $groups = join(", ", (CONTROLMAPNA, CONTROLMAPSHOWN, CONTROLMAPDEFAULT,
 CONTROLMAPMANDATORY));
 my $query = qq{
@@ -926,13 +881,11 @@ my $query = qq{
              AND (membercontrol != } . CONTROLMAPSHOWN . q{)
              AND ((membercontrol != } . CONTROLMAPDEFAULT . q{)
                   OR (othercontrol = } . CONTROLMAPSHOWN . q{)))};
-                  
-my $c = $dbh->selectrow_array($query);
-if ($c) {
-    Alert("Found $c bad group_control_map entries");
-}
 
-Status("Checking for bugs with groups violating their product's group controls");
+my $entries = $dbh->selectrow_array($query);
+Status('bug_check_control_values_alert', {entries => $entries}, 'alert') if $entries;
+
+Status('bug_check_control_values_violation');
 BugCheck("bugs
          INNER JOIN bug_group_map
             ON bugs.bug_id = bug_group_map.bug_id
@@ -941,10 +894,9 @@ BugCheck("bugs
            AND bug_group_map.group_id = group_control_map.group_id
          WHERE ((group_control_map.membercontrol = " . CONTROLMAPNA . ")
          OR (group_control_map.membercontrol IS NULL))",
-         'Have groups not permitted for their products',
+         'bug_check_control_values_error_text',
          'createmissinggroupcontrolmapentries',
-         'Permit the missing groups for the affected products
-          (set member control to <code>SHOWN</code>)');
+         'bug_check_control_values_repair_text');
 
 BugCheck("bugs
          INNER JOIN group_control_map
@@ -957,14 +909,13 @@ BugCheck("bugs
          WHERE group_control_map.membercontrol = " . CONTROLMAPMANDATORY . "
            AND bug_group_map.group_id IS NULL
            AND groups.isactive != 0",
-         "Are missing groups required for their products");
-
+         'bug_check_control_values_error_text2');
 
 ###########################################################################
 # Unsent mail
 ###########################################################################
 
-Status("Checking for unsent mail");
+Status('unsent_bugmail_check');
 
 my $time = $dbh->sql_interval(30, 'MINUTE');
 my $badbugs = $dbh->selectcol_arrayref(qq{
@@ -976,15 +927,15 @@ my $badbugs = $dbh->selectcol_arrayref(qq{
 
 
 if (scalar(@$badbugs > 0)) {
-    Alert("Bugs that have changes but no mail sent for at least half an hour: " .
-          BugListLinks(@$badbugs));
-
-    print qq{<a href="sanitycheck.cgi?rescanallBugMail=1">Send these mails</a>.<p>\n};
+    Status('unsent_bugmail_alert', {badbugs => $badbugs}, 'alert');
+    Status('unsent_bugmail_fix');
 }
 
 ###########################################################################
 # End
 ###########################################################################
 
-Status("Sanity check completed.");
-$template->put_footer();
+Status('checks_completed');
+
+$template->process('global/footer.html.tmpl', $vars)
+  || ThrowTemplateError($template->error());
index 48bf3fed8035df22844cddba6606e1ea130e5cb5..e94e889da02f896cff913c1a3a2b54caa79ac3d0 100644 (file)
     border-color: red;
 }
 
+.alert {
+    color: red;
+    background-color: inherit;
+}
+
 p.areyoureallyreallysure {
     color: red;
     font-size: 120%;
diff --git a/template/en/default/admin/sanitycheck/list.html.tmpl b/template/en/default/admin/sanitycheck/list.html.tmpl
new file mode 100644 (file)
index 0000000..2e4a7e0
--- /dev/null
@@ -0,0 +1,38 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+  # License Version 1.1 (the "License"); you may not use this file
+  # except in compliance with the License. You may obtain a copy of
+  # the License at http://www.mozilla.org/MPL/
+  #
+  # Software distributed under the License is distributed on an "AS
+  # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  # implied. See the License for the specific language governing
+  # rights and limitations under the License.
+  #
+  # The Original Code is the Bugzilla Bug Tracking System.
+  #
+  # The Initial Developer of the Original Code is Frédéric Buclin.
+  #
+  # Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
+  #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl title = "Sanity Check"
+                                   style_urls = ['skins/standard/admin.css'] %]
+
+<div>
+  <p>
+    [% terms.Bugzilla %] is checking the referential integrity of your database.
+    This may take several minutes to complete.
+  </p>
+
+  <p>
+    Errors, if any, will be <span class="alert">emphasized like this</span>.
+    Depending on the errors found, some links will be displayed allowing you
+    to easily fix them. Fixing these errors will automatically run this script
+    again (so be aware that it may take an even longer time than the first run).
+  </p>
+</div>
+
+<hr>
diff --git a/template/en/default/admin/sanitycheck/messages.html.tmpl b/template/en/default/admin/sanitycheck/messages.html.tmpl
new file mode 100644 (file)
index 0000000..c4dabd2
--- /dev/null
@@ -0,0 +1,288 @@
+[%# 1.0@bugzilla.org %]
+[%# The contents of this file are subject to the Mozilla Public
+  # License Version 1.1 (the "License"); you may not use this file
+  # except in compliance with the License. You may obtain a copy of
+  # the License at http://www.mozilla.org/MPL/
+  #
+  # Software distributed under the License is distributed on an "AS
+  # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  # implied. See the License for the specific language governing
+  # rights and limitations under the License.
+  #
+  # The Original Code is the Bugzilla Bug Tracking System.
+  #
+  # The Initial Developer of the Original Code is Frédéric Buclin.
+  #
+  # Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
+  #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% san_message = BLOCK %]
+  [% IF san_tag == "checks_start" %]
+    OK, now running sanity checks.
+
+  [% ELSIF san_tag == "checks_completed" %]
+    Sanity check completed.
+
+  [% ELSIF san_tag == "attachment_reference_deletion_start" %]
+    OK, now removing all references to deleted attachments.
+
+  [% ELSIF san_tag == "attachment_reference_deletion_end" %]
+    All references to deleted attachments have been removed.
+
+  [% ELSIF san_tag == "bug_check_alert" %]
+    [% errortext FILTER html %]: [% INCLUDE bug_list badbugs = badbugs %]
+
+  [% ELSIF san_tag == "bug_check_repair" %]
+    <a href="sanitycheck.cgi?[% param FILTER url_quote %]=1">[% text FILTER html %]</a>.
+
+  [% ELSIF san_tag == "bug_check_creation_date" %]
+    Checking for [% terms.bugs %] with no creation date (which makes them invisible).
+
+  [% ELSIF san_tag == "bug_check_creation_date_error_text" %]
+    [% terms.Bugs %] with no creation date
+
+  [% ELSIF san_tag == "bug_check_creation_date_repair_text" %]
+    Repair missing creation date for these [% terms.bugs %]
+
+  [% ELSIF san_tag == "bug_check_res_dupl" %]
+    Checking resolution/duplicates
+
+  [% ELSIF san_tag == "bug_check_res_dupl_error_text" %]
+    [% terms.Bugs %] found on duplicates table that are not marked duplicate
+
+  [% ELSIF san_tag == "bug_check_res_dupl_error_text2" %]
+    [% terms.Bugs %] found marked resolved duplicate and not on duplicates table
+
+  [% ELSIF san_tag == "bug_check_status_res" %]
+    Checking statuses/resolutions
+
+  [% ELSIF san_tag == "bug_check_status_res_error_text" %]
+    [% terms.Bugs %] with open status and a resolution
+
+  [% ELSIF san_tag == "bug_check_status_res_error_text2" %]
+    [% terms.Bugs %] with non-open status and no resolution
+
+  [% ELSIF san_tag == "bug_check_status_everconfirmed" %]
+    Checking statuses/everconfirmed
+
+  [% ELSIF san_tag == "bug_check_status_everconfirmed_error_text" %]
+    [% terms.Bugs %] that are UNCONFIRMED but have everconfirmed set
+
+  [% ELSIF san_tag == "bug_check_status_everconfirmed_error_text2" %]
+    [% terms.Bugs %] with confirmed status but don't have everconfirmed set
+
+  [% ELSIF san_tag == "bug_check_votes_everconfirmed" %]
+    Checking votes/everconfirmed
+
+  [% ELSIF san_tag == "bug_check_votes_everconfirmed_error_text" %]
+    [% terms.Bugs %] that have enough votes to be confirmed but haven't been
+
+  [% ELSIF san_tag == "bug_check_control_values" %]
+    Checking for bad values in group_control_map
+
+  [% ELSIF san_tag == "bug_check_control_values_alert" %]
+    Found [% entries FILTER html %] bad group_control_map entries
+
+  [% ELSIF san_tag == "bug_check_control_values_violation" %]
+    Checking for [% terms.bugs %] with groups violating their product's group controls
+
+  [% ELSIF san_tag == "bug_check_control_values_error_text" %]
+    Have groups not permitted for their products
+
+  [% ELSIF san_tag == "bug_check_control_values_repair_text" %]
+    Permit the missing groups for the affected products
+    (set member control to <code>SHOWN</code>)
+
+  [% ELSIF san_tag == "bug_check_control_values_error_text2" %]
+    Are missing groups required for their products
+
+  [% ELSIF san_tag == "bug_creation_date_start" %]
+    OK, now fixing missing [% terms.bug %] creation dates.
+
+  [% ELSIF san_tag == "bug_creation_date_fixed" %]
+    [% bug_count FILTER html %] [%+ terms.bugs %] have been fixed.
+
+  [% ELSIF san_tag == "bug_reference_deletion_start" %]
+    OK, now removing all references to deleted [% terms.bugs %].
+
+  [% ELSIF san_tag == "bug_reference_deletion_end" %]
+    All references to deleted [% terms.bugs %] have been removed.
+
+  [% ELSIF san_tag == "cross_check_to" %]
+    Checking references to [% table FILTER html %].[% field FILTER html %]...
+
+  [% ELSIF san_tag == "cross_check_from" %]
+    ... from [% table FILTER html %].[% field FILTER html %].
+
+  [% ELSIF san_tag == "cross_check_alert" %]
+    Bad value '[% value FILTER html %]' found in
+    [%+ table FILTER html %].[% field FILTER html %]
+    [% IF keyname %]
+      [% IF keyname == "bug_id" %]
+        ([% "$terms.bug $key" FILTER bug_link(key) FILTER none %])
+      [% ELSE %]
+        ([% keyname FILTER html %] == '[% key FILTER html %]')
+      [% END %]
+    [% END %]
+
+  [% ELSIF san_tag == "cross_check_attachment_has_references" %]
+    <a href="sanitycheck.cgi?remove_invalid_attach_references=1">Remove
+    invalid references to non existent attachments.</a>
+
+  [% ELSIF san_tag == "cross_check_bug_has_references" %]
+    <a href="sanitycheck.cgi?remove_invalid_bug_references=1">Remove
+    invalid references to non existent [% terms.bugs %].</a>
+
+  [% ELSIF san_tag == "double_cross_check_to" %]
+    Checking references to [% table FILTER html %].[% field1 FILTER html %] /
+    [%+ table FILTER html %].[% field2 FILTER html %]...
+
+  [% ELSIF san_tag == "double_cross_check_from" %]
+    ... from [% table FILTER html %].[% field1 FILTER html %] /
+    [%+ table FILTER html %].[% field2 FILTER html %].
+
+  [% ELSIF san_tag == "double_cross_check_alert" %]
+    Bad values '[% value1 FILTER html %]', '[% value2 FILTER html %]' found
+    in [% table FILTER html %].[% field1 FILTER html %] /
+    [%+ table FILTER html %].[% field2 FILTER html %].
+    [% IF keyname %]
+      [% IF keyname == "bug_id" %]
+        ([% "$terms.bug $key" FILTER bug_link(key) FILTER none %])
+      [% ELSE %]
+        ([% keyname FILTER html %] == '[% key FILTER html %]')
+      [% END %]
+    [% END %]
+
+  [% ELSIF san_tag == "flag_check_start" %]
+    Checking for flags being in the wrong product/component.
+
+  [% ELSIF san_tag == "flag_deletion_start" %]
+    OK, now deleting invalid flags.
+
+  [% ELSIF san_tag == "flag_deletion_end" %]
+    Invalid flags deleted.
+
+  [% ELSIF san_tag == "flag_alert" %]
+    Invalid flag [% flag_id FILTER html %] for
+    [% IF attach_id %]
+      attachment [% attach_id FILTER html %] in
+    [% END %]
+    [%+ "$terms.bug $bug_id" FILTER bug_link(bug_id) FILTER none %].
+
+  [% ELSIF san_tag == "flag_fix" %]
+    <a href="sanitycheck.cgi?remove_invalid_flags=1">Click
+    here to delete invalid flags</a>
+
+  [% ELSIF san_tag == "group_control_map_entries_creation" %]
+    OK, now creating <code>SHOWN</code> member control entries
+    for product/group combinations lacking one.
+
+  [% ELSIF san_tag == "group_control_map_entries_update" %]
+    Updating <code>NA/<em>xxx</em></code> group control setting
+    for group <em>[% group_name FILTER html %]</em> to
+    <code>SHOWN/<em>xxx</em></code> in product
+    <em>[% product_name FILTER html %]</em>.
+
+  [% ELSIF san_tag == "group_control_map_entries_generation" %]
+    Generating <code>SHOWN/NA</code> group control setting
+    for group <em>[% group_name FILTER html %]</em> in product
+    <em>[% product_name FILTER html %]</em>.
+
+  [% ELSIF san_tag == "group_control_map_entries_repaired" %]
+    Repaired [% counter FILTER html %] defective group control settings.
+
+  [% ELSIF san_tag == "keyword_check_start" %]
+    Checking keywords table.
+
+  [% ELSIF san_tag == "keyword_check_alert" %]
+    Duplicate entry in keyworddefs for id [% id FILTER html %].
+
+  [% ELSIF san_tag == "keyword_check_invalid_name" %]
+    Bogus name in keyworddefs for id [% id FILTER html %].
+
+  [% ELSIF san_tag == "keyword_check_invalid_id" %]
+    Bogus keywordids [% id FILTER html %] found in keywords table.
+
+  [% ELSIF san_tag == "keyword_check_duplicated_ids" %]
+    Duplicate keyword IDs found in [% "$terms.bug $id" FILTER bug_link(id) FILTER none %].
+
+  [% ELSIF san_tag == "keyword_cache_start" %]
+    Checking cached keywords.
+
+  [% ELSIF san_tag == "keyword_cache_alert" %]
+    [% badbugs.size FILTER none %] [%+ terms.bugs %] found with
+    incorrect keyword cache: [% INCLUDE bug_list badbugs = badbugs %]
+
+  [% ELSIF san_tag == "keyword_cache_fixing" %]
+    OK, now fixing keyword cache.
+
+  [% ELSIF san_tag == "keyword_cache_fixed" %]
+    Keyword cache fixed.
+
+  [% ELSIF san_tag == "keyword_cache_rebuild" %]
+    <a href="sanitycheck.cgi?rebuildkeywordcache=1">Click here to
+    rebuild the keyword cache</a>.
+
+  [% ELSIF san_tag == "profile_login_start" %]
+    Checking profile logins.
+
+  [% ELSIF san_tag == "profile_login_alert" %]
+    Bad profile email address, id=[% id FILTER html %],
+    &lt;[% email FILTER html %]&gt;.
+
+  [% ELSIF san_tag == "repair_bugs" %]
+    Repair these [% terms.bugs %].
+
+  [% ELSIF san_tag == "send_bugmail_start" %]
+    OK, now attempting to send unsent mail.
+
+  [% ELSIF san_tag == "send_bugmail_status" %]
+    [% bug_count FILTER html %] [%+ terms.bugs %] found with
+    possibly unsent mail.
+
+  [% ELSIF san_tag == "send_bugmail_end" %]
+    Unsent mail has been sent.
+
+  [% ELSIF san_tag == "unsent_bugmail_check" %]
+    Checking for unsent mail
+
+  [% ELSIF san_tag == "unsent_bugmail_alert" %]
+    [% terms.Bugs %] that have changes but no mail sent for at least
+    half an hour: [% INCLUDE bug_list badbugs = badbugs %]
+
+  [% ELSIF san_tag == "unsent_bugmail_fix" %]
+    <a href="sanitycheck.cgi?rescanallBugMail=1">Send these mails</a>.
+
+  [% ELSIF san_tag == "vote_cache_rebuild_start" %]
+    OK, now rebuilding vote cache.
+
+  [% ELSIF san_tag == "vote_cache_rebuild_end" %]
+    Vote cache has been rebuilt.
+
+  [% ELSIF san_tag == "vote_cache_rebuild_fix" %]
+    <a href="sanitycheck.cgi?rebuildvotecache=1">Click here to
+    rebuild the vote cache</a>
+
+  [% ELSIF san_tag == "vote_cache_alert" %]
+    Bad vote cache for [% "$terms.bug $id" FILTER bug_link(id) FILTER none %]
+
+  [% ELSIF san_tag == "vote_count_start" %]
+    Checking cached vote counts.
+
+  [% ELSIF san_tag == "vote_count_alert" %]
+    Bad vote sum for [% terms.bug %] [%+ id FILTER html %].
+
+  [% END %]
+[% END %]
+
+[% san_message FILTER html %]
+
+
+[% BLOCK bug_list %]
+  [% FOREACH bug_id = badbugs %]
+    [%+ bug_id FILTER bug_link(bug_id) FILTER none %][% ", " IF !loop.last %]
+  [% END %]
+  (<a href="buglist.cgi?bug_id=[% badbugs.join(",") FILTER url_quote %]">as buglist</a>).
+[% END %]
index b0d92b3d111ad58c685e451a1ebf54b8b23c195d..ef03f76145db1f81664e94519dbe26c427fde10b 100644 (file)
     set to zero automatically as part of marking this [% terms.bug %]
     as either RESOLVED or CLOSED.
 
+  [% ELSIF message_tag == "sanitycheck" %]
+    [%# We use this way to call sanitycheck-specific messages so that
+      # we can still use get_text(). %]
+    [% PROCESS "admin/sanitycheck/messages.html.tmpl" %]
+
   [% ELSIF message_tag == "sudo_started" %]
     [% title = "Sudo session started" %]
       The sudo session has been started.  For the next 6 hours, or until you