From: Dylan William Hardison Date: Fri, 8 Mar 2019 04:02:38 +0000 (-0500) Subject: Bug 1532416 - Refactor move_flag_types to use Mojolicious and DBIx::Class X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0b274a53a2b0e2accba3960406255c2719136d6;p=thirdparty%2Fbugzilla.git Bug 1532416 - Refactor move_flag_types to use Mojolicious and DBIx::Class --- diff --git a/Bugzilla/App/Command/move_flag_types.pm b/Bugzilla/App/Command/move_flag_types.pm new file mode 100755 index 000000000..8646b0717 --- /dev/null +++ b/Bugzilla/App/Command/move_flag_types.pm @@ -0,0 +1,148 @@ +# 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. + +package Bugzilla::App::Command::move_flag_types; ## no critic (Capitalization) +use Mojo::Base 'Mojolicious::Command'; + +use Bugzilla::Constants; +use Mojo::File 'path'; +use Mojo::Util 'getopt'; +use JSON::MaybeXS; + +has description => 'Move flag types'; +has usage => sub { shift->extract_usage }; + +sub run { + my ($self, @args) = @_; + my $doit = 0; + my ($oldid, $newid, $product, $component, $debug); + + Bugzilla->usage_mode(USAGE_MODE_CMDLINE); + getopt \@args, + 'old-id|o=s' => \$oldid, + 'new-id|n=s' => \$newid, + 'product|p=s' => \$product, + 'component|c=s' => \$component, + 'doit|d' => \$doit, + 'debug|D' => \$debug; + + die $self->usage unless $oldid && $newid && $product; + + my $model = Bugzilla->dbh->model; + + my $old_flagtype = $model->resultset('FlagType')->find({id => $oldid}) + or die "No flagtype $oldid"; + my $new_flagtype = $model->resultset('FlagType')->find({id => $newid}) + or die "No flagtype $newid"; + + my $bugs = $model->resultset('Bug')->search(_bug_query($product, $component)); + my $flags = $bugs->search_related('flags', {'flags.type_id' => $oldid}); + my $count = $flags->count; + + if ($debug) { + my $query = ${ $flags->as_query }; + say STDERR "SQL query:\n", JSON::MaybeXS->new(pretty => 1, canonical => 1)->encode($query); + } + if ($count) { + my $old_name = $old_flagtype->name; + my $new_name = $new_flagtype->name; + say "Moving '$count' flags from $old_name ($oldid) to $new_name ($newid)..."; + + if (!$doit) { + say + "Pass the argument --doit or -d to permanently make changes to the database."; + } + else { + while (my $flag = $flags->next) { + $model->txn_do(sub { + $flag->type_id($new_flagtype->id); + $flag->update(); + }); + say "Bug: ", $flag->bug_id, " Flag: ", $flag->id; + } + } + + # 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(); + } + else { + say "No flags to move"; + } +} + +sub _bug_query { + my ($product, $component) = @_; + + # if we have a component name, search on product and component name + if ($component) { + return ({'product.name' => $product, 'component.name' => $component}, + {join => {component => 'product'}}); + } + else { + return ({'product.name' => $product}, {join => 'product'}); + } +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::App::Command::move_flag_types - Move currently set flags from one type id to another based +on product and optionally component. + +=head1 SYNOPSIS + + Usage: APPLICATION move_flag_types + + ./bugzilla.pl move_flag_types --old-id 4 --new-id 720 --product Firefox --component Installer + + Options: + -h, --help Print a brief help message and exits. + -o, --oldid type_id Old flag type id. Use editflagtypes.cgi to determine the type id from the URL. + -n, --newid type_id New flag type id. Use editflagtypes.cgi to determine the type id from the URL. + -p, --product name The product that the bugs most be assigned to. + -c, --component name (Optional) The component of the given product that the bugs must be assigned to. + -d, --doit Without this argument, changes are not actually committed to the database. + -D, --debug Show the SQL query + +=head1 DESCRIPTION + +This command will move bugs matching a specific product (and optionally a component) +from one flag type id to another if the bug has the flag set to either +, -, or ?. + +=head1 ATTRIBUTES + +L inherits all attributes from +L and implements the following new ones. + +=head2 description + + my $description = $move_flag_types->description; + $move_flag_types = $move_flag_types->description('Foo'); + +Short description of this command, used for the command list. + +=head2 usage + + my $usage = $move_flag_types->usage; + $move_flag_types = $move_flag_types->usage('Foo'); + +Usage information for this command, used for the help screen. + +=head1 METHODS + +L inherits all methods from +L and implements the following new ones. + +=head2 run + + $move_flag_types->run(@ARGV); + +Run this command. diff --git a/scripts/move_flag_types.pl b/scripts/move_flag_types.pl deleted file mode 100755 index 28ccb9d9d..000000000 --- a/scripts/move_flag_types.pl +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env perl -# -*- 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 Initial Developer of the Original Code is Mozilla Foundation -# Portions created by the Initial Developer are Copyright (C) 2011 the -# Initial Developer. All Rights Reserved. -# -#=============================================================================== -# -# FILE: move_flag_types.pl -# -# USAGE: ./move_flag_types.pl -# -# DESCRIPTION: Move current set flag from one type_id to another -# based on product and optionally component. -# -# OPTIONS: --- -# REQUIREMENTS: --- -# BUGS: --- -# NOTES: --- -# AUTHOR: David Lawrence (:dkl), dkl@mozilla.com -# COMPANY: Mozilla Foundation -# VERSION: 1.0 -# CREATED: 08/22/2011 05:18:06 PM -# REVISION: --- -#=============================================================================== - -=head1 NAME - -move_flag_types.pl - Move currently set flags from one type id to another based -on product and optionally component. - -=head1 SYNOPSIS - -This script will move bugs matching a specific product (and optionally a component) -from one flag type id to another if the bug has the flag set to either +, -, or ?. - -./move_flag_types.pl --old-id 4 --new-id 720 --product Firefox --component Installer - -=head1 OPTIONS - -=over - -=item B<--help|-h|?> - -Print a brief help message and exits. - -=item B<--oldid|-o> - -Old flag type id. Use editflagtypes.cgi to determine the type id from the URL. - -=item B<--newid|-n> - -New flag type id. Use editflagtypes.cgi to determine the type id from the URL. - -=item B<--product|-p> - -The product that the bugs most be assigned to. - -=item B<--component|-c> - -Optional: The component of the given product that the bugs must be assigned to. - -=item B<--doit|-d> - -Without this argument, changes are not actually committed to the database. - -=back - -=cut - -use strict; -use warnings; -use lib qw(. lib local/lib/perl5); - -use Bugzilla; -use Getopt::Long; -use Pod::Usage; - -my %params; -GetOptions(\%params, 'help|h|?', 'oldid|o=s', 'newid|n=s', 'product|p=s', - 'component|c:s', 'doit|d') - or pod2usage(1); - -if ( $params{'help'} - || !$params{'oldid'} - || !$params{'newid'} - || !$params{'product'}) -{ - pod2usage({-message => "Missing required argument", -exitval => 1}); -} - -# Set defaults -$params{'doit'} ||= 0; -$params{'component'} ||= ''; - -my $dbh = Bugzilla->dbh; - -# Get the flag names -my $old_flag_name - = $dbh->selectrow_array("SELECT name FROM flagtypes WHERE id = ?", - undef, $params{'oldid'}); -my $new_flag_name - = $dbh->selectrow_array("SELECT name FROM flagtypes WHERE id = ?", - undef, $params{'newid'}); - -# Find the product id -my $product_id = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?", - undef, $params{'product'}); - -# Find the component id if not __ANY__ -my $component_id; -if ($params{'component'}) { - $component_id - = $dbh->selectrow_array( - "SELECT id FROM components WHERE name = ? AND product_id = ?", - undef, $params{'component'}, $product_id); -} - -my @query_args = ($params{'oldid'}); - -my $flag_query = "SELECT flags.id AS flag_id, flags.bug_id AS bug_id - FROM flags JOIN bugs ON flags.bug_id = bugs.bug_id - WHERE flags.type_id = ? "; - -if ($component_id) { - - # No need to compare against product_id as component_id is already - # tied to a specific product - $flag_query .= "AND bugs.component_id = ?"; - push(@query_args, $component_id); -} -else { - # All bugs for a product regardless of component - $flag_query .= "AND bugs.product_id = ?"; - push(@query_args, $product_id); -} - -my $flags = $dbh->selectall_arrayref($flag_query, undef, @query_args); - -if (@$flags) { - print "Moving '" - . scalar @$flags - . "' flags " - . "from $old_flag_name (" - . $params{'oldid'} . ") " - . "to $new_flag_name (" - . $params{'newid'} - . ")...\n"; - - if (!$params{'doit'}) { - print - "Pass the argument --doit or -d to permanently make changes to the database.\n"; - } - else { - my $flag_update_sth - = $dbh->prepare("UPDATE flags SET type_id = ? WHERE id = ?"); - - foreach my $flag (@$flags) { - my ($flag_id, $bug_id) = @$flag; - print "Bug: $bug_id Flag: $flag_id\n"; - $flag_update_sth->execute($params{'newid'}, $flag_id); - } - } - - # 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(); -} -else { - print "No flags to move\n"; -}