diff options
author | lpsolit%gmail.com <> | 2007-03-06 01:33:37 +0100 |
---|---|---|
committer | lpsolit%gmail.com <> | 2007-03-06 01:33:37 +0100 |
commit | ae1857494e5bc3dc6a4b87c0e0e329c0c76108bc (patch) | |
tree | 3a3a41ac2b814d38c09c5365d60ae2f7a296261b | |
parent | 439851b43d129eaa04b2d29438956db8add6de30 (diff) | |
download | bugzilla-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.pm | 38 | ||||
-rwxr-xr-x | sanitycheck.cgi | 319 | ||||
-rw-r--r-- | skins/standard/admin.css | 5 | ||||
-rw-r--r-- | template/en/default/admin/sanitycheck/list.html.tmpl | 38 | ||||
-rw-r--r-- | template/en/default/admin/sanitycheck/messages.html.tmpl | 288 | ||||
-rw-r--r-- | template/en/default/global/messages.html.tmpl | 5 |
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 "$value" 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 "$value1", "$value2" 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, <$email>."; + || 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 %], + <[% email FILTER html %]>. + + [% 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 |