Fix for bug 99203: Implements bug aliases feature.

r=bbaetz,jouni
This commit is contained in:
myk%mozilla.org 2002-07-03 23:07:14 +00:00
Родитель b9e21fc1f4
Коммит 82ed1771ce
9 изменённых файлов: 194 добавлений и 48 удалений

Просмотреть файл

@ -33,7 +33,7 @@ package Bug;
use CGI::Carp qw(fatalsToBrowser);
my %ok_field;
for my $key (qw (bug_id product version rep_platform op_sys bug_status
for my $key (qw (bug_id alias product version rep_platform op_sys bug_status
resolution priority bug_severity component assigned_to
reporter bug_file_loc short_desc target_milestone
qa_contact status_whiteboard creation_ts groupset
@ -74,9 +74,12 @@ sub initBug {
my $self = shift();
my ($bug_id, $user_id) = (@_);
# If the bug ID isn't numeric, it might be an alias, so try to convert it.
$bug_id = &::BugAliasToID($bug_id) if $bug_id !~ /^[1-9][0-9]*$/;
my $old_bug_id = $bug_id;
if ((! defined $bug_id) || (!$bug_id) || (!&::detaint_natural($bug_id))) {
# no bug number given
# no bug number given or the alias didn't match a bug
$self->{'bug_id'} = $old_bug_id;
$self->{'error'} = "InvalidBugId";
return $self;
@ -108,7 +111,7 @@ sub initBug {
my $query = "
select
bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
bugs.bug_id, alias, product, version, rep_platform, op_sys, bug_status,
resolution, priority, bug_severity, component, assigned_to, reporter,
bug_file_loc, short_desc, target_milestone, qa_contact,
status_whiteboard, date_format(creation_ts,'%Y-%m-%d %H:%i'),
@ -123,7 +126,7 @@ sub initBug {
if (@row = &::FetchSQLData()) {
my $count = 0;
my %fields;
foreach my $field ("bug_id", "product", "version", "rep_platform",
foreach my $field ("bug_id", "alias", "product", "version", "rep_platform",
"op_sys", "bug_status", "resolution", "priority",
"bug_severity", "component", "assigned_to", "reporter",
"bug_file_loc", "short_desc", "target_milestone",
@ -248,7 +251,7 @@ sub emitXML {
$xml .= "<bug>\n";
foreach my $field ("bug_id", "bug_status", "product",
foreach my $field ("bug_id", "alias", "bug_status", "product",
"priority", "version", "rep_platform", "assigned_to", "delta_ts",
"component", "reporter", "target_milestone", "bug_severity",
"creation_ts", "qa_contact", "op_sys", "resolution", "bug_file_loc",

Просмотреть файл

@ -33,7 +33,7 @@ package Bug;
use CGI::Carp qw(fatalsToBrowser);
my %ok_field;
for my $key (qw (bug_id product version rep_platform op_sys bug_status
for my $key (qw (bug_id alias product version rep_platform op_sys bug_status
resolution priority bug_severity component assigned_to
reporter bug_file_loc short_desc target_milestone
qa_contact status_whiteboard creation_ts groupset
@ -74,9 +74,12 @@ sub initBug {
my $self = shift();
my ($bug_id, $user_id) = (@_);
# If the bug ID isn't numeric, it might be an alias, so try to convert it.
$bug_id = &::BugAliasToID($bug_id) if $bug_id !~ /^[1-9][0-9]*$/;
my $old_bug_id = $bug_id;
if ((! defined $bug_id) || (!$bug_id) || (!&::detaint_natural($bug_id))) {
# no bug number given
# no bug number given or the alias didn't match a bug
$self->{'bug_id'} = $old_bug_id;
$self->{'error'} = "InvalidBugId";
return $self;
@ -108,7 +111,7 @@ sub initBug {
my $query = "
select
bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
bugs.bug_id, alias, product, version, rep_platform, op_sys, bug_status,
resolution, priority, bug_severity, component, assigned_to, reporter,
bug_file_loc, short_desc, target_milestone, qa_contact,
status_whiteboard, date_format(creation_ts,'%Y-%m-%d %H:%i'),
@ -123,7 +126,7 @@ sub initBug {
if (@row = &::FetchSQLData()) {
my $count = 0;
my %fields;
foreach my $field ("bug_id", "product", "version", "rep_platform",
foreach my $field ("bug_id", "alias", "product", "version", "rep_platform",
"op_sys", "bug_status", "resolution", "priority",
"bug_severity", "component", "assigned_to", "reporter",
"bug_file_loc", "short_desc", "target_milestone",
@ -248,7 +251,7 @@ sub emitXML {
$xml .= "<bug>\n";
foreach my $field ("bug_id", "bug_status", "product",
foreach my $field ("bug_id", "alias", "bug_status", "product",
"priority", "version", "rep_platform", "assigned_to", "delta_ts",
"component", "reporter", "target_milestone", "bug_severity",
"creation_ts", "qa_contact", "op_sys", "resolution", "bug_file_loc",

Просмотреть файл

@ -248,22 +248,55 @@ sub CheckFormFieldDefined (\%$) {
}
}
sub BugAliasToID {
# Queries the database for the bug with a given alias, and returns
# the ID of the bug if it exists or the undefined value if it doesn't.
my ($alias) = @_;
return undef unless Param("usebugaliases");
PushGlobalSQLState();
SendSQL("SELECT bug_id FROM bugs WHERE alias = " . SqlQuote($alias));
my $id = FetchOneColumn();
PopGlobalSQLState();
return $id;
}
sub ValidateBugID {
# Validates and verifies a bug ID, making sure the number is a
# positive integer, that it represents an existing bug in the
# database, and that the user is authorized to access that bug.
# We detaint the number here, too
$_[0] = trim($_[0]); # Allow whitespace arround the number
detaint_natural($_[0])
|| DisplayError("The bug number is invalid. If you are trying to use " .
"QuickSearch, you need to enable JavaScript in your " .
"browser. To help us fix this limitation, look " .
"<a href=\"http://bugzilla.mozilla.org/show_bug.cgi?id=70907\">here</a>.")
&& exit;
my ($id) = @_;
my ($id, $skip_authorization) = @_;
# Get rid of white-space around the ID.
$id = trim($id);
# If the ID isn't a number, it might be an alias, so try to convert it.
if ($id !~ /^[1-9][0-9]*$/) {
$id = BugAliasToID($id);
if (!$id) {
my $html_id = html_quote($_[0]);
my $alias_specific_message = Param("usebugaliases") ?
" (it is neither a bug number nor an alias to a bug number)" : "";
DisplayError(qq|
The bug number <em>$html_id</em> is invalid$alias_specific_message.
If you are trying to use QuickSearch, you need to enable JavaScript
in your browser. To help us fix this limitation, add your comments
to <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=70907">bug
70907</a>.
|);
exit;
}
}
# Modify the calling code's original variable to contain the trimmed,
# converted-from-alias ID.
$_[0] = $id;
# Get the values of the usergroupset and userid global variables
# and write them to local variables for use within this function,
# setting those local variables to the default value of zero if
@ -276,6 +309,8 @@ sub ValidateBugID {
|| DisplayError("Bug #$id does not exist.")
&& exit;
return if $skip_authorization;
return if CanSeeBug($id, $::userid, $::usergroupset);
# The user did not pass any of the authorization tests, which means they

Просмотреть файл

@ -77,7 +77,7 @@ sub show_bug {
# Populate the bug hash with the info we get directly from the DB.
my $query = "
SELECT bugs.bug_id, product, version, rep_platform,
SELECT bugs.bug_id, alias, product, version, rep_platform,
op_sys, bug_status, resolution, priority,
bug_severity, component, assigned_to, reporter,
bug_file_loc, short_desc, target_milestone,
@ -92,7 +92,7 @@ sub show_bug {
my $value;
my @row = FetchSQLData();
foreach my $field ("bug_id", "product", "version", "rep_platform",
foreach my $field ("bug_id", "alias", "product", "version", "rep_platform",
"op_sys", "bug_status", "resolution", "priority",
"bug_severity", "component", "assigned_to", "reporter",
"bug_file_loc", "short_desc", "target_milestone",

Просмотреть файл

@ -5,11 +5,12 @@
maintainer CDATA #REQUIRED
exporter CDATA #IMPLIED
>
<!ELEMENT bug (bug_id, (bug_status, product, priority, version, rep_platform, assigned_to, delta_ts, component, reporter, target_milestone?, bug_severity, creation_ts, qa_contact?, op_sys, resolution?, bug_file_loc?, short_desc?, keywords*, status_whiteboard?, dependson*, blocks*, cc*, long_desc*, attachment*)?)>
<!ELEMENT bug (bug_id, (alias?, bug_status, product, priority, version, rep_platform, assigned_to, delta_ts, component, reporter, target_milestone?, bug_severity, creation_ts, qa_contact?, op_sys, resolution?, bug_file_loc?, short_desc?, keywords*, status_whiteboard?, dependson*, blocks*, cc*, long_desc*, attachment*)?)>
<!ATTLIST bug
error (NotFound | NotPermitted | InvalidBugId) #IMPLIED
>
<!ELEMENT bug_id (#PCDATA)>
<!ELEMENT alias (#PCDATA)>
<!ELEMENT exporter (#PCDATA)>
<!ELEMENT urlbase (#PCDATA)>
<!ELEMENT bug_status (#PCDATA)>

Просмотреть файл

@ -1134,7 +1134,7 @@ my $drh = DBI->install_driver($db_base)
if ($my_db_check) {
# Do we have the database itself?
my $sql_want = "3.22.5"; # minimum version of MySQL
my $sql_want = "3.23.6"; # minimum version of MySQL
# original DSN line was:
# my $dsn = "DBI:$db_base:$my_db_name;$my_db_host;$my_db_port";
@ -1332,7 +1332,8 @@ $table{bugs} =
everconfirmed tinyint not null,
reporter_accessible tinyint not null default 1,
cclist_accessible tinyint not null default 1,
alias varchar(20),
index (assigned_to),
index (creation_ts),
index (delta_ts),
@ -1347,7 +1348,9 @@ $table{bugs} =
index (resolution),
index (target_milestone),
index (qa_contact),
index (votes)';
index (votes),
unique(alias)';
$table{cc} =
@ -1564,6 +1567,30 @@ $table{tokens} =
# Create tables
###########################################################################
# Figure out if any existing tables are of type ISAM and convert them
# to type MyISAM if so. ISAM tables are deprecated in MySQL 3.23,
# which Bugzilla now requires, and they don't support more than 16
# indexes per table, which Bugzilla needs.
my $sth = $dbh->prepare("SHOW TABLE STATUS FROM $::db_name");
$sth->execute;
my @isam_tables = ();
while (my ($name, $type) = $sth->fetchrow_array) {
push(@isam_tables, $name) if $type eq "ISAM";
}
if(scalar(@isam_tables)) {
print "One or more of the tables in your existing MySQL database are of type ISAM.\n" .
"ISAM tables are deprecated in MySQL 3.23 and don't support more than 16 indexes\n" .
"per table, which Bugzilla needs. Converting your ISAM tables to type MyISAM:\n\n";
foreach my $table (@isam_tables) {
print "Converting table $table... ";
$dbh->do("ALTER TABLE $table TYPE = MYISAM");
print "done.\n";
}
print "\nISAM->MyISAM table conversion done.\n\n";
}
# Get a list of the existing tables (if any) in the database
my @tables = map { $_ =~ s/.*\.//; $_ } $dbh->tables;
#print 'Tables: ', join " ", @tables, "\n";
@ -1592,10 +1619,6 @@ while (my ($tabname, $fielddef) = each %table) {
or die "Could not create table '$tabname'. Please check your '$db_base' access.\n";
}
###########################################################################
# Populate groups table
###########################################################################
@ -1733,6 +1756,7 @@ AddFDef("delta_ts", "Last changed date", 0);
AddFDef("(to_days(now()) - to_days(bugs.delta_ts))", "Days since bug changed",
0);
AddFDef("longdesc", "Comment", 0);
AddFDef("alias", "Alias", 0);
@ -1861,7 +1885,7 @@ sub bailout { # this is just in case we get interrupted while getting passwd
exit 1;
}
my $sth = $dbh->prepare(<<_End_Of_SQL_);
$sth = $dbh->prepare(<<_End_Of_SQL_);
SELECT login_name
FROM profiles
WHERE groupset=9223372036854775807
@ -2955,6 +2979,14 @@ if (GetFieldDef("logincookies", "hostname")) {
AddField("logincookies", "ipaddr", "varchar(40) NOT NULL");
}
# 2002-07-03 myk@mozilla.org bug99203:
# Add a bug alias field to the bugs table so bugs can be referenced by alias
# in addition to ID.
if (!GetFieldDef("bugs", "alias")) {
AddField("bugs", "alias", "VARCHAR(20)");
$dbh->do("ALTER TABLE bugs ADD UNIQUE (alias)");
}
# If you had to change the --TABLE-- definition in any way, then add your
# differential change code *** A B O V E *** this comment.
#

Просмотреть файл

@ -400,6 +400,12 @@ DefParam("usedependencies",
"b",
1);
DefParam("usebugaliases",
"Do you wish to use bug aliases, which allow you to assign bugs
an easy-to-remember name by which you can refer to them?",
"b",
0);
DefParam("webdotbase",
"It is possible to show graphs of dependent bugs. You may set this parameter to
any of the following:

Просмотреть файл

@ -101,6 +101,24 @@ if (defined $::FORM{'dup_id'} && $::FORM{'knob'} eq "duplicate") {
ValidateComment($::FORM{'comment'});
# If the bug(s) being modified have dependencies, validate them
# and rebuild the list with the validated values. This is important
# because there are situations where validation changes the value
# instead of throwing an error, f.e. when one or more of the values
# is a bug alias that gets converted to its corresponding bug ID
# during validation.
foreach my $field ("dependson", "blocked") {
if (defined($::FORM{$field}) && $::FORM{$field} ne "") {
my @validvalues;
foreach my $id (split(/[\s,]+/, $::FORM{$field})) {
next unless $id;
ValidateBugID($id, 1);
push(@validvalues, $id);
}
$::FORM{$field} = join(",", @validvalues);
}
}
######################################################################
# End Data/Security Validation
######################################################################
@ -497,6 +515,63 @@ foreach my $field ("rep_platform", "priority", "bug_severity",
}
}
# If this installation uses bug aliases, and the user is changing the alias,
# add this change to the query.
if (Param("usebugaliases") && defined($::FORM{'alias'})) {
my $alias = trim($::FORM{'alias'});
# Since aliases are unique (like bug numbers), they can only be changed
# for one bug at a time, so ignore the alias change unless only a single
# bug is being changed.
if (scalar(@idlist) == 1) {
# Validate the alias if the user entered one.
if ($alias ne "") {
# Make sure the alias isn't too long.
if (length($alias) > 20) {
ThrowUserError("Bug aliases cannot be longer than 20 characters.
Please choose a shorter alias.");
}
# Make sure the alias is unique.
my $escaped_alias = SqlQuote($alias);
SendSQL("SELECT bug_id FROM bugs WHERE alias = $escaped_alias " .
"AND bug_id != $idlist[0]");
my $id = FetchOneColumn();
if ($id) {
my $escaped_alias = html_quote($alias);
my $bug_link = GetBugLink($id, "Bug $id");
ThrowUserError("$bug_link has already taken the alias
<em>$escaped_alias</em>. Please choose another one.");
}
# Make sure the alias isn't just a number.
if ($alias =~ /^\d+$/) {
ThrowUserError("You gave this bug the alias <em>$alias</em>,
but aliases cannot be merely numbers, since they could
then be confused with bug IDs. Please choose another
alias containing at least one letter.");
}
# Make sure the alias has no commas or spaces.
if ($alias =~ /[, ]/) {
my $escaped_alias = html_quote($alias);
ThrowUserError("The alias you entered, <em>$escaped_alias</em>,
contains one or more commas or spaces. Aliases cannot contain
commas or spaces because those characters are used to separate
aliases from each other in lists. Please choose another alias
that does not contain commas and spaces.");
}
}
# Add the alias change to the query. If the field contains the blank
# value, make the field be NULL to indicate that the bug has no alias.
# Otherwise, if the field contains a value, update the record
# with that value.
DoComma();
$::query .= "alias = ";
$::query .= ($alias eq "") ? "NULL" : SqlQuote($alias);
}
}
if (defined $::FORM{'qa_contact'}) {
my $name = trim($::FORM{'qa_contact'});
@ -909,23 +984,8 @@ foreach my $id (@idlist) {
$deptree{$target} = [];
my %seen;
foreach my $i (split('[\s,]+', $::FORM{$target})) {
if ($i eq "") {
next;
}
my $orig = $i;
if (!detaint_natural($i)) {
ThrowUserError("$orig is not a legal bug number", undef, "abort");
}
# Don't use CanSeeBug, since we want to keep deps to bugs a
# user can't see
SendSQL("select bug_id from bugs where bug_id = " .
SqlQuote($i));
my $comp = FetchOneColumn();
if ($comp ne $i) {
ThrowUserError("$i is not a legal bug number", undef, "abort");
}
next if $i eq "";
if ($id eq $i) {
ThrowUserError("You can't make a bug blocked or dependent on itself.",
undef,

Просмотреть файл

@ -49,6 +49,12 @@
<td>
<a href="[% Param('urlbase') %]show_bug.cgi?id=[% bug.bug_id %]">
[% bug.bug_id %]</a>
[% IF Param("usebugaliases") %]
<label title="a name for the bug that can be used in place of its ID number, f.e. when adding it to a list of dependencies">
<b>alias:</b>
<input name="alias" value="[% bug.alias FILTER html %]" size="20" maxlength="20">
</label>
[% END %]
</td>
<td>&nbsp;</td>