]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1532416 - Refactor move_flag_types to use Mojolicious and DBIx::Class
authorDylan William Hardison <dylan@hardison.net>
Fri, 8 Mar 2019 04:02:38 +0000 (23:02 -0500)
committerGitHub <noreply@github.com>
Fri, 8 Mar 2019 04:02:38 +0000 (23:02 -0500)
Bugzilla/App/Command/move_flag_types.pm [new file with mode: 0755]
scripts/move_flag_types.pl [deleted file]

diff --git a/Bugzilla/App/Command/move_flag_types.pm b/Bugzilla/App/Command/move_flag_types.pm
new file mode 100755 (executable)
index 0000000..8646b07
--- /dev/null
@@ -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<Bugzilla::App::Command::move_flag_types> inherits all attributes from
+L<Mojolicious::Command> 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<Bugzilla::App::Command::move_flag_types> inherits all methods from
+L<Mojolicious::Command> 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 (executable)
index 28ccb9d..0000000
+++ /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";
-}