mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
8ec2fa3b0f
authority maintain a list of keywords, and users can associate any keyword with any bug. The new functionality won't appear until at least one keyword is defined. Note that you *must* run the "checksetup.pl" script after updating this change, in order to create the new required tables "keywords" and "keyworddefs".
707 lines
24 KiB
Perl
Executable File
707 lines
24 KiB
Perl
Executable File
#!/usr/bonsaitools/bin/perl -w
|
|
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
|
#
|
|
# 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 Netscape Communications
|
|
# Corporation. Portions created by Netscape are
|
|
# Copyright (C) 1998 Netscape Communications Corporation. All
|
|
# Rights Reserved.
|
|
#
|
|
# Contributor(s): Terry Weissman <terry@mozilla.org>
|
|
# Dan Mosedale <dmose@mozilla.org>
|
|
|
|
use diagnostics;
|
|
use strict;
|
|
|
|
require "CGI.pl";
|
|
|
|
# Shut up misguided -w warnings about "used only once":
|
|
|
|
use vars %::versions,
|
|
%::components,
|
|
%::COOKIE,
|
|
%::keywordsbyname,
|
|
%::legal_keywords,
|
|
%::legal_opsys,
|
|
%::legal_platform,
|
|
%::legal_priority,
|
|
%::legal_severity;
|
|
|
|
confirm_login();
|
|
|
|
print "Content-type: text/html\n\n";
|
|
|
|
PutHeader ("Bug processed");
|
|
|
|
GetVersionTable();
|
|
|
|
if ( Param("strictvaluechecks") ) {
|
|
CheckFormFieldDefined(\%::FORM, 'product');
|
|
CheckFormFieldDefined(\%::FORM, 'version');
|
|
CheckFormFieldDefined(\%::FORM, 'component');
|
|
}
|
|
|
|
if ($::FORM{'product'} ne $::dontchange) {
|
|
if ( Param("strictvaluechecks") ) {
|
|
CheckFormField(\%::FORM, 'product', \@::legal_product);
|
|
}
|
|
my $prod = $::FORM{'product'};
|
|
|
|
# note that when this script is called from buglist.cgi (rather
|
|
# than show_bug.cgi), it's possible that the product will be changed
|
|
# but that the version and/or component will be set to
|
|
# "--dont_change--" but still happen to be correct. in this case,
|
|
# the if statement will incorrectly trigger anyway. this is a
|
|
# pretty weird case, and not terribly unreasonable behavior, but
|
|
# worthy of a comment, perhaps.
|
|
#
|
|
my $vok = lsearch($::versions{$prod}, $::FORM{'version'}) >= 0;
|
|
my $cok = lsearch($::components{$prod}, $::FORM{'component'}) >= 0;
|
|
if (!$vok || !$cok) {
|
|
print "<H1>Changing product means changing version and component.</H1>\n";
|
|
print "You have chosen a new product, and now the version and/or\n";
|
|
print "component fields are not correct. (Or, possibly, the bug did\n";
|
|
print "not have a valid component or version field in the first place.)\n";
|
|
print "Anyway, please set the version and component now.<p>\n";
|
|
print "<form>\n";
|
|
print "<table>\n";
|
|
print "<tr>\n";
|
|
print "<td align=right><b>Product:</b></td>\n";
|
|
print "<td>$prod</td>\n";
|
|
print "</tr><tr>\n";
|
|
print "<td align=right><b>Version:</b></td>\n";
|
|
print "<td>" . Version_element($::FORM{'version'}, $prod) . "</td>\n";
|
|
print "</tr><tr>\n";
|
|
print "<td align=right><b>Component:</b></td>\n";
|
|
print "<td>" . Component_element($::FORM{'component'}, $prod) . "</td>\n";
|
|
print "</tr>\n";
|
|
print "</table>\n";
|
|
foreach my $i (keys %::FORM) {
|
|
if ($i ne 'version' && $i ne 'component') {
|
|
print "<input type=hidden name=$i value=\"" .
|
|
value_quote($::FORM{$i}) . "\">\n";
|
|
}
|
|
}
|
|
print "<input type=submit value=Commit>\n";
|
|
print "</form>\n";
|
|
print "</hr>\n";
|
|
print "<a href=query.cgi>Cancel all this and go to the query page.</a>\n";
|
|
exit;
|
|
}
|
|
}
|
|
|
|
|
|
my @idlist;
|
|
if (defined $::FORM{'id'}) {
|
|
|
|
# since this means that we were called from show_bug.cgi, now is a good
|
|
# time to do a whole bunch of error checking that can't easily happen when
|
|
# we've been called from buglist.cgi, because buglist.cgi only tweaks
|
|
# values that have been changed instead of submitting all the new values.
|
|
# (XXX those error checks need to happen too, but implementing them
|
|
# is more work in the current architecture of this script...)
|
|
#
|
|
if ( Param('strictvaluechecks') ) {
|
|
CheckFormField(\%::FORM, 'rep_platform', \@::legal_platform);
|
|
CheckFormField(\%::FORM, 'priority', \@::legal_priority);
|
|
CheckFormField(\%::FORM, 'bug_severity', \@::legal_severity);
|
|
CheckFormField(\%::FORM, 'component',
|
|
\@{$::components{$::FORM{'product'}}});
|
|
CheckFormFieldDefined(\%::FORM, 'bug_file_loc');
|
|
CheckFormFieldDefined(\%::FORM, 'short_desc');
|
|
CheckFormField(\%::FORM, 'product', \@::legal_product);
|
|
CheckFormField(\%::FORM, 'version',
|
|
\@{$::versions{$::FORM{'product'}}});
|
|
CheckFormField(\%::FORM, 'op_sys', \@::legal_opsys);
|
|
CheckFormFieldDefined(\%::FORM, 'longdesclength');
|
|
CheckPosInt($::FORM{'id'});
|
|
}
|
|
push @idlist, $::FORM{'id'};
|
|
} else {
|
|
foreach my $i (keys %::FORM) {
|
|
if ($i =~ /^id_/) {
|
|
if ( Param('strictvaluechecks') ) {
|
|
CheckPosInt(substr($i, 3));
|
|
}
|
|
push @idlist, substr($i, 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!defined $::FORM{'who'}) {
|
|
$::FORM{'who'} = $::COOKIE{'Bugzilla_login'};
|
|
}
|
|
|
|
# the common updates to all bugs in @idlist start here
|
|
#
|
|
print "<TITLE>Update Bug " . join(" ", @idlist) . "</TITLE>\n";
|
|
if (defined $::FORM{'id'}) {
|
|
navigation_header();
|
|
}
|
|
print "<HR>\n";
|
|
$::query = "update bugs\nset";
|
|
$::comma = "";
|
|
umask(0);
|
|
|
|
sub DoComma {
|
|
$::query .= "$::comma\n ";
|
|
$::comma = ",";
|
|
}
|
|
|
|
sub ChangeStatus {
|
|
my ($str) = (@_);
|
|
if ($str ne $::dontchange) {
|
|
DoComma();
|
|
$::query .= "bug_status = '$str'";
|
|
}
|
|
}
|
|
|
|
sub ChangeResolution {
|
|
my ($str) = (@_);
|
|
if ($str ne $::dontchange) {
|
|
DoComma();
|
|
$::query .= "resolution = '$str'";
|
|
}
|
|
}
|
|
|
|
#
|
|
# This function checks if there is a comment required for a specific
|
|
# function and tests, if the comment was given.
|
|
# If comments are required for functions is defined by params.
|
|
#
|
|
sub CheckonComment( $ ) {
|
|
my ($function) = (@_);
|
|
|
|
# Param is 1 if comment should be added !
|
|
my $ret = Param( "commenton" . $function );
|
|
|
|
# Allow without comment in case of undefined Params.
|
|
$ret = 0 unless ( defined( $ret ));
|
|
|
|
if( $ret ) {
|
|
if (!defined $::FORM{'comment'} || $::FORM{'comment'} =~ /^\s*$/) {
|
|
# No commet - sorry, action not allowed !
|
|
warnBanner("You have to specify a <b>comment</b> on this change." .
|
|
"<p>" .
|
|
"Please press <b>Back</b> and give some words " .
|
|
"on the reason of the your change.\n" );
|
|
exit( 0 );
|
|
} else {
|
|
$ret = 0;
|
|
}
|
|
}
|
|
return( ! $ret ); # Return val has to be inverted
|
|
}
|
|
|
|
|
|
my $foundbit = 0;
|
|
foreach my $b (grep(/^bit-\d*$/, keys %::FORM)) {
|
|
if (!$foundbit) {
|
|
$foundbit = 1;
|
|
DoComma();
|
|
$::query .= "groupset = 0";
|
|
}
|
|
if ($::FORM{$b}) {
|
|
my $v = substr($b, 4);
|
|
$::query .= "+ $v"; # Carefully written so that the math is
|
|
# done by MySQL, which can handle 64-bit math,
|
|
# and not by Perl, which I *think* can not.
|
|
}
|
|
}
|
|
|
|
foreach my $field ("rep_platform", "priority", "bug_severity",
|
|
"summary", "component", "bug_file_loc", "short_desc",
|
|
"product", "version", "op_sys",
|
|
"target_milestone", "status_whiteboard") {
|
|
if (defined $::FORM{$field}) {
|
|
if ($::FORM{$field} ne $::dontchange) {
|
|
DoComma();
|
|
$::query .= "$field = " . SqlQuote(trim($::FORM{$field}));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (defined $::FORM{'qa_contact'}) {
|
|
my $name = trim($::FORM{'qa_contact'});
|
|
if ($name ne $::dontchange) {
|
|
my $id = 0;
|
|
if ($name ne "") {
|
|
$id = DBNameToIdAndCheck($name);
|
|
}
|
|
DoComma();
|
|
$::query .= "qa_contact = $id";
|
|
}
|
|
}
|
|
|
|
|
|
ConnectToDatabase();
|
|
|
|
if ( Param('strictvaluechecks') ) {
|
|
CheckFormFieldDefined(\%::FORM, 'knob');
|
|
}
|
|
SWITCH: for ($::FORM{'knob'}) {
|
|
/^none$/ && do {
|
|
last SWITCH;
|
|
};
|
|
/^accept$/ && CheckonComment( "accept" ) && do {
|
|
ChangeStatus('ASSIGNED');
|
|
last SWITCH;
|
|
};
|
|
/^clearresolution$/ && CheckonComment( "clearresolution" ) &&do {
|
|
ChangeResolution('');
|
|
last SWITCH;
|
|
};
|
|
/^resolve$/ && CheckonComment( "resolve" ) && do {
|
|
ChangeStatus('RESOLVED');
|
|
ChangeResolution($::FORM{'resolution'});
|
|
last SWITCH;
|
|
};
|
|
/^reassign$/ && CheckonComment( "reassign" ) && do {
|
|
ChangeStatus('NEW');
|
|
DoComma();
|
|
if ( Param("strictvaluechecks") ) {
|
|
if ( !defined$::FORM{'assigned_to'} ||
|
|
trim($::FORM{'assigned_to'}) eq "") {
|
|
print "You cannot reassign to a bug to noone. Unless you intentionally cleared out the \"Reassign bug to\" field, ";
|
|
print Param("browserbugmessage");
|
|
exit 0;
|
|
}
|
|
}
|
|
my $newid = DBNameToIdAndCheck($::FORM{'assigned_to'});
|
|
$::query .= "assigned_to = $newid";
|
|
last SWITCH;
|
|
};
|
|
/^reassignbycomponent$/ && CheckonComment( "reassignbycomponent" ) && do {
|
|
if ($::FORM{'product'} eq $::dontchange) {
|
|
print "You must specify a product to help determine the new\n";
|
|
print "owner of these bugs.\n";
|
|
exit 0
|
|
}
|
|
if ($::FORM{'component'} eq $::dontchange) {
|
|
print "You must specify a component whose owner should get\n";
|
|
print "assigned these bugs.\n";
|
|
exit 0
|
|
}
|
|
ChangeStatus('NEW');
|
|
SendSQL("select initialowner from components where program=" .
|
|
SqlQuote($::FORM{'product'}) . " and value=" .
|
|
SqlQuote($::FORM{'component'}));
|
|
my $newname = FetchOneColumn();
|
|
my $newid = DBNameToIdAndCheck($newname, 1);
|
|
DoComma();
|
|
$::query .= "assigned_to = $newid";
|
|
last SWITCH;
|
|
};
|
|
/^reopen$/ && CheckonComment( "reopen" ) && do {
|
|
ChangeStatus('REOPENED');
|
|
last SWITCH;
|
|
};
|
|
/^verify$/ && CheckonComment( "verify" ) && do {
|
|
ChangeStatus('VERIFIED');
|
|
last SWITCH;
|
|
};
|
|
/^close$/ && CheckonComment( "close" ) && do {
|
|
ChangeStatus('CLOSED');
|
|
last SWITCH;
|
|
};
|
|
/^duplicate$/ && CheckonComment( "duplicate" ) && do {
|
|
ChangeStatus('RESOLVED');
|
|
ChangeResolution('DUPLICATE');
|
|
if ( Param('strictvaluechecks') ) {
|
|
CheckFormFieldDefined(\%::FORM,'dup_id');
|
|
}
|
|
my $num = trim($::FORM{'dup_id'});
|
|
if ($num !~ /^[0-9]*$/) {
|
|
print "You must specify a bug number of which this bug is a\n";
|
|
print "duplicate. The bug has not been changed.\n";
|
|
exit;
|
|
}
|
|
if (defined($::FORM{'id'}) && $::FORM{'dup_id'} == $::FORM{'id'}) {
|
|
print "Nice try, $::FORM{'who'}. But it doesn't really make sense to mark a\n";
|
|
print "bug as a duplicate of itself, does it?\n";
|
|
exit;
|
|
}
|
|
AppendComment($::FORM{'dup_id'}, $::FORM{'who'}, "*** Bug $::FORM{'id'} has been marked as a duplicate of this bug. ***");
|
|
if ( Param('strictvaluechecks') ) {
|
|
CheckFormFieldDefined(\%::FORM,'comment');
|
|
}
|
|
$::FORM{'comment'} .= "\n\n*** This bug has been marked as a duplicate of $::FORM{'dup_id'} ***";
|
|
|
|
print "<TABLE BORDER=1><TD><H2>Notation added to bug $::FORM{'dup_id'}</H2>\n";
|
|
system("./processmail $::FORM{'dup_id'} $::FORM{'who'}");
|
|
print "<TD><A HREF=\"show_bug.cgi?id=$::FORM{'dup_id'}\">Go To BUG# $::FORM{'dup_id'}</A></TABLE>\n";
|
|
|
|
last SWITCH;
|
|
};
|
|
# default
|
|
print "Unknown action $::FORM{'knob'}!\n";
|
|
exit;
|
|
}
|
|
|
|
|
|
if ($#idlist < 0) {
|
|
print "You apparently didn't choose any bugs to modify.\n";
|
|
print "<p>Click <b>Back</b> and try again.\n";
|
|
exit;
|
|
}
|
|
|
|
|
|
my @keywordlist;
|
|
my %keywordseen;
|
|
|
|
if ($::FORM{'keywords'}) {
|
|
foreach my $keyword (split(/,/, $::FORM{'keywords'})) {
|
|
$keyword = trim($keyword);
|
|
my $i = $::keywordsbyname{$keyword};
|
|
if (!$i) {
|
|
print "Unknown keyword named <code>$keyword</code>.\n";
|
|
print "<P>The legal keyword names are <A HREF=describekeywords.cgi>";
|
|
print "listed here</A>.\n";
|
|
print "<P>Please click the <B>Back</B> button and try again.\n";
|
|
exit;
|
|
}
|
|
if (!$keywordseen{$i}) {
|
|
push(@keywordlist, $i);
|
|
$keywordseen{$i} = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($::comma eq "") {
|
|
if (!defined $::FORM{'comment'} || $::FORM{'comment'} =~ /^\s*$/) {
|
|
print "Um, you apparently did not change anything on the selected\n";
|
|
print "bugs. <p>Click <b>Back</b> and try again.\n";
|
|
exit
|
|
}
|
|
}
|
|
|
|
my $basequery = $::query;
|
|
my $delta_ts;
|
|
|
|
|
|
sub SnapShotBug {
|
|
my ($id) = (@_);
|
|
SendSQL("select delta_ts, " . join(',', @::log_columns) .
|
|
" from bugs where bug_id = $id");
|
|
my @row = FetchSQLData();
|
|
$delta_ts = shift @row;
|
|
|
|
return @row;
|
|
}
|
|
|
|
|
|
sub SnapShotDeps {
|
|
my ($i, $target, $me) = (@_);
|
|
SendSQL("select $target from dependencies where $me = $i order by $target");
|
|
my @list;
|
|
while (MoreSQLData()) {
|
|
push(@list, FetchOneColumn());
|
|
}
|
|
return join(',', @list);
|
|
}
|
|
|
|
|
|
sub SnapShotKeywords {
|
|
my ($id) = (@_);
|
|
SendSQL("SELECT keyworddefs.name
|
|
FROM keyworddefs, keywords
|
|
WHERE keywords.bug_id = $id AND keyworddefs.id = keywords.keywordid
|
|
ORDER BY keyworddefs.name");
|
|
my @list;
|
|
while (MoreSQLData()) {
|
|
push(@list, FetchOneColumn());
|
|
}
|
|
return join(',', @list);
|
|
}
|
|
|
|
|
|
my $keywordaction = $::FORM{'keywordaction'} || "makeexact";
|
|
|
|
|
|
my $whoid = DBNameToIdAndCheck($::FORM{'who'});
|
|
my $timestamp;
|
|
|
|
sub LogDependencyActivity {
|
|
my ($i, $oldstr, $target, $me) = (@_);
|
|
my $newstr = SnapShotDeps($i, $target, $me);
|
|
if ($oldstr ne $newstr) {
|
|
SendSQL("insert into bugs_activity (bug_id,who,bug_when,field,oldvalue,newvalue) values ($i,$whoid,$timestamp,'$target','$oldstr','$newstr')");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
# this loop iterates once for each bug to be processed (eg when this script
|
|
# is called with multiple bugs selected from buglist.cgi instead of
|
|
# show_bug.cgi).
|
|
#
|
|
foreach my $id (@idlist) {
|
|
my %dependencychanged;
|
|
SendSQL("lock tables bugs write, bugs_activity write, cc write, profiles write, dependencies write, votes write, keywords write, keyworddefs read");
|
|
my @oldvalues = SnapShotBug($id);
|
|
my $oldkeywords = SnapShotKeywords($id);
|
|
|
|
if (defined $::FORM{'delta_ts'} && $::FORM{'delta_ts'} ne $delta_ts) {
|
|
print "
|
|
<H1>Mid-air collision detected!</H1>
|
|
Someone else has made changes to this bug at the same time you were trying to.
|
|
The changes made were:
|
|
<p>
|
|
";
|
|
DumpBugActivity($id, $delta_ts);
|
|
my $longdesc = GetLongDescription($id);
|
|
my $longchanged = 0;
|
|
|
|
if (length($longdesc) > $::FORM{'longdesclength'}) {
|
|
$longchanged = 1;
|
|
print "<P>Added text to the long description:<blockquote><pre>";
|
|
print html_quote(substr($longdesc, $::FORM{'longdesclength'}));
|
|
print "</pre></blockquote>\n";
|
|
}
|
|
SendSQL("unlock tables");
|
|
print "You have the following choices: <ul>\n";
|
|
$::FORM{'delta_ts'} = $delta_ts;
|
|
print "<li><form method=post>";
|
|
foreach my $i (keys %::FORM) {
|
|
my $value = value_quote($::FORM{$i});
|
|
print qq{<input type=hidden name="$i" value="$value">\n};
|
|
}
|
|
print qq{<input type=submit value="Submit my changes anyway">\n};
|
|
print " This will cause all of the above changes to be overwritten";
|
|
if ($longchanged) {
|
|
print ", except for the changes to the description";
|
|
}
|
|
print qq{.</form>\n<li><a href="show_bug.cgi?id=$id">Throw away my changes, and go revisit bug $id</a></ul>\n};
|
|
navigation_header();
|
|
exit;
|
|
}
|
|
|
|
my %deps;
|
|
if (defined $::FORM{'dependson'}) {
|
|
my $me = "blocked";
|
|
my $target = "dependson";
|
|
for (1..2) {
|
|
$deps{$target} = [];
|
|
my %seen;
|
|
foreach my $i (split('[\s,]+', $::FORM{$target})) {
|
|
if ($i eq "") {
|
|
next;
|
|
|
|
}
|
|
SendSQL("select bug_id from bugs where bug_id = " .
|
|
SqlQuote($i));
|
|
my $comp = FetchOneColumn();
|
|
if ($comp ne $i) {
|
|
print "<H1>$i is not a legal bug number</H1>\n";
|
|
print "<p>Click <b>Back</b> and try again.\n";
|
|
exit;
|
|
}
|
|
if (!exists $seen{$i}) {
|
|
push(@{$deps{$target}}, $i);
|
|
$seen{$i} = 1;
|
|
}
|
|
}
|
|
my @stack = @{$deps{$target}};
|
|
while (@stack) {
|
|
my $i = shift @stack;
|
|
SendSQL("select $target from dependencies where $me = $i");
|
|
while (MoreSQLData()) {
|
|
my $t = FetchOneColumn();
|
|
if ($t == $id) {
|
|
print "<H1>Dependency loop detected!</H1>\n";
|
|
print "The change you are making to dependencies\n";
|
|
print "has caused a circular dependency chain.\n";
|
|
print "<p>Click <b>Back</b> and try again.\n";
|
|
exit;
|
|
}
|
|
if (!exists $seen{$t}) {
|
|
push @stack, $t;
|
|
$seen{$t} = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
my $tmp = $me;
|
|
$me = $target;
|
|
$target = $tmp;
|
|
}
|
|
}
|
|
|
|
if (@::legal_keywords) {
|
|
# There are three kinds of "keywordsaction": makeexact, add, delete.
|
|
# For makeexact, we delete everything, and then add our things.
|
|
# For add, we delete things we're adding (to make sure we don't
|
|
# end up having them twice), and then we add them.
|
|
# For delete, we just delete things on the list.
|
|
if ($keywordaction eq "makeexact") {
|
|
SendSQL("DELETE FROM keywords WHERE bug_id = $id");
|
|
}
|
|
foreach my $keyword (@keywordlist) {
|
|
if ($keywordaction ne "makeexact") {
|
|
SendSQL("DELETE FROM keywords
|
|
WHERE bug_id = $id AND keywordid = $keyword");
|
|
}
|
|
if ($keywordaction ne "delete") {
|
|
SendSQL("INSERT INTO keywords
|
|
(bug_id, keywordid) VALUES ($id, $keyword)");
|
|
}
|
|
}
|
|
}
|
|
|
|
my $query = "$basequery\nwhere bug_id = $id";
|
|
|
|
# print "<PRE>$query</PRE>\n";
|
|
|
|
if ($::comma ne "") {
|
|
SendSQL($query);
|
|
}
|
|
|
|
if (defined $::FORM{'comment'}) {
|
|
AppendComment($id, $::FORM{'who'}, $::FORM{'comment'});
|
|
}
|
|
|
|
if (defined $::FORM{'cc'} && ShowCcList($id) ne $::FORM{'cc'}) {
|
|
my %ccids;
|
|
foreach my $person (split(/[ ,]/, $::FORM{'cc'})) {
|
|
if ($person ne "") {
|
|
my $cid = DBNameToIdAndCheck($person);
|
|
$ccids{$cid} = 1;
|
|
}
|
|
}
|
|
|
|
SendSQL("delete from cc where bug_id = $id");
|
|
foreach my $ccid (keys %ccids) {
|
|
SendSQL("insert into cc (bug_id, who) values ($id, $ccid)");
|
|
}
|
|
}
|
|
|
|
SendSQL("select delta_ts from bugs where bug_id = $id");
|
|
$timestamp = FetchOneColumn();
|
|
|
|
if (defined $::FORM{'dependson'}) {
|
|
my $me = "blocked";
|
|
my $target = "dependson";
|
|
for (1..2) {
|
|
SendSQL("select $target from dependencies where $me = $id order by $target");
|
|
my %snapshot;
|
|
my @oldlist;
|
|
while (MoreSQLData()) {
|
|
push(@oldlist, FetchOneColumn());
|
|
}
|
|
my @newlist = sort {$a <=> $b} @{$deps{$target}};
|
|
@dependencychanged{@oldlist} = 1;
|
|
@dependencychanged{@newlist} = 1;
|
|
|
|
while (0 < @oldlist || 0 < @newlist) {
|
|
if (@oldlist == 0 || (@newlist > 0 &&
|
|
$oldlist[0] > $newlist[0])) {
|
|
$snapshot{$newlist[0]} = SnapShotDeps($newlist[0], $me,
|
|
$target);
|
|
shift @newlist;
|
|
} elsif (@newlist == 0 || (@oldlist > 0 &&
|
|
$newlist[0] > $oldlist[0])) {
|
|
$snapshot{$oldlist[0]} = SnapShotDeps($oldlist[0], $me,
|
|
$target);
|
|
shift @oldlist;
|
|
} else {
|
|
if ($oldlist[0] != $newlist[0]) {
|
|
die "Error in list comparing code";
|
|
}
|
|
shift @oldlist;
|
|
shift @newlist;
|
|
}
|
|
}
|
|
my @keys = keys(%snapshot);
|
|
if (@keys) {
|
|
my $oldsnap = SnapShotDeps($id, $target, $me);
|
|
SendSQL("delete from dependencies where $me = $id");
|
|
foreach my $i (@{$deps{$target}}) {
|
|
SendSQL("insert into dependencies ($me, $target) values ($id, $i)");
|
|
}
|
|
foreach my $k (@keys) {
|
|
LogDependencyActivity($k, $snapshot{$k}, $me, $target);
|
|
}
|
|
LogDependencyActivity($id, $oldsnap, $target, $me);
|
|
}
|
|
|
|
my $tmp = $me;
|
|
$me = $target;
|
|
$target = $tmp;
|
|
}
|
|
}
|
|
|
|
|
|
# get a snapshot of the newly set values out of the database,
|
|
# and then generate any necessary bug activity entries by seeing
|
|
# what has changed since before we wrote out the new values.
|
|
#
|
|
my @newvalues = SnapShotBug($id);
|
|
|
|
push(@oldvalues, $oldkeywords);
|
|
push(@newvalues, SnapShotKeywords($id));
|
|
foreach my $c (@::log_columns, "keywords") {
|
|
my $col = $c; # We modify it, don't want to modify array
|
|
# values in place.
|
|
my $old = shift @oldvalues;
|
|
my $new = shift @newvalues;
|
|
if (!defined $old) {
|
|
$old = "";
|
|
}
|
|
if (!defined $new) {
|
|
$new = "";
|
|
}
|
|
if ($old ne $new) {
|
|
if ($col eq 'assigned_to' || $col eq 'qa_contact') {
|
|
$old = DBID_to_name($old) if $old != 0;
|
|
$new = DBID_to_name($new) if $new != 0;
|
|
}
|
|
if ($col eq 'product') {
|
|
RemoveVotes($id,
|
|
"This bug has been moved to a different product");
|
|
}
|
|
$col = SqlQuote($col);
|
|
$old = SqlQuote($old);
|
|
$new = SqlQuote($new);
|
|
my $q = "insert into bugs_activity (bug_id,who,bug_when,field,oldvalue,newvalue) values ($id,$whoid,$timestamp,$col,$old,$new)";
|
|
# puts "<pre>$q</pre>"
|
|
SendSQL($q);
|
|
}
|
|
}
|
|
|
|
print "<TABLE BORDER=1><TD><H2>Changes to bug $id submitted</H2>\n";
|
|
SendSQL("unlock tables");
|
|
system("./processmail $id $::FORM{'who'}");
|
|
print "<TD><A HREF=\"show_bug.cgi?id=$id\">Back To BUG# $id</A></TABLE>\n";
|
|
|
|
foreach my $k (keys(%dependencychanged)) {
|
|
print "<TABLE BORDER=1><TD><H2>Checking for dependency changes on bug $k</H2>\n";
|
|
system("./processmail $k $::FORM{'who'}");
|
|
print "<TD><A HREF=\"show_bug.cgi?id=$k\">Go To BUG# $k</A></TABLE>\n";
|
|
}
|
|
|
|
}
|
|
|
|
if (defined $::next_bug) {
|
|
print("<P>The next bug in your list is:\n");
|
|
$::FORM{'id'} = $::next_bug;
|
|
print "<HR>\n";
|
|
|
|
navigation_header();
|
|
do "bug_form.pl";
|
|
} else {
|
|
navigation_header();
|
|
}
|