зеркало из https://github.com/mozilla/pjs.git
Fix for bug 99203: Implements bug aliases feature.
r=bbaetz,jouni
This commit is contained in:
Родитель
b9e21fc1f4
Коммит
82ed1771ce
|
@ -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> </td>
|
||||
|
|
Загрузка…
Ссылка в новой задаче