Bug 86328: Deleting bugs doesn't delete dependent records properly - Patch by Frederic Buclin <LpSolit@gmail.com> r=wurblzap a=justdave
This commit is contained in:
Родитель
bad96f0f9d
Коммит
a2c3e919ac
|
@ -23,6 +23,7 @@
|
|||
# Bradley Baetz <bbaetz@acm.org>
|
||||
# Dave Miller <justdave@bugzilla.org>
|
||||
# Max Kanat-Alexander <mkanat@kerio.com>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
|
||||
package Bugzilla::Bug;
|
||||
|
||||
|
@ -217,6 +218,60 @@ sub initBug {
|
|||
return $self;
|
||||
}
|
||||
|
||||
# This is the correct way to delete bugs from the DB.
|
||||
# No bug should be deleted from anywhere else except from here.
|
||||
#
|
||||
sub remove_from_db {
|
||||
my ($self) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
if ($self->{'error'}) {
|
||||
ThrowCodeError("bug_error", { bug => $self });
|
||||
}
|
||||
|
||||
my $bug_id = $self->{'bug_id'};
|
||||
|
||||
# tables having 'bugs.bug_id' as a foreign key:
|
||||
# - attachments
|
||||
# - bug_group_map
|
||||
# - bugs
|
||||
# - bugs_activity
|
||||
# - cc
|
||||
# - dependencies
|
||||
# - duplicates
|
||||
# - flags
|
||||
# - keywords
|
||||
# - longdescs
|
||||
# - votes
|
||||
|
||||
$dbh->bz_lock_tables('attachments WRITE', 'bug_group_map WRITE',
|
||||
'bugs WRITE', 'bugs_activity WRITE', 'cc WRITE',
|
||||
'dependencies WRITE', 'duplicates WRITE',
|
||||
'flags WRITE', 'keywords WRITE',
|
||||
'longdescs WRITE', 'votes WRITE');
|
||||
|
||||
$dbh->do("DELETE FROM bug_group_map WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM bugs_activity WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM cc WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM dependencies WHERE blocked = ? OR dependson = ?",
|
||||
undef, ($bug_id, $bug_id));
|
||||
$dbh->do("DELETE FROM duplicates WHERE dupe = ? OR dupe_of = ?",
|
||||
undef, ($bug_id, $bug_id));
|
||||
$dbh->do("DELETE FROM flags WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM keywords WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM longdescs WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM votes WHERE bug_id = ?", undef, $bug_id);
|
||||
# Several of the previous tables also depend on attach_id.
|
||||
$dbh->do("DELETE FROM attachments WHERE bug_id = ?", undef, $bug_id);
|
||||
$dbh->do("DELETE FROM bugs WHERE bug_id = ?", undef, $bug_id);
|
||||
|
||||
$dbh->bz_unlock_tables();
|
||||
|
||||
# Now this bug no longer exists
|
||||
$self->DESTROY;
|
||||
return $self;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Accessors
|
||||
#####################################################################
|
||||
|
|
|
@ -112,7 +112,8 @@ sub CheckComponent ($$)
|
|||
# Preliminary checks:
|
||||
#
|
||||
|
||||
Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $user = Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $whoid = $user->id;
|
||||
|
||||
print Bugzilla->cgi->header();
|
||||
|
||||
|
@ -436,57 +437,36 @@ if ($action eq 'del') {
|
|||
#
|
||||
|
||||
if ($action eq 'delete') {
|
||||
|
||||
CheckComponent($product, $component);
|
||||
my $component_id = get_component_id(get_product_id($product),$component);
|
||||
my $component_id = get_component_id(get_product_id($product), $component);
|
||||
|
||||
# lock the tables before we start to change everything:
|
||||
my $bug_ids =
|
||||
$dbh->selectcol_arrayref("SELECT bug_id FROM bugs WHERE component_id = ?",
|
||||
undef, $component_id);
|
||||
|
||||
$dbh->bz_lock_tables('attachments WRITE',
|
||||
'bugs WRITE',
|
||||
'bugs_activity WRITE',
|
||||
'components WRITE',
|
||||
'dependencies WRITE',
|
||||
'flaginclusions WRITE',
|
||||
'flagexclusions 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")) {
|
||||
my $deleted_bug_count = 0;
|
||||
|
||||
SendSQL("SELECT bug_id
|
||||
FROM bugs
|
||||
WHERE component_id = $component_id");
|
||||
while (MoreSQLData()) {
|
||||
my $bugid = FetchOneColumn();
|
||||
|
||||
PushGlobalSQLState();
|
||||
SendSQL("DELETE FROM attachments WHERE bug_id=$bugid");
|
||||
SendSQL("DELETE FROM bugs_activity WHERE bug_id=$bugid");
|
||||
SendSQL("DELETE FROM dependencies WHERE blocked=$bugid");
|
||||
PopGlobalSQLState();
|
||||
|
||||
$deleted_bug_count++;
|
||||
my $nb_bugs = scalar(@$bug_ids);
|
||||
if ($nb_bugs) {
|
||||
if (Param("allowbugdeletion")) {
|
||||
foreach my $bug_id (@$bug_ids) {
|
||||
my $bug = new Bugzilla::Bug($bug_id, $whoid);
|
||||
$bug->remove_from_db();
|
||||
}
|
||||
}
|
||||
else {
|
||||
ThrowUserError("component_has_bugs", { nb => $nb_bugs });
|
||||
}
|
||||
|
||||
$vars->{'deleted_bug_count'} = $deleted_bug_count;
|
||||
|
||||
# Deleting the rest is easier:
|
||||
|
||||
SendSQL("DELETE FROM bugs
|
||||
WHERE component_id=$component_id");
|
||||
}
|
||||
|
||||
SendSQL("DELETE FROM flaginclusions
|
||||
WHERE component_id=$component_id");
|
||||
SendSQL("DELETE FROM flagexclusions
|
||||
WHERE component_id=$component_id");
|
||||
|
||||
SendSQL("DELETE FROM components
|
||||
WHERE id=$component_id");
|
||||
$vars->{'deleted_bug_count'} = $nb_bugs;
|
||||
|
||||
$dbh->bz_lock_tables('components WRITE', 'flaginclusions WRITE',
|
||||
'flagexclusions WRITE');
|
||||
|
||||
$dbh->do("DELETE FROM flaginclusions WHERE component_id = ?",
|
||||
undef, $component_id);
|
||||
$dbh->do("DELETE FROM flagexclusions WHERE component_id = ?",
|
||||
undef, $component_id);
|
||||
$dbh->do("DELETE FROM components WHERE id = ?", undef, $component_id);
|
||||
|
||||
$dbh->bz_unlock_tables();
|
||||
|
||||
|
@ -494,10 +474,8 @@ if ($action eq 'delete') {
|
|||
|
||||
$vars->{'name'} = $component;
|
||||
$vars->{'product'} = $product;
|
||||
$template->process("admin/components/deleted.html.tmpl",
|
||||
$vars)
|
||||
$template->process("admin/components/deleted.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# Matt Masson <matthew@zeroknowledge.com>
|
||||
#
|
||||
# Contributors : Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
#
|
||||
|
||||
|
||||
|
@ -119,7 +120,8 @@ sub CheckMilestone ($$)
|
|||
# Preliminary checks:
|
||||
#
|
||||
|
||||
Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $user = Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $whoid = $user->id;
|
||||
|
||||
print Bugzilla->cgi->header();
|
||||
|
||||
|
@ -304,39 +306,31 @@ if ($action eq 'new') {
|
|||
#
|
||||
|
||||
if ($action eq 'del') {
|
||||
|
||||
CheckMilestone($product, $milestone);
|
||||
my $product_id = get_product_id($product);
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
my $sth = $dbh->prepare('SELECT count(bug_id), product_id, target_milestone
|
||||
FROM bugs ' .
|
||||
$dbh->sql_group_by('product_id,
|
||||
target_milestone') . '
|
||||
HAVING product_id = ?
|
||||
AND target_milestone = ?');
|
||||
$vars->{'default_milestone'} =
|
||||
$dbh->selectrow_array('SELECT defaultmilestone
|
||||
FROM products WHERE id = ?',
|
||||
undef, $product_id);
|
||||
|
||||
trick_taint($milestone);
|
||||
$vars->{'bug_count'} = $dbh->selectrow_array($sth,
|
||||
undef,
|
||||
$product_id,
|
||||
$milestone) || 0;
|
||||
|
||||
$sth = $dbh->prepare('SELECT defaultmilestone
|
||||
FROM products
|
||||
WHERE id = ?');
|
||||
|
||||
$vars->{'default_milestone'} = $dbh->selectrow_array($sth,
|
||||
undef,
|
||||
$product_id) || '';
|
||||
|
||||
$vars->{'name'} = $milestone;
|
||||
$vars->{'product'} = $product;
|
||||
$template->process("admin/milestones/confirm-delete.html.tmpl",
|
||||
$vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
|
||||
# The default milestone cannot be deleted.
|
||||
if ($vars->{'default_milestone'} eq $milestone) {
|
||||
ThrowUserError("milestone_is_default", $vars);
|
||||
}
|
||||
|
||||
$vars->{'bug_count'} =
|
||||
$dbh->selectrow_array("SELECT COUNT(bug_id) FROM bugs
|
||||
WHERE product_id = ? AND target_milestone = ?",
|
||||
undef, ($product_id, $milestone)) || 0;
|
||||
|
||||
$template->process("admin/milestones/confirm-delete.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -347,88 +341,52 @@ if ($action eq 'del') {
|
|||
#
|
||||
|
||||
if ($action eq 'delete') {
|
||||
|
||||
CheckMilestone($product,$milestone);
|
||||
CheckMilestone($product, $milestone);
|
||||
my $product_id = get_product_id($product);
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
# lock the tables before we start to change everything:
|
||||
my $default_milestone =
|
||||
$dbh->selectrow_array("SELECT defaultmilestone
|
||||
FROM products WHERE id = ?",
|
||||
undef, $product_id);
|
||||
|
||||
$dbh->bz_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.
|
||||
|
||||
# Detaint this here, as we may need it if deleting bugs, but will
|
||||
# definitely need it detainted whhen we actually delete the
|
||||
# milestone itself
|
||||
trick_taint($milestone);
|
||||
$vars->{'name'} = $milestone;
|
||||
$vars->{'product'} = $product;
|
||||
|
||||
if (Param("allowbugdeletion")) {
|
||||
|
||||
my $deleted_bug_count = 0;
|
||||
|
||||
my $sth = $dbh->prepare_cached('SELECT bug_id
|
||||
FROM bugs
|
||||
WHERE product_id = ?
|
||||
AND target_milestone = ?');
|
||||
|
||||
my $data = $dbh->selectall_arrayref($sth,
|
||||
undef,
|
||||
$product_id,
|
||||
$milestone);
|
||||
|
||||
foreach my $aref (@$data) {
|
||||
|
||||
my ($bugid) = @$aref;
|
||||
|
||||
$dbh->do('DELETE FROM attachments WHERE bug_id = ?',
|
||||
undef,
|
||||
$bugid);
|
||||
$dbh->do('DELETE FROM bugs_activity WHERE bug_id = ?',
|
||||
undef,
|
||||
$bugid);
|
||||
$dbh->do('DELETE FROM dependencies WHERE blocked = ?',
|
||||
undef,
|
||||
$bugid);
|
||||
|
||||
$deleted_bug_count++;
|
||||
}
|
||||
|
||||
$vars->{'deleted_bug_count'} = $deleted_bug_count;
|
||||
|
||||
# Deleting the rest is easier:
|
||||
|
||||
$dbh->do('DELETE FROM bugs
|
||||
WHERE product_id = ?
|
||||
AND target_milestone = ?',
|
||||
undef,
|
||||
$product_id,
|
||||
$milestone);
|
||||
# The default milestone cannot be deleted.
|
||||
if ($milestone eq $default_milestone) {
|
||||
ThrowUserError("milestone_is_default", $vars);
|
||||
}
|
||||
|
||||
$dbh->do('DELETE FROM milestones
|
||||
WHERE product_id = ?
|
||||
AND value = ?',
|
||||
undef,
|
||||
$product_id,
|
||||
$milestone);
|
||||
# We don't want to delete bugs when deleting a milestone.
|
||||
# Bugs concerned are reassigned to the default milestone.
|
||||
my $bug_ids =
|
||||
$dbh->selectcol_arrayref("SELECT bug_id FROM bugs
|
||||
WHERE product_id = ? AND target_milestone = ?",
|
||||
undef, ($product_id, $milestone));
|
||||
|
||||
$dbh->bz_unlock_tables();
|
||||
my $nb_bugs = scalar(@$bug_ids);
|
||||
if ($nb_bugs) {
|
||||
my $timestamp = $dbh->selectrow_array("SELECT NOW()");
|
||||
foreach my $bug_id (@$bug_ids) {
|
||||
$dbh->do("UPDATE bugs SET target_milestone = ?,
|
||||
delta_ts = ? WHERE bug_id = ?",
|
||||
undef, ($default_milestone, $timestamp, $bug_id));
|
||||
# We have to update the 'bugs_activity' table too.
|
||||
LogActivityEntry($bug_id, 'target_milestone', $milestone,
|
||||
$default_milestone, $whoid, $timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
$vars->{'bug_count'} = $nb_bugs;
|
||||
|
||||
$dbh->do("DELETE FROM milestones WHERE product_id = ? AND value = ?",
|
||||
undef, ($product_id, $milestone));
|
||||
|
||||
unlink "$datadir/versioncache";
|
||||
|
||||
|
||||
$vars->{'name'} = $milestone;
|
||||
$vars->{'product'} = $product;
|
||||
$template->process("admin/milestones/deleted.html.tmpl",
|
||||
$vars)
|
||||
$template->process("admin/milestones/deleted.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
exit;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
# Dawn Endico <endico@mozilla.org>
|
||||
# Joe Robins <jmrobins@tgix.com>
|
||||
# Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
#
|
||||
# Direct any questions on this source code to
|
||||
#
|
||||
|
@ -259,7 +260,8 @@ sub PutTrailer (@)
|
|||
# Preliminary checks:
|
||||
#
|
||||
|
||||
Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $user = Bugzilla->login(LOGIN_REQUIRED);
|
||||
my $whoid = $user->id;
|
||||
|
||||
print Bugzilla->cgi->header();
|
||||
|
||||
|
@ -771,79 +773,55 @@ one.";
|
|||
#
|
||||
|
||||
if ($action eq 'delete') {
|
||||
PutHeader("Deleting product");
|
||||
CheckProduct($product);
|
||||
my $product_id = get_product_id($product);
|
||||
|
||||
# lock the tables before we start to change everything:
|
||||
my $bug_ids =
|
||||
$dbh->selectcol_arrayref("SELECT bug_id FROM bugs WHERE product_id = ?",
|
||||
undef, $product_id);
|
||||
|
||||
$dbh->bz_lock_tables('attachments WRITE',
|
||||
'bugs WRITE',
|
||||
'bugs_activity WRITE',
|
||||
'components WRITE',
|
||||
'dependencies WRITE',
|
||||
'versions WRITE',
|
||||
'products WRITE',
|
||||
'groups WRITE',
|
||||
'group_control_map WRITE',
|
||||
'profiles WRITE',
|
||||
'milestones WRITE',
|
||||
'flaginclusions WRITE',
|
||||
'flagexclusions 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_id=$product_id");
|
||||
while (MoreSQLData()) {
|
||||
my $bugid = FetchOneColumn();
|
||||
|
||||
PushGlobalSQLState();
|
||||
SendSQL("DELETE FROM attachments WHERE bug_id=$bugid");
|
||||
SendSQL("DELETE FROM bugs_activity WHERE bug_id=$bugid");
|
||||
SendSQL("DELETE FROM dependencies WHERE blocked=$bugid");
|
||||
PopGlobalSQLState();
|
||||
my $nb_bugs = scalar(@$bug_ids);
|
||||
if ($nb_bugs) {
|
||||
if (Param("allowbugdeletion")) {
|
||||
foreach my $bug_id (@$bug_ids) {
|
||||
my $bug = new Bugzilla::Bug($bug_id, $whoid);
|
||||
$bug->remove_from_db();
|
||||
}
|
||||
}
|
||||
else {
|
||||
ThrowUserError("product_has_bugs", { nb => $nb_bugs });
|
||||
}
|
||||
print "Attachments, bug activity and dependencies deleted.<BR>\n";
|
||||
|
||||
|
||||
# Deleting the rest is easier:
|
||||
|
||||
SendSQL("DELETE FROM bugs
|
||||
WHERE product_id=$product_id");
|
||||
print "Bugs deleted.<BR>\n";
|
||||
}
|
||||
|
||||
SendSQL("DELETE FROM components
|
||||
WHERE product_id=$product_id");
|
||||
PutHeader("Deleting product");
|
||||
print "All references to deleted bugs removed.<P>\n" if $nb_bugs;
|
||||
|
||||
$dbh->bz_lock_tables('products WRITE', 'components WRITE',
|
||||
'versions WRITE', 'milestones WRITE',
|
||||
'group_control_map WRITE',
|
||||
'flaginclusions WRITE', 'flagexclusions WRITE');
|
||||
|
||||
$dbh->do("DELETE FROM components WHERE product_id = ?", undef, $product_id);
|
||||
print "Components deleted.<BR>\n";
|
||||
|
||||
SendSQL("DELETE FROM versions
|
||||
WHERE product_id=$product_id");
|
||||
print "Versions deleted.<P>\n";
|
||||
$dbh->do("DELETE FROM versions WHERE product_id = ?", undef, $product_id);
|
||||
print "Versions deleted.<BR>\n";
|
||||
|
||||
# deleting associated target milestones - matthew@zeroknowledge.com
|
||||
SendSQL("DELETE FROM milestones
|
||||
WHERE product_id=$product_id");
|
||||
print "Milestones deleted.<BR>\n";
|
||||
$dbh->do("DELETE FROM milestones WHERE product_id = ?", undef, $product_id);
|
||||
print "Milestones deleted.<P>\n";
|
||||
|
||||
SendSQL("DELETE FROM group_control_map
|
||||
WHERE product_id=$product_id");
|
||||
$dbh->do("DELETE FROM group_control_map WHERE product_id = ?",
|
||||
undef, $product_id);
|
||||
print "Group controls deleted.<BR>\n";
|
||||
|
||||
SendSQL("DELETE FROM flaginclusions
|
||||
WHERE product_id=$product_id");
|
||||
SendSQL("DELETE FROM flagexclusions
|
||||
WHERE product_id=$product_id");
|
||||
print "Flag inclusions and exclusions deleted.<BR>\n";
|
||||
$dbh->do("DELETE FROM flaginclusions WHERE product_id = ?",
|
||||
undef, $product_id);
|
||||
$dbh->do("DELETE FROM flagexclusions WHERE product_id = ?",
|
||||
undef, $product_id);
|
||||
print "Flag inclusions and exclusions deleted.<P>\n";
|
||||
|
||||
SendSQL("DELETE FROM products
|
||||
WHERE id=$product_id");
|
||||
print "Product '$product' deleted.<BR>\n";
|
||||
$dbh->do("DELETE FROM products WHERE id = ?", undef, $product_id);
|
||||
print "Product '$product' deleted.<P>\n";
|
||||
|
||||
$dbh->bz_unlock_tables();
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
# Contributor(s): Holger Schurig <holgerschurig@nikocity.de>
|
||||
# Terry Weissman <terry@mozilla.org>
|
||||
# Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
#
|
||||
#
|
||||
# Direct any questions on this source code to
|
||||
|
@ -293,66 +294,32 @@ if ($action eq 'del') {
|
|||
#
|
||||
|
||||
if ($action eq 'delete') {
|
||||
|
||||
CheckVersion($product,$version);
|
||||
CheckVersion($product, $version);
|
||||
my $product_id = get_product_id($product);
|
||||
|
||||
# lock the tables before we start to change everything:
|
||||
trick_taint($version);
|
||||
|
||||
$dbh->bz_lock_tables('attachments WRITE',
|
||||
'bugs WRITE',
|
||||
'bugs_activity WRITE',
|
||||
'versions 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")) {
|
||||
|
||||
my $deleted_bug_count = 0;
|
||||
|
||||
SendSQL("SELECT bug_id
|
||||
FROM bugs
|
||||
WHERE product_id = $product_id
|
||||
AND version = " . SqlQuote($version));
|
||||
while (MoreSQLData()) {
|
||||
my $bugid = FetchOneColumn();
|
||||
|
||||
PushGlobalSQLState();
|
||||
SendSQL("DELETE FROM attachments WHERE bug_id = $bugid");
|
||||
SendSQL("DELETE FROM bugs_activity WHERE bug_id = $bugid");
|
||||
SendSQL("DELETE FROM dependencies WHERE blocked = $bugid");
|
||||
PopGlobalSQLState();
|
||||
|
||||
$deleted_bug_count++;
|
||||
}
|
||||
|
||||
$vars->{'deleted_bug_count'} = $deleted_bug_count;
|
||||
|
||||
# Deleting the rest is easier:
|
||||
|
||||
SendSQL("DELETE FROM bugs
|
||||
WHERE product_id = $product_id
|
||||
AND version = " . SqlQuote($version));
|
||||
my $nb_bugs =
|
||||
$dbh->selectrow_array("SELECT COUNT(bug_id) FROM bugs
|
||||
WHERE product_id = ? AND version = ?",
|
||||
undef, ($product_id, $version));
|
||||
|
||||
# The version cannot be removed if there are bugs
|
||||
# associated with it.
|
||||
if ($nb_bugs) {
|
||||
ThrowUserError("version_has_bugs", { nb => $nb_bugs });
|
||||
}
|
||||
|
||||
SendSQL("DELETE FROM versions
|
||||
WHERE product_id = $product_id
|
||||
AND value = " . SqlQuote($version));
|
||||
|
||||
$dbh->bz_unlock_tables();
|
||||
$dbh->do("DELETE FROM versions WHERE product_id = ? AND value = ?",
|
||||
undef, ($product_id, $version));
|
||||
|
||||
unlink "$datadir/versioncache";
|
||||
|
||||
$vars->{'name'} = $version;
|
||||
$vars->{'product'} = $product;
|
||||
$template->process("admin/versions/deleted.html.tmpl",
|
||||
$vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
|
||||
$template->process("admin/versions/deleted.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,23 +36,15 @@
|
|||
|
||||
<p>
|
||||
[% IF deleted_bug_count %]
|
||||
Attachments, [% terms.bug %] activity and dependencies deleted for
|
||||
[%+ deleted_bug_count %]
|
||||
[%- IF deleted_bug_count %]
|
||||
[% terms.bugs %]
|
||||
[% ELSE %]
|
||||
[% terms.bug %]
|
||||
[% END %].
|
||||
|
||||
</p><p>
|
||||
[% deleted_bug_count %]
|
||||
[%- IF deleted_bug_count %]
|
||||
[%- IF deleted_bug_count > 1 %]
|
||||
[% terms.bugs %]
|
||||
[% ELSE %]
|
||||
[% terms.bug %]
|
||||
[% END %]
|
||||
deleted.
|
||||
|
||||
</p><p>
|
||||
All references to those deleted [% terms.bugs %] have been removed.
|
||||
[% ELSE %]
|
||||
No [% terms.bugs %] existed for the component.
|
||||
[% END %]
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
|
@ -69,66 +70,30 @@
|
|||
|
||||
[% IF bug_count %]
|
||||
|
||||
[% IF !Param("allowbugdeletion") %]
|
||||
|
||||
Sorry, there
|
||||
|
||||
<table border="0" cellpadding="20" width="70%" bgcolor="red">
|
||||
<tr><td>
|
||||
There
|
||||
[% IF bug_count > 1 %]
|
||||
are [% bug_count %] [%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
is [% bug_count %] [%+ terms.bug %]
|
||||
is 1 [% terms.bug %]
|
||||
[% END %]
|
||||
|
||||
outstanding for this milestone. You must move
|
||||
|
||||
[% IF bug_count > 1 %]
|
||||
those [% terms.bugs %]
|
||||
[% ELSE %]
|
||||
that [% terms.bug %]
|
||||
[% END %]
|
||||
|
||||
to another milestone before you can delete this one.
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<table border="0" cellpadding="20" width="70%" bgcolor="red"><tr><td>
|
||||
|
||||
There [% IF bug_count > 1 %]
|
||||
are [% bug_count %] [%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
is 1 [% terms.bug %]
|
||||
[% END %]
|
||||
entered for this milestone! When you delete this
|
||||
milestone, <b><blink>ALL</blink></b> stored [% terms.bugs %] will be deleted,
|
||||
too.
|
||||
You could not even see the [% terms.bug %] history for this milestone anymore!
|
||||
</td></tr></table>
|
||||
|
||||
[% END %]
|
||||
entered for this milestone! When you delete this milestone,
|
||||
<b><blink>ALL</blink></b> stored [% terms.bugs %] will be reassigned to
|
||||
the default milestone of this product.
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% IF default_milestone == name %]
|
||||
<p>Do you really want to delete this milestone?<p>
|
||||
|
||||
<p>Sorry, but '[% name FILTER html %]' is the default milestone for product '
|
||||
[%- product FILTER html %]', and so it can not be deleted.
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
[% IF bug_count == 0 || Param('allowbugdeletion') %]
|
||||
|
||||
<p>Do you really want to delete this milestone?<p>
|
||||
|
||||
<form method="post" action="editmilestones.cgi">
|
||||
<input type="submit" value="Yes, delete">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="product" value="[% product FILTER html %]">
|
||||
<input type="hidden" name="milestone" value="[% name FILTER html %]">
|
||||
</form>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
||||
<form method="post" action="editmilestones.cgi">
|
||||
<input type="submit" value="Yes, delete">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="product" value="[% product FILTER html %]">
|
||||
<input type="hidden" name="milestone" value="[% name FILTER html %]">
|
||||
</form>
|
||||
|
||||
[% PROCESS admin/milestones/footer.html.tmpl %]
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
|
@ -24,8 +25,8 @@
|
|||
#
|
||||
# product: string; the name of the product the milestone belonged to
|
||||
#
|
||||
# deleted_bug_count: number; the number of bugs which were deleted
|
||||
# (if bug deletion is allowed)
|
||||
# bug_count: number; the number of bugs which were reassigned to
|
||||
# the default milestone.
|
||||
#%]
|
||||
|
||||
[% title = BLOCK %]Deleted Milestone '[% name FILTER html %]' of Product
|
||||
|
@ -35,23 +36,15 @@
|
|||
%]
|
||||
|
||||
<p>
|
||||
[% IF deleted_bug_count %]
|
||||
Attachments, [% terms.bug %] activity and dependencies deleted for
|
||||
[%+ deleted_bug_count %]
|
||||
[% IF deleted_bug_count > 1 %]
|
||||
[%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
[%+ terms.bug %]
|
||||
[% END %].
|
||||
[% IF bug_count %]
|
||||
|
||||
</p><p>
|
||||
[% deleted_bug_count %]
|
||||
[% IF deleted_bug_count > 1 %]
|
||||
[% bug_count %]
|
||||
[% IF bug_count > 1 %]
|
||||
[%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
[%+ terms.bug %]
|
||||
[% END %]
|
||||
deleted.
|
||||
reassigned to the default milestone.
|
||||
|
||||
[% ELSE %]
|
||||
No [% terms.bugs %] were targetted at the milestone.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Gavin Shelley <bugzilla@chimpychompy.org>
|
||||
# Frédéric Buclin <LpSolit@gmail.com>
|
||||
#%]
|
||||
|
||||
[%# INTERFACE:
|
||||
|
@ -67,46 +68,23 @@
|
|||
|
||||
[% IF bug_count %]
|
||||
|
||||
[% IF !Param("allowbugdeletion") %]
|
||||
|
||||
Sorry, there
|
||||
|
||||
[% IF bug_count > 1 %]
|
||||
are [% bug_count %] [%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
is [% bug_count %] [%+ terms.bug %]
|
||||
[% END %]
|
||||
|
||||
outstanding for this version. You must move
|
||||
|
||||
[% IF bug_count > 1 %]
|
||||
those [% terms.bugs %]
|
||||
[% ELSE %]
|
||||
that [% terms.bug %]
|
||||
[% END %]
|
||||
|
||||
to another version before you can delete this one.
|
||||
|
||||
Sorry, there
|
||||
[% IF bug_count > 1 %]
|
||||
are [% bug_count %] [%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
|
||||
<table border="0" cellpadding="20" width="70%" bgcolor="red"><tr><td>
|
||||
|
||||
There [% IF bug_count > 1 %]
|
||||
are [% bug_count %] [%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
is 1 [% terms.bug %]
|
||||
[% END %]
|
||||
entered for this version! When you delete this
|
||||
version, <b><blink>ALL</blink></b> stored [% terms.bugs %] will be deleted,
|
||||
too.
|
||||
You could not even see the [% terms.bug %] history for this version anymore!
|
||||
</td></tr></table>
|
||||
|
||||
is [% bug_count %] [%+ terms.bug %]
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
||||
outstanding for this version. You must move
|
||||
|
||||
[% IF bug_count == 0 || Param('allowbugdeletion') %]
|
||||
[% IF bug_count > 1 %]
|
||||
those [% terms.bugs %]
|
||||
[% ELSE %]
|
||||
that [% terms.bug %]
|
||||
[% END %]
|
||||
to another version before you can delete this one.
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<p>Do you really want to delete this version?<p>
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
#
|
||||
# product: string; the name of the product the version belonged to
|
||||
#
|
||||
# deleted_bug_count: number; the number of bugs which were deleted
|
||||
# (if bug deletion is allowed)
|
||||
#%]
|
||||
|
||||
[% title = BLOCK %]Deleted Version '[% name FILTER html %]' of Product
|
||||
|
@ -34,30 +32,6 @@
|
|||
title = title
|
||||
%]
|
||||
|
||||
<p>
|
||||
[% IF deleted_bug_count %]
|
||||
Attachments, [% terms.bug %] activity and dependencies deleted for
|
||||
[%+ deleted_bug_count %]
|
||||
[% IF deleted_bug_count > 1 %]
|
||||
[%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
[%+ terms.bug %]
|
||||
[% END %].
|
||||
|
||||
</p><p>
|
||||
[% deleted_bug_count %]
|
||||
[% IF deleted_bug_count > 1 %]
|
||||
[%+ terms.bugs %]
|
||||
[% ELSE %]
|
||||
[%+ terms.bug %]
|
||||
[% END %]
|
||||
deleted.
|
||||
|
||||
[% ELSE %]
|
||||
No [% terms.bugs %] were targetted at the version.
|
||||
[% END %]
|
||||
</p>
|
||||
|
||||
<p>Version '[% name FILTER html %]' deleted.</p>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -624,17 +624,13 @@
|
|||
],
|
||||
|
||||
'admin/milestones/deleted.html.tmpl' => [
|
||||
'deleted_bug_count'
|
||||
'bug_count'
|
||||
],
|
||||
|
||||
'admin/versions/confirm-delete.html.tmpl' => [
|
||||
'bug_count'
|
||||
],
|
||||
|
||||
'admin/versions/deleted.html.tmpl' => [
|
||||
'deleted_bug_count'
|
||||
],
|
||||
|
||||
'admin/settings/edit.html.tmpl' => [
|
||||
'name',
|
||||
'checkbox_name'
|
||||
|
|
|
@ -249,6 +249,12 @@
|
|||
[% title = "Blank Component Name Not Allowed" %]
|
||||
You must enter a name for this new component.
|
||||
|
||||
[% ELSIF error == "component_has_bugs" %]
|
||||
[% title = BLOCK %]Component has [% terms.Bugs %][% END %]
|
||||
There are [% nb FILTER html %] [%+ terms.bugs %] entered for this component!
|
||||
You must reassign those [% terms.bugs %] to another component before you
|
||||
can delete this one.
|
||||
|
||||
[% ELSIF error == "component_must_have_a_name" %]
|
||||
[% title = "Blank Component Name Not Allowed" %]
|
||||
You cannot delete the component name for component '[% name FILTER html %]'.
|
||||
|
@ -683,6 +689,11 @@
|
|||
[% title = "Blank Milestone Name Not Allowed" %]
|
||||
You must enter a name for this milestone.
|
||||
|
||||
[% ELSIF error == "milestone_is_default" %]
|
||||
[% title = "Default milestone not deletable" %]
|
||||
Sorry, but [% name FILTER html %] is the default milestone for
|
||||
product '[% product FILTER html %]', and so it can not be deleted.
|
||||
|
||||
[% ELSIF error == "milestone_name_too_long" %]
|
||||
[% title = "Milestone Name Is Too Long" %]
|
||||
The name of a milestone is limited to 20 characters.
|
||||
|
@ -911,6 +922,12 @@
|
|||
You are not permitted to edit [% terms.bugs %] in product
|
||||
[% product FILTER html %].
|
||||
|
||||
[% ELSIF error == "product_has_bugs" %]
|
||||
[% title = BLOCK %]Product has [% terms.Bugs %][% END %]
|
||||
There are [% nb FILTER html %] [%+ terms.bugs %] entered for this product!
|
||||
You must reassign those [% terms.bugs %] to another product before you
|
||||
can delete this one.
|
||||
|
||||
[% ELSIF error == "query_name_missing" %]
|
||||
[% title = "No Search Name Specified" %]
|
||||
You must enter a name for your search.
|
||||
|
@ -1026,6 +1043,12 @@
|
|||
[% title = "Blank Version Name Not Allowed" %]
|
||||
You must enter a name for this version.
|
||||
|
||||
[% ELSIF error == "version_has_bugs" %]
|
||||
[% title = BLOCK %]Version has [% terms.Bugs %][% END %]
|
||||
There are [% nb FILTER html %] [%+ terms.bugs %] associated with this
|
||||
version! You must reassign those [% terms.bugs %] to another version
|
||||
before you can delete this one.
|
||||
|
||||
[% ELSIF error == "version_name_too_long" %]
|
||||
[% title = "Version Name Is Too Long" %]
|
||||
The name of a version is limited to 20 characters.
|
||||
|
|
Загрузка…
Ссылка в новой задаче