summaryrefslogtreecommitdiffstats
path: root/scripts/migrate_whiteboard_keyword.pl
blob: f31a30521e2a4ab5ba206984c6e01f48bb200cb8 (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
#!/usr/bin/perl
# 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.
#===============================================================================
#
#         FILE:  migrate_whiteboard_keyword.pl
#
#        USAGE:  ./migrate_whiteboard_keyword.pl [--remove]
#
#  DESCRIPTION:  Add keyword to bugs with specified string stored in
#                whiteboard field. If --remove, then also remove the string
#                value from whiteboard.
#
#      OPTIONS:  Without --doit, does a dry-run without updating the database.
#                If --doit is passed, then the database is updated.
#                --remove will remove string from the whiteboard.
# REQUIREMENTS:  None
#         BUGS:  1279368
#        NOTES:  None
#       AUTHOR:  David Lawrence (dkl@mozilla.com),
#      COMPANY:  Mozilla Corproation
#      VERSION:  1.0
#      CREATED:  10/31/2012
#     REVISION:  1
#===============================================================================

use 5.10.1;
use strict;
use warnings;

use FindBin;
use lib "$FindBin::Bin/..", "$FindBin::Bin/../lib", "$FindBin::Bin/../local/lib/perl5";

use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Field;
use Bugzilla::Keyword;
use Bugzilla::User;
use Bugzilla::Util qw(trick_taint trim);

use Getopt::Long;
use Term::ANSIColor qw(colored);

Bugzilla->usage_mode(USAGE_MODE_CMDLINE);

my ($remove_whiteboard, $help, $doit);
GetOptions("r|remove" => \$remove_whiteboard,
           "h|help" => \$help, 'doit' => \$doit);

sub usage {
    my $error = shift || "";
    print colored(['red'], $error) if $error;
    print <<USAGE;
Usage: migrate_whiteboard_keyword.pl [--remove|-r] [--help|-h] [--doit]

E.g.: migrate_whiteboard_keyword.pl --remove --doit "good first bug" "good-first-bug"
This script will add the specified keyword to any bugs that
contain a string in the status whiteboard. If the --remove option is
given, then string will be removed from the whiteboard as well.

Pass --doit to make the database changes permanent.
USAGE
    exit(1);
}

# exit if help was requested
usage() if $help;

# grab whiteboard and keyword
my $whiteboard = shift;
my $keyword = shift;
($whiteboard && $keyword) || usage("Whiteboard or keyword strings were not provided\n");
trick_taint($whiteboard);
trick_taint($keyword);

# User to make changes as automation@bmo.tld
my $auto_user = Bugzilla::User->check({ name => 'automation@bmo.tld' });
$auto_user || usage("Can't find user 'automation\@bmo.tld'\n");

# field ids for logging activity
my $keyword_field = Bugzilla::Field->new({ name => 'keywords'});
$keyword_field || usage("Can't find field 'keywords'\n");
my $whiteboard_field = Bugzilla::Field->new({ name => 'status_whiteboard' });
$whiteboard_field || usage("Can't find field 'status_whiteboard'\n");

# keyword object (assumes already created)
my $keyword_obj = Bugzilla::Keyword->new({ name => $keyword });
$keyword_obj || usage("Can't find keyword '$keyword'\n");

my $dbh = Bugzilla->dbh;

my $bugs = $dbh->selectall_arrayref("SELECT DISTINCT bugs.bug_id, bugs.status_whiteboard
                                     FROM bugs WHERE bugs.status_whiteboard LIKE ?",
                                    { Slice => {} }, '%' . $whiteboard . '%');

my $bug_count = scalar @$bugs;
$bug_count || usage("No bugs were found in matching search criteria.\n");

print colored(['green'], "Processing $bug_count bug(s)\n");

$dbh->bz_start_transaction() if $doit;

foreach my $bug (@$bugs) {
    my $bug_id = $bug->{'bug_id'};
    my $status_whiteboard = $bug->{'status_whiteboard'};

    print "working on bug $bug_id\n";

    my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');

    my $keyword_present = $dbh->selectrow_array("
        SELECT bug_id FROM keywords WHERE bug_id = ? AND keywordid = ?",
        undef, $bug_id, $keyword_obj->id);

    if (!$keyword_present) {
        print "  adding keyword\n";
        if ($doit) {
            $dbh->do("INSERT INTO keywords (bug_id, keywordid) VALUES (?, ?)",
                     undef, $bug_id, $keyword_obj->id);
            $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
                     "VALUES (?, ?, ?, ?, '', ?)",
                     undef, $bug_id, $auto_user->id, $timestamp, $keyword_field->id, $keyword);
            $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?",
                     undef, $timestamp, $timestamp, $bug_id);
        }
    }

    if ($remove_whiteboard) {
        print "  removing whiteboard\n";
        if ($doit) {
            my $old_whiteboard = $status_whiteboard;
            $status_whiteboard =~ s/\Q$whiteboard\E//ig;
            $status_whiteboard = trim($status_whiteboard);

            $dbh->do("UPDATE bugs SET status_whiteboard = ? WHERE bug_id = ?",
                     undef, $status_whiteboard, $bug_id);
            $dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
                     "VALUES (?, ?, ?, ?, ?, ?)",
                     undef, $bug_id, $auto_user->id, $timestamp, $whiteboard_field->id, $old_whiteboard, $status_whiteboard);
            $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?",
                     undef, $timestamp, $timestamp, $bug_id);
        }
    }
}

$dbh->bz_commit_transaction() if $doit;

if ($doit) {
    # 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();

    print colored(['green'], "DATABASE WAS UPDATED\n");
}
else {
    print colored(['red'], "DATABASE WAS NOT UPDATED\n");
}

exit(0);