summaryrefslogtreecommitdiffstats
path: root/scripts/move_flag_types.pl
blob: bf0bf0ecad8684089838e55e9d03c7d31e10f786 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/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 FindBin qw($RealBin);
use lib ("$RealBin/..", "$RealBin/../lib", "$RealBin/../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";
}