Commit 6b2eec91 authored by terry%mozilla.org's avatar terry%mozilla.org

Patch by "Matt Masson" <matthew@zeroknowledge.com> -- allow definition

of different target milestones by product.
parent c7ae4f65
......@@ -38,6 +38,7 @@ sub bug_form_pl_sillyness {
$zz = @::legal_priority;
$zz = @::legal_resolution_no_dup;
$zz = @::legal_severity;
$zz = %::target_milestone;
}
my $loginok = quietly_check_login();
......@@ -207,14 +208,11 @@ if (Param("usetargetmilestone")) {
if ($url eq "") {
$url = "notargetmilestone.html";
}
if ($bug{'target_milestone'} eq "") {
$bug{'target_milestone'} = " ";
}
push(@::legal_target_milestone, " ");
print "
<TD ALIGN=RIGHT><A href=\"$url\"><B>Target Milestone:</B></A></TD>
<TD><SELECT NAME=target_milestone>" .
make_options(\@::legal_target_milestone,
make_options($::target_milestone{$bug{'product'}},
$bug{'target_milestone'}) .
"</SELECT></TD>";
}
......
......@@ -45,6 +45,7 @@ sub sillyness {
$zz = @::legal_severity;
$zz = @::legal_target_milestone;
$zz = @::versions;
$zz = @::target_milestone;
};
my $serverpush = 0;
......@@ -1232,9 +1233,11 @@ document.write(\" <input type=button value=\\\"Uncheck All\\\" onclick=\\\"SetCh
</TR>";
if (Param("usetargetmilestone")) {
push(@::legal_target_milestone, " ");
my $tfm_popup = make_options(\@::legal_target_milestone,
$::dontchange);
my @legal_milestone;
if(1 == @prod_list) {
@legal_milestone = @{$::target_milestone{$prod_list[0]}};
}
my $tfm_popup = make_options(\@legal_milestone, $::dontchange);
print "
<TR>
<TD ALIGN=RIGHT><B>Target milestone:</B></TD>
......
......@@ -752,6 +752,12 @@ $table{keyworddefs} =
unique(name)';
$table{milestones} =
'value varchar(190) not null,
product varchar(64) not null,
sortkey smallint not null,
unique (product, value)';
$table{shadowlog} =
'id int not null auto_increment primary key,
ts timestamp,
......@@ -1493,6 +1499,44 @@ AddField('products', 'votestoconfirm', 'smallint not null');
AddField('profiles', 'blessgroupset', 'bigint not null');
# 2000-03-21 Adding a table for target milestones to
# database - matthew@zeroknowledge.com
$sth = $dbh->prepare("SELECT count(*) from milestones");
$sth->execute();
if (!($sth->fetchrow_arrayref()->[0])) {
print "Replacing blank milestones...\n";
$dbh->do("UPDATE bugs SET target_milestone = '---', delta_ts=delta_ts WHERE target_milestone = ' '");
# Populate milestone table with all exisiting values in database
$sth = $dbh->prepare("SELECT DISTINCT target_milestone, product FROM bugs");
$sth->execute();
print "Populating milestones table...\n";
my $value;
my $product;
while(($value, $product) = $sth->fetchrow_array())
{
# check if the value already exists
my $sortkey = substr($value, 1);
if ($sortkey !~ /^\d+$/) {
$sortkey = 0;
} else {
$sortkey *= 10;
}
$value = $dbh->quote($value);
$product = $dbh->quote($product);
my $s2 = $dbh->prepare("SELECT value FROM milestones WHERE value = $value AND product = $product");
$s2->execute();
if(!$s2->fetchrow_array())
{
$dbh->do("INSERT INTO milestones(value, product, sortkey) VALUES($value, $product, $sortkey)");
}
}
}
#
# If you had to change the --TABLE-- definition in any way, then add your
# differential change code *** A B O V E *** this comment.
......
#!/usr/bonsaitools/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# This is a script to edit the target milestones. It is largely a copy of
# the editversions.cgi script, since the two fields were set up in a
# very similar fashion.
#
# (basically replace each occurance of 'milestone' with 'version', and
# you'll have the original script)
#
# Matt Masson <matthew@zeroknowledge.com>
#
use diagnostics;
use strict;
require "CGI.pl";
require "globals.pl";
# TestProduct: just returns if the specified product does exists
# CheckProduct: same check, optionally emit an error text
# TestMilestone: just returns if the specified product/version combination exists
# CheckMilestone: same check, optionally emit an error text
sub TestProduct ($)
{
my $prod = shift;
# does the product exist?
SendSQL("SELECT product
FROM products
WHERE product=" . SqlQuote($prod));
return FetchOneColumn();
}
sub CheckProduct ($)
{
my $prod = shift;
# do we have a product?
unless ($prod) {
print "Sorry, you haven't specified a product.";
PutTrailer();
exit;
}
unless (TestProduct $prod) {
print "Sorry, product '$prod' does not exist.";
PutTrailer();
exit;
}
}
sub TestMilestone ($$)
{
my ($prod,$mile) = @_;
# does the product exist?
SendSQL("SELECT product,value
FROM milestones
WHERE product=" . SqlQuote($prod) . " and value=" . SqlQuote($mile));
return FetchOneColumn();
}
sub CheckMilestone ($$)
{
my ($prod,$mile) = @_;
# do we have the milestone?
unless ($mile) {
print "Sorry, you haven't specified a milestone.";
PutTrailer();
exit;
}
CheckProduct($prod);
unless (TestMilestone $prod,$mile) {
print "Sorry, milestone '$mile' for product '$prod' does not exist.";
PutTrailer();
exit;
}
}
#
# Displays the form to edit a milestone
#
sub EmitFormElements ($$$)
{
my ($product, $milestone, $sortkey) = @_;
print " <TH ALIGN=\"right\">Milestone:</TH>\n";
print " <TD><INPUT SIZE=64 MAXLENGTH=64 NAME=\"milestone\" VALUE=\"" .
value_quote($milestone) . "\">\n";
print "</TR><TR>\n";
print " <TH ALIGN=\"right\">Sortkey:</TH>\n";
print " <TD><INPUT SIZE=64 MAXLENGTH=64 NAME=\"sortkey\" VALUE=\"" .
value_quote($sortkey) . "\">\n";
print " <INPUT TYPE=HIDDEN NAME=\"product\" VALUE=\"" .
value_quote($product) . "\"></TD>\n";
}
#
# Displays a text like "a.", "a or b.", "a, b or c.", "a, b, c or d."
#
sub PutTrailer (@)
{
my (@links) = ("Back to the <A HREF=\"query.cgi\">query page</A>", @_);
my $count = $#links;
my $num = 0;
print "<P>\n";
foreach (@links) {
print $_;
if ($num == $count) {
print ".\n";
}
elsif ($num == $count-1) {
print " or ";
}
else {
print ", ";
}
$num++;
}
PutFooter();
}
#
# Preliminary checks:
#
confirm_login();
print "Content-type: text/html\n\n";
unless (UserInGroup("editcomponents")) {
PutHeader("Not allowed");
print "Sorry, you aren't a member of the 'editcomponents' group.\n";
print "And so, you aren't allowed to add, modify or delete milestones.\n";
PutTrailer();
exit;
}
#
# often used variables
#
my $product = trim($::FORM{product} || '');
my $milestone = trim($::FORM{milestone} || '');
my $sortkey = trim($::FORM{sortkey} || '0');
my $action = trim($::FORM{action} || '');
my $localtrailer;
if ($milestone) {
$localtrailer = "<A HREF=\"editmilestones.cgi?product=" . url_quote($product) . "\">edit</A> more milestones";
} else {
$localtrailer = "<A HREF=\"editmilestones.cgi\">edit</A> more milestones";
}
#
# product = '' -> Show nice list of milestones
#
unless ($product) {
PutHeader("Select product");
SendSQL("SELECT products.product,products.description,'xyzzy'
FROM products
GROUP BY products.product
ORDER BY products.product");
print "<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0><TR BGCOLOR=\"#6666FF\">\n";
print " <TH ALIGN=\"left\">Edit milestones of ...</TH>\n";
print " <TH ALIGN=\"left\">Description</TH>\n";
print " <TH ALIGN=\"left\">Bugs</TH>\n";
print "</TR>";
while ( MoreSQLData() ) {
my ($product, $description, $bugs) = FetchSQLData();
$description ||= "<FONT COLOR=\"red\">missing</FONT>";
$bugs ||= "none";
print "<TR>\n";
print " <TD VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product=", url_quote($product), "\"><B>$product</B></A></TD>\n";
print " <TD VALIGN=\"top\">$description</TD>\n";
print " <TD VALIGN=\"top\">$bugs</TD>\n";
}
print "</TR></TABLE>\n";
PutTrailer();
exit;
}
#
# action='' -> Show nice list of milestones
#
unless ($action) {
PutHeader("Select milestone");
CheckProduct($product);
SendSQL("SELECT value,sortkey
FROM milestones
WHERE product=" . SqlQuote($product) . "
ORDER BY sortkey,value");
print "<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0><TR BGCOLOR=\"#6666FF\">\n";
print " <TH ALIGN=\"left\">Edit milestone ...</TH>\n";
#print " <TH ALIGN=\"left\">Bugs</TH>\n";
print " <TH ALIGN=\"left\">Sortkey</TH>\n";
print " <TH ALIGN=\"left\">Action</TH>\n";
print "</TR>";
while ( MoreSQLData() ) {
my ($milestone,$sortkey,$bugs) = FetchSQLData();
$bugs ||= 'none';
print "<TR>\n";
print " <TD VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product=", url_quote($product), "&milestone=", url_quote($milestone), "&action=edit\"><B>$milestone</B></A></TD>\n";
#print " <TD VALIGN=\"top\">$bugs</TD>\n";
print " <TD VALIGN=\"top\" ALIGN=\"right\">$sortkey</TD>\n";
print " <TD VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product=", url_quote($product), "&milestone=", url_quote($milestone), "&action=del\"><B>Delete</B></A></TD>\n";
print "</TR>";
}
print "<TR>\n";
print " <TD VALIGN=\"top\" COLSPAN=\"2\">Add a new milestone</TD>\n";
print " <TD VALIGN=\"top\" ALIGN=\"middle\"><A HREF=\"editmilestones.cgi?product=", url_quote($product) . "&action=add\">Add</A></TD>\n";
print "</TR></TABLE>\n";
PutTrailer();
exit;
}
#
# action='add' -> present form for parameters for new milestone
#
# (next action will be 'new')
#
if ($action eq 'add') {
PutHeader("Add milestone");
CheckProduct($product);
#print "This page lets you add a new milestone to a $::bugzilla_name tracked product.\n";
print "<FORM METHOD=POST ACTION=editmilestones.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
EmitFormElements($product, $milestone, 0);
print "</TABLE>\n<HR>\n";
print "<INPUT TYPE=SUBMIT VALUE=\"Add\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"new\">\n";
print "</FORM>";
my $other = $localtrailer;
$other =~ s/more/other/;
PutTrailer($other);
exit;
}
#
# action='new' -> add milestone entered in the 'action=add' screen
#
if ($action eq 'new') {
PutHeader("Adding new milestone");
CheckProduct($product);
# Cleanups and valididy checks
unless ($milestone) {
print "You must enter a text for the new milestone. Please press\n";
print "<b>Back</b> and try again.\n";
PutTrailer($localtrailer);
exit;
}
if (TestMilestone($product,$milestone)) {
print "The milestone '$milestone' already exists. Please press\n";
print "<b>Back</b> and try again.\n";
PutTrailer($localtrailer);
exit;
}
# Add the new milestone
SendSQL("INSERT INTO milestones ( " .
"value, product, sortkey" .
" ) VALUES ( " .
SqlQuote($milestone) . "," .
SqlQuote($product) . ", $sortkey)");
# Make versioncache flush
unlink "data/versioncache";
print "OK, done.<p>\n";
PutTrailer($localtrailer);
exit;
}
#
# action='del' -> ask if user really wants to delete
#
# (next action would be 'delete')
#
if ($action eq 'del') {
PutHeader("Delete milestone");
CheckMilestone($product, $milestone);
SendSQL("SELECT count(bug_id),product,target_milestone
FROM bugs
GROUP BY product,target_milestone
HAVING product=" . SqlQuote($product) . "
AND target_milestone=" . SqlQuote($milestone));
my $bugs = FetchOneColumn();
print "<TABLE BORDER=1 CELLPADDING=4 CELLSPACING=0>\n";
print "<TR BGCOLOR=\"#6666FF\">\n";
print " <TH VALIGN=\"top\" ALIGN=\"left\">Part</TH>\n";
print " <TH VALIGN=\"top\" ALIGN=\"left\">Value</TH>\n";
print "</TR><TR>\n";
print " <TH ALIGN=\"left\" VALIGN=\"top\">Product:</TH>\n";
print " <TD VALIGN=\"top\">$product</TD>\n";
print "</TR><TR>\n";
print " <TH ALIGN=\"left\" VALIGN=\"top\">Milestone:</TH>\n";
print " <TD VALIGN=\"top\">$milestone</TD>\n";
print "</TR><TR>\n";
print " <TH ALIGN=\"left\" VALIGN=\"top\">Bugs:</TH>\n";
print " <TD VALIGN=\"top\">", $bugs || 'none' , "</TD>\n";
print "</TR></TABLE>\n";
print "<H2>Confirmation</H2>\n";
if ($bugs) {
if (!Param("allowbugdeletion")) {
print "Sorry, there are $bugs bugs outstanding for this milestone.
You must reassign those bugs to another milestone before you can delete this
one.";
PutTrailer($localtrailer);
exit;
}
print "<TABLE BORDER=0 CELLPADDING=20 WIDTH=\"70%\" BGCOLOR=\"red\"><TR><TD>\n",
"There are bugs entered for this milestone! When you delete this ",
"milestone, <B><BLINK>all</BLINK></B> stored bugs will be deleted, too. ",
"You could not even see the bug history for this milestone anymore!\n",
"</TD></TR></TABLE>\n";
}
print "<P>Do you really want to delete this milestone?<P>\n";
print "<FORM METHOD=POST ACTION=editmilestones.cgi>\n";
print "<INPUT TYPE=SUBMIT VALUE=\"Yes, delete\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"delete\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"product\" VALUE=\"" .
value_quote($product) . "\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"milestone\" VALUE=\"" .
value_quote($milestone) . "\">\n";
print "</FORM>";
PutTrailer($localtrailer);
exit;
}
#
# action='delete' -> really delete the milestone
#
if ($action eq 'delete') {
PutHeader("Deleting milestone");
CheckMilestone($product,$milestone);
# lock the tables before we start to change everything:
SendSQL("LOCK TABLES attachments WRITE,
bugs WRITE,
bugs_activity WRITE,
milestones WRITE,
dependencies WRITE");
# According to MySQL doc I cannot do a DELETE x.* FROM x JOIN Y,
# so I have to iterate over bugs and delete all the indivial entries
# in bugs_activies and attachments.
if (Param("allowbugdeletion")) {
SendSQL("SELECT bug_id
FROM bugs
WHERE product=" . SqlQuote($product) . "
AND target_milestone=" . SqlQuote($milestone));
while (MoreSQLData()) {
my $bugid = FetchOneColumn();
my $query =
$::db->query("DELETE FROM attachments WHERE bug_id=$bugid")
or die "$::db_errstr";
$query =
$::db->query("DELETE FROM bugs_activity WHERE bug_id=$bugid")
or die "$::db_errstr";
$query =
$::db->query("DELETE FROM dependencies WHERE blocked=$bugid")
or die "$::db_errstr";
}
print "Attachments, bug activity and dependencies deleted.<BR>\n";
# Deleting the rest is easier:
SendSQL("DELETE FROM bugs
WHERE product=" . SqlQuote($product) . "
AND target_milestone=" . SqlQuote($milestone));
print "Bugs deleted.<BR>\n";
}
SendSQL("DELETE FROM milestones
WHERE product=" . SqlQuote($product) . "
AND value=" . SqlQuote($milestone));
print "Milestone deleted.<P>\n";
SendSQL("UNLOCK TABLES");
unlink "data/versioncache";
PutTrailer($localtrailer);
exit;
}
#
# action='edit' -> present the edit milestone form
#
# (next action would be 'update')
#
if ($action eq 'edit') {
PutHeader("Edit milestone");
CheckMilestone($product,$milestone);
SendSQL("SELECT sortkey FROM milestones WHERE product=" .
SqlQuote($product) . " AND value = " . SqlQuote($milestone));
my $sortkey = FetchOneColumn();
print "<FORM METHOD=POST ACTION=editmilestones.cgi>\n";
print "<TABLE BORDER=0 CELLPADDING=4 CELLSPACING=0><TR>\n";
EmitFormElements($product, $milestone, $sortkey);
print "</TR></TABLE>\n";
print "<INPUT TYPE=HIDDEN NAME=\"milestoneold\" VALUE=\"" .
value_quote($milestone) . "\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"sortkeyold\" VALUE=\"" .
value_quote($sortkey) . "\">\n";
print "<INPUT TYPE=HIDDEN NAME=\"action\" VALUE=\"update\">\n";
print "<INPUT TYPE=SUBMIT VALUE=\"Update\">\n";
print "</FORM>";
my $other = $localtrailer;
$other =~ s/more/other/;
PutTrailer($other);
exit;
}
#
# action='update' -> update the milestone
#
if ($action eq 'update') {
PutHeader("Update milestone");
my $milestoneold = trim($::FORM{milestoneold} || '');
my $sortkeyold = trim($::FORM{sortkeyold} || '0');
CheckMilestone($product,$milestoneold);
SendSQL("LOCK TABLES bugs WRITE,
milestones WRITE");
if ($milestone ne $milestoneold) {
unless ($milestone) {
print "Sorry, I can't delete the milestone text.";
PutTrailer($localtrailer);
SendSQL("UNLOCK TABLES");
exit;
}
if (TestMilestone($product,$milestone)) {
print "Sorry, milestone '$milestone' is already in use.";
PutTrailer($localtrailer);
SendSQL("UNLOCK TABLES");
exit;
}
SendSQL("UPDATE bugs
SET target_milestone=" . SqlQuote($milestone) . "
WHERE target_milestone=" . SqlQuote($milestoneold) . "
AND product=" . SqlQuote($product));
SendSQL("UPDATE milestones
SET value=" . SqlQuote($milestone) . "
WHERE product=" . SqlQuote($product) . "
AND value=" . SqlQuote($milestoneold));
unlink "data/versioncache";
print "Updated milestone.<BR>\n";
}
if ($sortkey != $sortkeyold) {
SendSQL("UPDATE milestones SET sortkey=$sortkey
WHERE product=" . SqlQuote($product) . "
AND value=" . SqlQuote($milestoneold));
unlink "data/versioncache";
print "Updated sortkey.<BR>\n";
}
SendSQL("UNLOCK TABLES");
PutTrailer($localtrailer);
exit;
}
#
# No valid action found
#
PutHeader("Error");
print "I don't have a clue what you want.<BR>\n";
foreach ( sort keys %::FORM) {
print "$_: $::FORM{$_}<BR>\n";
}
......@@ -485,6 +485,29 @@ if ($action eq 'del') {
print "<FONT COLOR=\"red\">missing</FONT>";
}
#
# Adding listing for associated target milestones - matthew@zeroknowledge.com
#
if (Param('usetargetmilestone')) {
print "</TD>\n</TR><TR>\n";
print " <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product=", url_quote($product), "\">Edit milestones:</A></TH>\n";
print " <TD>";
SendSQL("SELECT value
FROM milestones
WHERE product=" . SqlQuote($product) . "
ORDER BY sortkey,value");
if(MoreSQLData()) {
my $br = 0;
while ( MoreSQLData() ) {
my ($milestone) = FetchSQLData();
print "<BR>" if $br;
print $milestone;
$br = 1;
}
} else {
print "<FONT COLOR=\"red\">missing</FONT>";
}
}
print "</TD>\n</TR><TR>\n";
print " <TD VALIGN=\"top\">Bugs:</TD>\n";
......@@ -548,7 +571,8 @@ if ($action eq 'delete') {
versions WRITE,
products WRITE,
groups WRITE,
profiles WRITE");
profiles WRITE,
milestones WRITE");
# According to MySQL doc I cannot do a DELETE x.* FROM x JOIN Y,
# so I have to iterate over bugs and delete all the indivial entries
......@@ -589,6 +613,11 @@ if ($action eq 'delete') {
WHERE program=" . SqlQuote($product));
print "Versions deleted.<P>\n";
# deleting associated target milestones - matthew@zeroknowledge.com
SendSQL("DELETE FROM milestones
WHERE product=" . SqlQuote($product));
print "Milestones deleted.<BR>\n";
SendSQL("DELETE FROM products
WHERE product=" . SqlQuote($product));
print "Product '$product' deleted.<BR>\n";
......@@ -700,6 +729,29 @@ if ($action eq 'edit') {
print "<FONT COLOR=\"red\">missing</FONT>";
}
#
# Adding listing for associated target milestones - matthew@zeroknowledge.com
#
if (Param('usetargetmilestone')) {
print "</TD>\n</TR><TR>\n";
print " <TH ALIGN=\"right\" VALIGN=\"top\"><A HREF=\"editmilestones.cgi?product=", url_quote($product), "\">Edit milestones:</A></TH>\n";
print " <TD>";
SendSQL("SELECT value
FROM milestones
WHERE product=" . SqlQuote($product) . "
ORDER BY sortkey,value");
if(MoreSQLData()) {
my $br = 0;
while ( MoreSQLData() ) {
my ($milestone) = FetchSQLData();
print "<BR>" if $br;
print $milestone;
$br = 1;
}
} else {
print "<FONT COLOR=\"red\">missing</FONT>";
}
}
print "</TD>\n</TR><TR>\n";
print " <TH ALIGN=\"right\">Bugs:</TH>\n";
......@@ -782,7 +834,8 @@ if ($action eq 'update') {
products WRITE,
versions WRITE,
groups WRITE,
profiles WRITE");
profiles WRITE,
milestones WRITE");
if ($disallownew ne $disallownewold) {
$disallownew ||= 0;
......@@ -923,6 +976,7 @@ if ($action eq 'update') {
SendSQL("UPDATE components SET program=$qp WHERE program=$qpold");
SendSQL("UPDATE products SET product=$qp WHERE product=$qpold");
SendSQL("UPDATE versions SET program=$qp WHERE program=$qpold");
SendSQL("UPDATE milestones SET product=$qp WHERE product=$qpold");
# Need to do an update to groups as well. If there is a corresponding
# bug group, whether usebuggroups is currently set or not, we want to
# update it so it will match in the future. If there is no group, this
......
......@@ -260,7 +260,23 @@ sub Version_element {
return make_popup("version", $versionlist, $defversion, 1, $onchange);
}
sub Milestone_element {
my ($tm, $prod, $onchange) = (@_);
my $tmlist;
if (!defined $::target_milestone{$prod}) {
$tmlist = [];
} else {
$tmlist = $::target_milestone{$prod};
}
my $deftm = $tmlist->[0];
if (lsearch($tmlist, $tm) >= 0) {
$deftm = $tm;
}
return make_popup("target_milestone", $tmlist, $deftm, 1, $onchange);
}
# Generate a string which, when later interpreted by the Perl compiler, will
# be the same as the given string.
......@@ -427,11 +443,24 @@ sub GenerateVersionTable {
print FID GenerateCode('$::anyvotesallowed');
if ($dotargetmilestone) {
my $last = Param("nummilestones");
my $i;
for ($i=1 ; $i<=$last ; $i++) {
push(@::legal_target_milestone, "M$i");
# reading target milestones in from the database - matthew@zeroknowledge.com
SendSQL("SELECT value, product FROM milestones ORDER BY sortkey, value");
my @line;
my %tmarray;
@::legal_target_milestone = ();
while(@line = FetchSQLData()) {
my ($tm, $pr) = (@line);
if (!defined $::target_milestone{$pr}) {
$::target_milestone{$pr} = [];
}
push @{$::target_milestone{$pr}}, $tm;
if (!exists $tmarray{$tm}) {
$tmarray{$tm} = 1;
push(@::legal_target_milestone, $tm);
}
}
print FID GenerateCode('%::target_milestone');
print FID GenerateCode('@::legal_target_milestone');
print FID GenerateCode('%::milestoneurl');
}
......
......@@ -39,6 +39,7 @@ use vars %::versions,
%::legal_opsys,
%::legal_platform,
%::legal_priority,
%::target_milestone,
%::legal_severity;
my $whoid = confirm_login();
......@@ -53,6 +54,11 @@ if ( Param("strictvaluechecks") ) {
CheckFormFieldDefined(\%::FORM, 'product');
CheckFormFieldDefined(\%::FORM, 'version');
CheckFormFieldDefined(\%::FORM, 'component');
# check if target milestone is defined - matthew@zeroknowledge.com
if ( Param("usetargetmilestone") ) {
CheckFormFieldDefined(\%::FORM, 'target_milestone');
}
}
if ($::FORM{'product'} ne $::dontchange) {
......@@ -71,12 +77,18 @@ if ($::FORM{'product'} ne $::dontchange) {
#
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";
my $mok = 1; # so it won't affect the 'if' statement if milestones aren't used
if ( Param("usetargetmilestone") ) {
$mok = lsearch($::target_milestone{$prod}, $::FORM{'target_milestone'}) >= 0;
}
if (!$vok || !$cok || !$mok) {
print "<H1>Changing product means changing version, target milestone and component.</H1>\n";
print "You have chosen a new product, and now the version, target milestone 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 "not have a valid target milestone, component or version field in the first place.)\n";
print "Anyway, please set the version, target milestone and component now.<p>\n";
print "<form>\n";
print "<table>\n";
print "<tr>\n";
......@@ -86,12 +98,19 @@ if ($::FORM{'product'} ne $::dontchange) {
print "<td align=right><b>Version:</b></td>\n";
print "<td>" . Version_element($::FORM{'version'}, $prod) . "</td>\n";
print "</tr><tr>\n";
if ( Param("usetargetmilestone") ) {
print "<td align=right><b>Target Milestone:</b></td>\n";
print "<td>" . Milestone_element($::FORM{'target_milestone'}, $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') {
if ($i ne 'version' && $i ne 'component' && $i ne 'target_milestone') {
print "<input type=hidden name=$i value=\"" .
value_quote($::FORM{$i}) . "\">\n";
}
......
......@@ -282,12 +282,14 @@ my $jscript = << 'ENDSCRIPT';
<!--
var cpts = new Array();
var vers = new Array();
var tms = new Array();
ENDSCRIPT
my $p;
my $v;
my $c;
my $m;
my $i = 0;
my $j = 0;
......@@ -299,6 +301,10 @@ foreach $v (@::legal_versions) {
$jscript .= "vers['$v'] = new Array();\n";
}
my $tm;
foreach $tm (@::legal_target_milestone) {
$jscript .= "tms['$tm'] = new Array();\n";
}
for $p (@::legal_product) {
if ($::components{$p}) {
......@@ -312,6 +318,12 @@ for $p (@::legal_product) {
$jscript .= "vers['$v'][vers['$v'].length] = '$p';\n";
}
}
if ($::target_milestone{$p}) {
foreach $m (@{$::target_milestone{$p}}) {
$jscript .= "tms['$m'][tms['$m'].length] = '$p';\n";
}
}
}
$i = 0;
......@@ -404,8 +416,39 @@ function selectProduct(f) {
}
}
var tmsel = new Array();
for (i=0 ; i<f.target_milestone.length ; i++) {
if (f.target_milestone[i].selected) {
tmsel[f.target_milestone[i].value] = 1;
}
}
f.target_milestone.options.length = 0;
for (tm in tms) {
if (typeof(tms[v]) == 'function') continue;
var doit = doall;
for (i=0 ; !doit && i<f.product.length ; i++) {
if (f.product[i].selected) {
var p = f.product[i].value;
for (j in tms[tm]) {
if (typeof(tms[tm][j]) == 'function') continue;
var p2 = tms[tm][j];
if (p2 == p) {
doit = true;
break;
}
}
}
}
if (doit) {
var l = f.target_milestone.length;
f.target_milestone[l] = new Option(tm, tm);
if (tmsel[tm]) {
f.target_milestone[l].selected = true;
}
}
}
}
// -->
......@@ -431,7 +474,6 @@ PutHeader("Bugzilla Query Page", "Query",
0, $jscript);
push @::legal_resolution, "---"; # Oy, what a hack.
push @::legal_target_milestone, "---"; # Oy, what a hack.
my @logfields = ("[Bug creation]", @::log_columns);
......
......@@ -194,6 +194,25 @@ foreach my $ref (@checklist) {
}
}
# Adding check for Target Milestones / products - matthew@zeroknowledge.com
Status("Checking milestone/products");
@checklist = ();
SendSQL("select distinct product, target_milestone from bugs");
while (@row = FetchSQLData()) {
my @copy = @row;
push(@checklist, \@copy);
}
foreach my $ref (@checklist) {
my ($product, $milestone) = (@$ref);
SendSQL("SELECT count(*) FROM milestones WHERE product = '$product' AND value = '$milestone'");
if(FetchOneColumn() != 1) {
Alert("Bug(s) found with invalud product/milestone: $product/$milestone");
}
}
Status("Checking components/products");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment