diff options
7 files changed, 232 insertions, 120 deletions
diff --git a/contrib/reorg-tools/movecomponent.pl b/contrib/reorg-tools/movecomponent.pl index 162942627..bdbfdc976 100755 --- a/contrib/reorg-tools/movecomponent.pl +++ b/contrib/reorg-tools/movecomponent.pl @@ -1,46 +1,29 @@ #!/usr/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): Gervase Markham <gerv@gerv.net> - -# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569 +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. # +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. use strict; -use Cwd 'abs_path'; -use File::Basename; -BEGIN { - my $root = abs_path(dirname(__FILE__) . '/../..'); - chdir($root); -} -use lib qw(. lib); +use FindBin '$RealBin'; +use lib "$RealBin/../..", "$RealBin/../../lib"; use Bugzilla; +use Bugzilla::Component; use Bugzilla::Constants; +use Bugzilla::Field; use Bugzilla::Hook; +use Bugzilla::Product; use Bugzilla::Util; -sub usage() { - print <<USAGE; -Usage: movecomponent.pl <oldproduct> <newproduct> <component> <doit> +Bugzilla->usage_mode(USAGE_MODE_CMDLINE); + +if (scalar @ARGV < 3) { + die <<USAGE; +Usage: movecomponent.pl <oldproduct> <newproduct> <component> E.g.: movecomponent.pl ReplicationEngine FoodReplicator SeaMonkey will move the component "SeaMonkey" from the product "ReplicationEngine" @@ -49,71 +32,26 @@ to the product "FoodReplicator". Important: You must make sure the milestones and versions of the bugs in the component are available in the new product. See syncmsandversions.pl. -Pass in a true value for "doit" to make the database changes permament. USAGE - - exit(1); -} - -############################################################################# -# MAIN CODE -############################################################################# - -# This is a pure command line script. -Bugzilla->usage_mode(USAGE_MODE_CMDLINE); - -if (scalar @ARGV < 3) { - usage(); - exit(); } -my ($oldproduct, $newproduct, $component, $doit) = @ARGV; +my ($old_product_name, $new_product_name, $component_name) = @ARGV; +my $old_product = Bugzilla::Product->check({ name => $old_product_name }); +my $new_product = Bugzilla::Product->check({ name => $new_product_name }); +my $component = Bugzilla::Component->check({ product => $old_product, name => $component_name }); +my $field_id = get_field_id('product'); my $dbh = Bugzilla->dbh; -$dbh->{'AutoCommit'} = 0 unless $doit; # Turn off autocommit by default - -# Find product IDs -my $oldprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?", - undef, $oldproduct); -if (!$oldprodid) { - print "Can't find product ID for '$oldproduct'.\n"; - exit(1); -} - -my $newprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?", - undef, $newproduct); -if (!$newprodid) { - print "Can't find product ID for '$newproduct'.\n"; - exit(1); -} - -# Find component ID -my $compid = $dbh->selectrow_array("SELECT id FROM components - WHERE name = ? AND product_id = ?", - undef, $component, $oldprodid); -if (!$compid) { - print "Can't find component ID for '$component' in product " . - "'$oldproduct'.\n"; - exit(1); -} - -my $fieldid = $dbh->selectrow_array("SELECT id FROM fielddefs - WHERE name = 'product'"); -if (!$fieldid) { - print "Can't find field ID for 'product' field!\n"; - exit(1); -} - # check versions my @missing_versions; my $ra_versions = $dbh->selectcol_arrayref( "SELECT DISTINCT version FROM bugs WHERE component_id = ?", - undef, $compid); + undef, $component->id); foreach my $version (@$ra_versions) { my $has_version = $dbh->selectrow_array( "SELECT 1 FROM versions WHERE product_id = ? AND value = ?", - undef, $newprodid, $version); + undef, $new_product->id, $version); push @missing_versions, $version unless $has_version; } @@ -121,85 +59,87 @@ foreach my $version (@$ra_versions) { my @missing_milestones; my $ra_milestones = $dbh->selectcol_arrayref( "SELECT DISTINCT target_milestone FROM bugs WHERE component_id = ?", - undef, $compid); + undef, $component->id); foreach my $milestone (@$ra_milestones) { my $has_milestone = $dbh->selectrow_array( "SELECT 1 FROM milestones WHERE product_id=? AND value=?", - undef, $newprodid, $milestone); + undef, $new_product->id, $milestone); push @missing_milestones, $milestone unless $has_milestone; } my $missing_error = ''; if (@missing_versions) { - $missing_error .= "'$newproduct' is missing the following version(s):\n " . + $missing_error .= "'$new_product_name' is missing the following version(s):\n " . join("\n ", @missing_versions) . "\n"; } if (@missing_milestones) { - $missing_error .= "'$newproduct' is missing the following milestone(s):\n " . + $missing_error .= "'$new_product_name' is missing the following milestone(s):\n " . join("\n ", @missing_milestones) . "\n"; } die $missing_error if $missing_error; # confirmation print <<EOF; -About to move the component '$component' -From '$oldproduct' -To '$newproduct' +About to move the component '$component_name' +From '$old_product_name' +To '$new_product_name' Press <Ctrl-C> to stop or <Enter> to continue... EOF getc(); -print "Moving '$component' from '$oldproduct' to '$newproduct'...\n\n"; -$dbh->bz_start_transaction() if $doit; +print "Moving '$component_name' from '$old_product_name' to '$new_product_name'...\n\n"; +$dbh->bz_start_transaction(); my $ra_ids = $dbh->selectcol_arrayref( "SELECT bug_id FROM bugs WHERE product_id=? AND component_id=?", - undef, $oldprodid, $compid); + undef, $old_product->id, $component->id); # Bugs table -$dbh->do("UPDATE bugs SET product_id = ? WHERE component_id = ?", +$dbh->do("UPDATE bugs SET product_id = ? WHERE component_id = ?", undef, - ($newprodid, $compid)); + ($new_product->id, $component->id)); # Flags tables -$dbh->do("UPDATE flaginclusions SET product_id = ? WHERE component_id = ?", +$dbh->do("UPDATE flaginclusions SET product_id = ? WHERE component_id = ?", undef, - ($newprodid, $compid)); + ($new_product->id, $component->id)); -$dbh->do("UPDATE flagexclusions SET product_id = ? WHERE component_id = ?", +$dbh->do("UPDATE flagexclusions SET product_id = ? WHERE component_id = ?", undef, - ($newprodid, $compid)); + ($new_product->id, $component->id)); # Components -$dbh->do("UPDATE components SET product_id = ? WHERE id = ?", +$dbh->do("UPDATE components SET product_id = ? WHERE id = ?", undef, - ($newprodid, $compid)); + ($new_product->id, $component->id)); + +Bugzilla::Hook::process('reorg_move_component', { + old_product => $old_product, + new_product => $new_product, + component => $component, +} ); # Mark bugs as touched -$dbh->do("UPDATE bugs SET delta_ts = NOW() - WHERE component_id = ?", undef, $compid); -$dbh->do("UPDATE bugs SET lastdiffed = NOW() - WHERE component_id = ?", undef, $compid); +$dbh->do("UPDATE bugs SET delta_ts = NOW() + WHERE component_id = ?", undef, $component->id); +$dbh->do("UPDATE bugs SET lastdiffed = NOW() + WHERE component_id = ?", undef, $component->id); # Update bugs_activity my $userid = 1; # nobody@mozilla.org $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, - added) - SELECT bug_id, ?, delta_ts, ?, ?, ? + added) + SELECT bug_id, ?, delta_ts, ?, ?, ? FROM bugs WHERE component_id = ?", undef, - ($userid, $fieldid, $oldproduct, $newproduct, $compid)); + ($userid, $field_id, $old_product_name, $new_product_name, $component->id)); -Bugzilla::Hook::process('reorg_move_bugs', { bug_ids => $ra_ids } ) if $doit; - -if ($doit) { - $dbh->bz_commit_transaction(); - - # It's complex to determine which items now need to be flushed from memcached. - # As this is expected to be a rare event, we just flush the entire cache. - Bugzilla->memcached->clear_all(); -} +Bugzilla::Hook::process('reorg_move_bugs', { bug_ids => $ra_ids } ); +$dbh->bz_commit_transaction(); +# It's complex to determine which items now need to be flushed from memcached. +# As this is expected to be a rare event, we just flush the entire cache. +Bugzilla->memcached->clear_all(); diff --git a/extensions/ComponentWatching/Extension.pm b/extensions/ComponentWatching/Extension.pm index addbaba70..f85e0010c 100644 --- a/extensions/ComponentWatching/Extension.pm +++ b/extensions/ComponentWatching/Extension.pm @@ -530,4 +530,65 @@ sub _addDefaultSettings { } } +sub reorg_move_component { + my ($self, $args) = @_; + my $new_product = $args->{new_product}; + my $component = $args->{component}; + + Bugzilla->dbh->do( + "UPDATE component_watch SET product_id=? WHERE component_id=?", + undef, + $new_product->id, $component->id, + ); +} + +sub sanitycheck_check { + my ($self, $args) = @_; + my $status = $args->{status}; + + $status->('component_watching_check'); + + my ($count) = Bugzilla->dbh->selectrow_array(" + SELECT COUNT(*) + FROM component_watch + INNER JOIN components ON components.id = component_watch.component_id + WHERE component_watch.product_id <> components.product_id + "); + if ($count) { + $status->('component_watching_alert', undef, 'alert'); + $status->('component_watching_repair'); + } +} + +sub sanitycheck_repair { + my ($self, $args) = @_; + return unless Bugzilla->cgi->param('component_watching_repair'); + + my $status = $args->{'status'}; + my $dbh = Bugzilla->dbh; + $status->('component_watching_repairing'); + + my $rows = $dbh->selectall_arrayref(" + SELECT DISTINCT component_watch.product_id AS bad_product_id, + components.product_id AS good_product_id, + component_watch.component_id + FROM component_watch + INNER JOIN components ON components.id = component_watch.component_id + WHERE component_watch.product_id <> components.product_id + ", + { Slice => {} } + ); + foreach my $row (@$rows) { + $dbh->do(" + UPDATE component_watch + SET product_id=? + WHERE product_id=? AND component_id=? + ", undef, + $row->{good_product_id}, + $row->{bad_product_id}, + $row->{component_id}, + ); + } +} + __PACKAGE__->NAME; diff --git a/extensions/ComponentWatching/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl b/extensions/ComponentWatching/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl new file mode 100644 index 000000000..c22ffacaa --- /dev/null +++ b/extensions/ComponentWatching/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl @@ -0,0 +1,23 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% IF san_tag == "component_watching_repair" %] + <a href="sanitycheck.cgi?component_watching_repair=1&token= + [%- issue_hash_token(['sanitycheck']) FILTER uri %]" + >Repair invalid product_id values in the component_watch table</a> + +[% ELSIF san_tag == "component_watching_check" %] + Checking component_watch table for bad values of product_id. + +[% ELSIF san_tag == "component_watching_alert" %] + Bad values for product_id found in the component_watch table. + +[% ELSIF san_tag == "component_watching_repairing" %] + OK, now fixing bad product_id values in the component_watch table. + +[% END %] diff --git a/extensions/TrackingFlags/Extension.pm b/extensions/TrackingFlags/Extension.pm index 7d8f8c401..3ba9e768b 100644 --- a/extensions/TrackingFlags/Extension.pm +++ b/extensions/TrackingFlags/Extension.pm @@ -657,4 +657,65 @@ sub quicksearch_map { } } +sub reorg_move_component { + my ($self, $args) = @_; + my $new_product = $args->{new_product}; + my $component = $args->{component}; + + Bugzilla->dbh->do( + "UPDATE tracking_flags_visibility SET product_id=? WHERE component_id=?", + undef, + $new_product->id, $component->id, + ); +} + +sub sanitycheck_check { + my ($self, $args) = @_; + my $status = $args->{status}; + + $status->('tracking_flags_check'); + + my ($count) = Bugzilla->dbh->selectrow_array(" + SELECT COUNT(*) + FROM tracking_flags_visibility + INNER JOIN components ON components.id = tracking_flags_visibility.component_id + WHERE tracking_flags_visibility.product_id <> components.product_id + "); + if ($count) { + $status->('tracking_flags_alert', undef, 'alert'); + $status->('tracking_flags_repair'); + } +} + +sub sanitycheck_repair { + my ($self, $args) = @_; + return unless Bugzilla->cgi->param('tracking_flags_repair'); + + my $status = $args->{'status'}; + my $dbh = Bugzilla->dbh; + $status->('tracking_flags_repairing'); + + my $rows = $dbh->selectall_arrayref(" + SELECT DISTINCT tracking_flags_visibility.product_id AS bad_product_id, + components.product_id AS good_product_id, + tracking_flags_visibility.component_id + FROM tracking_flags_visibility + INNER JOIN components ON components.id = tracking_flags_visibility.component_id + WHERE tracking_flags_visibility.product_id <> components.product_id + ", + { Slice => {} } + ); + foreach my $row (@$rows) { + $dbh->do(" + UPDATE tracking_flags_visibility + SET product_id=? + WHERE product_id=? AND component_id=? + ", undef, + $row->{good_product_id}, + $row->{bad_product_id}, + $row->{component_id}, + ); + } +} + __PACKAGE__->NAME; diff --git a/extensions/TrackingFlags/lib/Admin.pm b/extensions/TrackingFlags/lib/Admin.pm index b72416819..389acde2c 100644 --- a/extensions/TrackingFlags/lib/Admin.pm +++ b/extensions/TrackingFlags/lib/Admin.pm @@ -263,7 +263,10 @@ sub _validate { if ($visibility->{component} ne '') { $visibility->{component_obj} = Bugzilla::Component->new({ product => $visibility->{product_obj}, name => $visibility->{component} }) - || ThrowCodeError('tracking_flags_invalid_component', { component => $visibility->{component} }); + || ThrowCodeError('tracking_flags_invalid_component', { + product => $visibility->{product}, + component_name => $visibility->{component}, + }); } } diff --git a/extensions/TrackingFlags/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl b/extensions/TrackingFlags/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl new file mode 100644 index 000000000..71ef63c11 --- /dev/null +++ b/extensions/TrackingFlags/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl @@ -0,0 +1,23 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% IF san_tag == "tracking_flags_repair" %] + <a href="sanitycheck.cgi?tracking_flags_repair=1&token= + [%- issue_hash_token(['sanitycheck']) FILTER uri %]" + >Repair invalid product_id values in the tracking_flags_visibility table</a> + +[% ELSIF san_tag == "tracking_flags_check" %] + Checking tracking_flags_visibility table for bad values of product_id. + +[% ELSIF san_tag == "tracking_flags_alert" %] + Bad values for product_id found in the tracking_flags_visibility table. + +[% ELSIF san_tag == "tracking_flags_repairing" %] + OK, now fixing bad product_id values in the tracking_flags_visibility table. + +[% END %] diff --git a/extensions/TrackingFlags/template/en/default/hook/global/code-error-errors.html.tmpl b/extensions/TrackingFlags/template/en/default/hook/global/code-error-errors.html.tmpl index 2d462ebaf..d656aac92 100644 --- a/extensions/TrackingFlags/template/en/default/hook/global/code-error-errors.html.tmpl +++ b/extensions/TrackingFlags/template/en/default/hook/global/code-error-errors.html.tmpl @@ -12,7 +12,8 @@ [% ELSIF error == "tracking_flags_invalid_component" %] [% title = "Invalid Component" %] - The component named '[% component FILTER html %]' does not exist. + The component named '[% component_name FILTER html %]' does not exist in the + product '[% product FILTER html %]'. [% ELSIF error == "tracking_flags_invalid_item_id" %] [% title = "Invalid " _ item _ " ID" %] |