summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormyk%mozilla.org <>2002-07-04 08:07:09 +0200
committermyk%mozilla.org <>2002-07-04 08:07:09 +0200
commit46c9fb479d36e0a0b3fcbc447d7483ec09666d43 (patch)
tree35b145824f00cee436b84e31de58b4955927aa86
parent690839509f1ce985205824e8092d5893a2130ba6 (diff)
downloadbugzilla-46c9fb479d36e0a0b3fcbc447d7483ec09666d43.tar.gz
bugzilla-46c9fb479d36e0a0b3fcbc447d7483ec09666d43.tar.xz
Fix for bug 99203: Implements bug aliases feature.
r=bbaetz,jouni
-rwxr-xr-xBug.pm13
-rwxr-xr-xBugzilla/Bug.pm13
-rw-r--r--CGI.pl55
-rw-r--r--bug_form.pl4
-rw-r--r--bugzilla.dtd3
-rwxr-xr-xchecksetup.pl48
-rw-r--r--defparams.pl6
-rwxr-xr-xprocess_bug.cgi94
-rw-r--r--template/en/default/bug/edit.html.tmpl6
9 files changed, 194 insertions, 48 deletions
diff --git a/Bug.pm b/Bug.pm
index 7ac2bd101..7e7478c46 100755
--- a/Bug.pm
+++ b/Bug.pm
@@ -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",
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm
index 7ac2bd101..7e7478c46 100755
--- a/Bugzilla/Bug.pm
+++ b/Bugzilla/Bug.pm
@@ -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",
diff --git a/CGI.pl b/CGI.pl
index 0b9935602..8e8da5871 100644
--- a/CGI.pl
+++ b/CGI.pl
@@ -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
diff --git a/bug_form.pl b/bug_form.pl
index 21adb0e30..262327f17 100644
--- a/bug_form.pl
+++ b/bug_form.pl
@@ -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",
diff --git a/bugzilla.dtd b/bugzilla.dtd
index 459755ccd..681a46f9b 100644
--- a/bugzilla.dtd
+++ b/bugzilla.dtd
@@ -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)>
diff --git a/checksetup.pl b/checksetup.pl
index f4eff45c7..628902d61 100755
--- a/checksetup.pl
+++ b/checksetup.pl
@@ -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.
#
diff --git a/defparams.pl b/defparams.pl
index f4fd85f6f..30a7b5fc0 100644
--- a/defparams.pl
+++ b/defparams.pl
@@ -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:
diff --git a/process_bug.cgi b/process_bug.cgi
index 103085457..afed412a3 100755
--- a/process_bug.cgi
+++ b/process_bug.cgi
@@ -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,
diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl
index 81b0a15bf..f88fb4002 100644
--- a/template/en/default/bug/edit.html.tmpl
+++ b/template/en/default/bug/edit.html.tmpl
@@ -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>