summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlpsolit%gmail.com <>2007-03-06 01:33:37 +0100
committerlpsolit%gmail.com <>2007-03-06 01:33:37 +0100
commitae1857494e5bc3dc6a4b87c0e0e329c0c76108bc (patch)
tree3a3a41ac2b814d38c09c5365d60ae2f7a296261b
parent439851b43d129eaa04b2d29438956db8add6de30 (diff)
downloadbugzilla-ae1857494e5bc3dc6a4b87c0e0e329c0c76108bc.tar.gz
bugzilla-ae1857494e5bc3dc6a4b87c0e0e329c0c76108bc.tar.xz
Bug 312197: Templatize sanitycheck.cgi - Patch by Frédéric Buclin <LpSolit@gmail.com> r/a=mkanat
-rw-r--r--Bugzilla/Template.pm38
-rwxr-xr-xsanitycheck.cgi319
-rw-r--r--skins/standard/admin.css5
-rw-r--r--template/en/default/admin/sanitycheck/list.html.tmpl38
-rw-r--r--template/en/default/admin/sanitycheck/messages.html.tmpl288
-rw-r--r--template/en/default/global/messages.html.tmpl5
6 files changed, 471 insertions, 222 deletions
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index 800536cd5..42c45823e 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -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.
diff --git a/sanitycheck.cgi b/sanitycheck.cgi
index bf8ba1980..873432fb9 100755
--- a/sanitycheck.cgi
+++ b/sanitycheck.cgi
@@ -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());
diff --git a/skins/standard/admin.css b/skins/standard/admin.css
index 48bf3fed8..e94e889da 100644
--- a/skins/standard/admin.css
+++ b/skins/standard/admin.css
@@ -29,6 +29,11 @@
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
index 000000000..2e4a7e0db
--- /dev/null
+++ b/template/en/default/admin/sanitycheck/list.html.tmpl
@@ -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
index 000000000..c4dabd2ca
--- /dev/null
+++ b/template/en/default/admin/sanitycheck/messages.html.tmpl
@@ -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 %]
diff --git a/template/en/default/global/messages.html.tmpl b/template/en/default/global/messages.html.tmpl
index b0d92b3d1..ef03f7614 100644
--- a/template/en/default/global/messages.html.tmpl
+++ b/template/en/default/global/messages.html.tmpl
@@ -374,6 +374,11 @@
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