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;
}
# 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
$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;
$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');
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
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
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;
}
# 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',
}
$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');
}
$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
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 @_;
$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
ON $refertable.$referfield = $table.$field
WHERE $table.$field IS NULL
AND $refertable.$referfield IS NOT NULL};
-
+
my $sth = $dbh->prepare($query);
$sth->execute;
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');
}
}
}
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,
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');
}
}
}
###########################################################################
# 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 {
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 }.
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;
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');
}
}
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');
}
}
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})) {
}
$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();
}
}
# 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
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');
}
}
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
# 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{
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
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
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{
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());
--- /dev/null
+[%# 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 %]