diff options
author | 2019-11-30 23:12:11 -0800 | |
---|---|---|
committer | 2019-12-01 14:53:51 -0800 | |
commit | 70780e40e5586c6882e33dd65a3dc3f31031a321 (patch) | |
tree | 51fc3608bd44e7b92d07a976ca3112fd5d87d843 /contrib | |
parent | Merge commit '3395d78cc8b0bd660e56f73a2689d495f2a22628' into bugstest (diff) | |
download | bugzilla-70780e40e5586c6882e33dd65a3dc3f31031a321.tar.gz bugzilla-70780e40e5586c6882e33dd65a3dc3f31031a321.tar.bz2 bugzilla-70780e40e5586c6882e33dd65a3dc3f31031a321.zip |
Gentoo-local version of 7f3a749d7bd78a3e4aee163f562d7e95b0954b44 w/ Perl-Tidy-20180220
Reformat all code using Perl-Tidy v20180220 and .perltidyrc from
matching upstream 7f3a749d7bd78a3e4aee163f562d7e95b0954b44 commit.
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/Bugzilla.pm | 2 | ||||
-rwxr-xr-x | contrib/bz_webservice_demo.pl | 239 | ||||
-rwxr-xr-x | contrib/bzdbcopy.pl | 306 | ||||
-rwxr-xr-x | contrib/console.pl | 157 | ||||
-rwxr-xr-x | contrib/convert-workflow.pl | 178 | ||||
-rwxr-xr-x | contrib/extension-convert.pl | 304 | ||||
-rwxr-xr-x | contrib/merge-users.pl | 204 | ||||
-rwxr-xr-x | contrib/mysqld-watcher.pl | 93 | ||||
-rwxr-xr-x | contrib/recode.pl | 315 | ||||
-rwxr-xr-x | contrib/sendbugmail.pl | 35 | ||||
-rwxr-xr-x | contrib/sendunsentbugmail.pl | 38 | ||||
-rwxr-xr-x | contrib/syncLDAP.pl | 377 |
12 files changed, 1175 insertions, 1073 deletions
diff --git a/contrib/Bugzilla.pm b/contrib/Bugzilla.pm index 31e0a0f6d..e7452bbb8 100644 --- a/contrib/Bugzilla.pm +++ b/contrib/Bugzilla.pm @@ -36,7 +36,7 @@ use warnings; ####################################################################### use constant BZ_ROOT_DIR => '/usr/share/bugzilla/lib'; -use constant BZ_LIB_DIR => BZ_ROOT_DIR . '/lib'; +use constant BZ_LIB_DIR => BZ_ROOT_DIR . '/lib'; ####################################################################### # DO NOT EDIT THE CODE BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING!! # diff --git a/contrib/bz_webservice_demo.pl b/contrib/bz_webservice_demo.pl index 6c8c21dfa..bf6d504ad 100755 --- a/contrib/bz_webservice_demo.pl +++ b/contrib/bz_webservice_demo.pl @@ -50,21 +50,22 @@ my $work_time; my $fetch_extension_info = 0; my $debug; -GetOptions('help|h|?' => \$help, - 'uri=s' => \$Bugzilla_uri, - 'login:s' => \$Bugzilla_login, - 'password=s' => \$Bugzilla_password, - 'restrictlogin!' => \$Bugzilla_restrict, - 'bug_id:s' => \$bug_id, - 'product_name:s' => \$product_name, - 'create:s' => \$create_file_name, - 'field:s' => \$legal_field_values, - 'comment:s' => \$add_comment, - 'private:i' => \$private, - 'worktime:f' => \$work_time, - 'extension_info' => \$fetch_extension_info, - 'debug' => \$debug - ) or pod2usage({'-verbose' => 0, '-exitval' => 1}); +GetOptions( + 'help|h|?' => \$help, + 'uri=s' => \$Bugzilla_uri, + 'login:s' => \$Bugzilla_login, + 'password=s' => \$Bugzilla_password, + 'restrictlogin!' => \$Bugzilla_restrict, + 'bug_id:s' => \$bug_id, + 'product_name:s' => \$product_name, + 'create:s' => \$create_file_name, + 'field:s' => \$legal_field_values, + 'comment:s' => \$add_comment, + 'private:i' => \$private, + 'worktime:f' => \$work_time, + 'extension_info' => \$fetch_extension_info, + 'debug' => \$debug +) or pod2usage({'-verbose' => 0, '-exitval' => 1}); =head1 OPTIONS @@ -171,7 +172,7 @@ Enable tracing at the debug level of XMLRPC requests and responses if requested. =cut if ($debug) { - $proxy->import(+trace => 'debug'); + $proxy->import(+trace => 'debug'); } =head2 Checking Bugzilla's version @@ -184,7 +185,8 @@ minimum required version your application needs. $soapresult = $proxy->call('Bugzilla.version'); _die_on_fault($soapresult); -print 'Connecting to a Bugzilla of version ' . $soapresult->result()->{version} . ".\n"; +print 'Connecting to a Bugzilla of version ' + . $soapresult->result()->{version} . ".\n"; =head2 Checking Bugzilla's timezone @@ -217,22 +219,27 @@ parameter). =cut if (defined($Bugzilla_login)) { - if ($Bugzilla_login ne '') { - # Log in. - $soapresult = $proxy->call('User.login', - { login => $Bugzilla_login, - password => $Bugzilla_password, - restrict_login => $Bugzilla_restrict } ); - $Bugzilla_token = $soapresult->result->{token}; - _die_on_fault($soapresult); - print "Login successful.\n"; - } - else { - # Log out. - $soapresult = $proxy->call('User.logout'); - _die_on_fault($soapresult); - print "Logout successful.\n"; - } + if ($Bugzilla_login ne '') { + + # Log in. + $soapresult = $proxy->call( + 'User.login', + { + login => $Bugzilla_login, + password => $Bugzilla_password, + restrict_login => $Bugzilla_restrict + } + ); + $Bugzilla_token = $soapresult->result->{token}; + _die_on_fault($soapresult); + print "Login successful.\n"; + } + else { + # Log out. + $soapresult = $proxy->call('User.logout'); + _die_on_fault($soapresult); + print "Logout successful.\n"; + } } =head2 Getting Extension Information @@ -242,16 +249,16 @@ Returns all the information any extensions have decided to provide to the webser =cut if ($fetch_extension_info) { - $soapresult = $proxy->call('Bugzilla.extensions', {token => $Bugzilla_token}); - _die_on_fault($soapresult); - my $extensions = $soapresult->result()->{extensions}; - foreach my $extensionname (keys(%$extensions)) { - print "Extension '$extensionname' information\n"; - my $extension = $extensions->{$extensionname}; - foreach my $data (keys(%$extension)) { - print ' ' . $data . ' => ' . $extension->{$data} . "\n"; - } + $soapresult = $proxy->call('Bugzilla.extensions', {token => $Bugzilla_token}); + _die_on_fault($soapresult); + my $extensions = $soapresult->result()->{extensions}; + foreach my $extensionname (keys(%$extensions)) { + print "Extension '$extensionname' information\n"; + my $extension = $extensions->{$extensionname}; + foreach my $data (keys(%$extension)) { + print ' ' . $data . ' => ' . $extension->{$data} . "\n"; } + } } =head2 Retrieving Bug Information @@ -262,21 +269,22 @@ The call will return a C<Bugzilla::Bug> object. =cut if ($bug_id) { - $soapresult = $proxy->call('Bug.get', { ids => [$bug_id], token => $Bugzilla_token}); - _die_on_fault($soapresult); - $result = $soapresult->result; - my $bug = $result->{bugs}->[0]; - foreach my $field (keys(%$bug)) { - my $value = $bug->{$field}; - if (ref($value) eq 'HASH') { - foreach (keys %$value) { - print "$_: " . $value->{$_} . "\n"; - } - } - else { - print "$field: $value\n"; - } + $soapresult + = $proxy->call('Bug.get', {ids => [$bug_id], token => $Bugzilla_token}); + _die_on_fault($soapresult); + $result = $soapresult->result; + my $bug = $result->{bugs}->[0]; + foreach my $field (keys(%$bug)) { + my $value = $bug->{$field}; + if (ref($value) eq 'HASH') { + foreach (keys %$value) { + print "$_: " . $value->{$_} . "\n"; + } } + else { + print "$field: $value\n"; + } + } } =head2 Retrieving Product Information @@ -287,27 +295,28 @@ The call will return a C<Bugzilla::Product> object. =cut if ($product_name) { - $soapresult = $proxy->call('Product.get', {'names' => [$product_name], token => $Bugzilla_token}); - _die_on_fault($soapresult); - $result = $soapresult->result()->{'products'}->[0]; - - # Iterate all entries, the values may be scalars or array refs with hash refs. - foreach my $key (sort(keys %$result)) { - my $value = $result->{$key}; - - if (ref($value)) { - my $counter = 0; - foreach my $hash (@$value) { - while (my ($innerKey, $innerValue) = each %$hash) { - print "$key.$counter.$innerKey: $innerValue\n"; - } - ++$counter; + $soapresult = $proxy->call('Product.get', + {'names' => [$product_name], token => $Bugzilla_token}); + _die_on_fault($soapresult); + $result = $soapresult->result()->{'products'}->[0]; + + # Iterate all entries, the values may be scalars or array refs with hash refs. + foreach my $key (sort(keys %$result)) { + my $value = $result->{$key}; + + if (ref($value)) { + my $counter = 0; + foreach my $hash (@$value) { + while (my ($innerKey, $innerValue) = each %$hash) { + print "$key.$counter.$innerKey: $innerValue\n"; } - } - else { - print "$key: $value\n" + ++$counter; } } + else { + print "$key: $value\n"; + } + } } =head2 Creating A Bug @@ -320,20 +329,20 @@ The call will return a hash with a bug id for the newly created bug. =cut if ($create_file_name) { - my $bug_fields = do "$create_file_name"; - $bug_fields->{Bugzilla_token} = $Bugzilla_token; - $soapresult = $proxy->call('Bug.create', \%$bug_fields); - _die_on_fault($soapresult); - $result = $soapresult->result; - - if (ref($result) eq 'HASH') { - foreach (keys(%$result)) { - print "$_: $$result{$_}\n"; - } - } - else { - print "$result\n"; + my $bug_fields = do "$create_file_name"; + $bug_fields->{Bugzilla_token} = $Bugzilla_token; + $soapresult = $proxy->call('Bug.create', \%$bug_fields); + _die_on_fault($soapresult); + $result = $soapresult->result; + + if (ref($result) eq 'HASH') { + foreach (keys(%$result)) { + print "$_: $$result{$_}\n"; } + } + else { + print "$result\n"; + } } @@ -346,11 +355,12 @@ list of legal values for this field. =cut if ($legal_field_values) { - $soapresult = $proxy->call('Bug.legal_values', {field => $legal_field_values, token => $Bugzilla_token} ); - _die_on_fault($soapresult); - $result = $soapresult->result; + $soapresult = $proxy->call('Bug.legal_values', + {field => $legal_field_values, token => $Bugzilla_token}); + _die_on_fault($soapresult); + $result = $soapresult->result; - print join("\n", @{$result->{values}}) . "\n"; + print join("\n", @{$result->{values}}) . "\n"; } =head2 Adding a comment to a bug @@ -362,15 +372,23 @@ or not. =cut if ($add_comment) { - if ($bug_id) { - $soapresult = $proxy->call('Bug.add_comment', {id => $bug_id, - comment => $add_comment, private => $private, work_time => $work_time, token => $Bugzilla_token}); - _die_on_fault($soapresult); - print "Comment added.\n"; - } - else { - print "A --bug_id must be supplied to add a comment."; - } + if ($bug_id) { + $soapresult = $proxy->call( + 'Bug.add_comment', + { + id => $bug_id, + comment => $add_comment, + private => $private, + work_time => $work_time, + token => $Bugzilla_token + } + ); + _die_on_fault($soapresult); + print "Comment added.\n"; + } + else { + print "A --bug_id must be supplied to add a comment."; + } } =head1 NOTES @@ -407,18 +425,19 @@ help to you. =cut sub _die_on_fault { - my $soapresult = shift; - - if ($soapresult->fault) { - my ($package, $filename, $line) = caller; - die $soapresult->faultcode . ' ' . $soapresult->faultstring . - " in SOAP call near $filename line $line.\n"; - } + my $soapresult = shift; + + if ($soapresult->fault) { + my ($package, $filename, $line) = caller; + die $soapresult->faultcode . ' ' + . $soapresult->faultstring + . " in SOAP call near $filename line $line.\n"; + } } sub _syntaxhelp { - my $msg = shift; + my $msg = shift; - print "Error: $msg\n"; - pod2usage({'-verbose' => 0, '-exitval' => 1}); + print "Error: $msg\n"; + pod2usage({'-verbose' => 0, '-exitval' => 1}); } diff --git a/contrib/bzdbcopy.pl b/contrib/bzdbcopy.pl index fcdbefd56..5556a167e 100755 --- a/contrib/bzdbcopy.pl +++ b/contrib/bzdbcopy.pl @@ -22,51 +22,56 @@ use Bugzilla::Util; ##################################################################### # Settings for the 'Source' DB that you are copying from. -use constant SOURCE_DB_TYPE => 'Mysql'; -use constant SOURCE_DB_NAME => 'bugs'; -use constant SOURCE_DB_USER => 'bugs'; +use constant SOURCE_DB_TYPE => 'Mysql'; +use constant SOURCE_DB_NAME => 'bugs'; +use constant SOURCE_DB_USER => 'bugs'; use constant SOURCE_DB_PASSWORD => ''; -use constant SOURCE_DB_HOST => 'localhost'; +use constant SOURCE_DB_HOST => 'localhost'; # Settings for the 'Target' DB that you are copying to. -use constant TARGET_DB_TYPE => 'Pg'; -use constant TARGET_DB_NAME => 'bugs'; -use constant TARGET_DB_USER => 'bugs'; +use constant TARGET_DB_TYPE => 'Pg'; +use constant TARGET_DB_NAME => 'bugs'; +use constant TARGET_DB_USER => 'bugs'; use constant TARGET_DB_PASSWORD => ''; -use constant TARGET_DB_HOST => 'localhost'; +use constant TARGET_DB_HOST => 'localhost'; ##################################################################### # MAIN SCRIPT ##################################################################### -print "Connecting to the '" . SOURCE_DB_NAME . "' source database on " - . SOURCE_DB_TYPE . "...\n"; +print "Connecting to the '" + . SOURCE_DB_NAME + . "' source database on " + . SOURCE_DB_TYPE . "...\n"; my $source_db = Bugzilla::DB::_connect({ - db_driver => SOURCE_DB_TYPE, - db_host => SOURCE_DB_HOST, - db_name => SOURCE_DB_NAME, - db_user => SOURCE_DB_USER, - db_pass => SOURCE_DB_PASSWORD, + db_driver => SOURCE_DB_TYPE, + db_host => SOURCE_DB_HOST, + db_name => SOURCE_DB_NAME, + db_user => SOURCE_DB_USER, + db_pass => SOURCE_DB_PASSWORD, }); + # Don't read entire tables into memory. if (SOURCE_DB_TYPE eq 'Mysql') { - $source_db->{'mysql_use_result'} = 1; + $source_db->{'mysql_use_result'} = 1; - # MySQL cannot have two queries running at the same time. Ensure the schema - # is loaded from the database so bz_column_info will not execute a query - $source_db->_bz_real_schema; + # MySQL cannot have two queries running at the same time. Ensure the schema + # is loaded from the database so bz_column_info will not execute a query + $source_db->_bz_real_schema; } -print "Connecting to the '" . TARGET_DB_NAME . "' target database on " - . TARGET_DB_TYPE . "...\n"; +print "Connecting to the '" + . TARGET_DB_NAME + . "' target database on " + . TARGET_DB_TYPE . "...\n"; my $target_db = Bugzilla::DB::_connect({ - db_driver => TARGET_DB_TYPE, - db_host => TARGET_DB_HOST, - db_name => TARGET_DB_NAME, - db_user => TARGET_DB_USER, - db_pass => TARGET_DB_PASSWORD, + db_driver => TARGET_DB_TYPE, + db_host => TARGET_DB_HOST, + db_name => TARGET_DB_NAME, + db_user => TARGET_DB_USER, + db_pass => TARGET_DB_PASSWORD, }); -my $ident_char = $target_db->get_info( 29 ); # SQL_IDENTIFIER_QUOTE_CHAR +my $ident_char = $target_db->get_info(29); # SQL_IDENTIFIER_QUOTE_CHAR # We use the table list from the target DB, because if somebody # has customized their source DB, we still want the script to work, @@ -79,136 +84,145 @@ my @table_list = grep { $_ ne 'bz_schema' } $target_db->bz_table_list_real(); # Instead of figuring out some fancy algorithm to insert data in the right # order and not break FK integrity, we just drop them all. $target_db->bz_drop_foreign_keys(); + # We start a transaction on the target DB, which helps when we're doing # so many inserts. $target_db->bz_start_transaction(); foreach my $table (@table_list) { - my @serial_cols; - print "Reading data from the source '$table' table on " - . SOURCE_DB_TYPE . "...\n"; - my @table_columns = $target_db->bz_table_columns_real($table); - # The column names could be quoted using the quote identifier char - # Remove these chars as different databases use different quote chars - @table_columns = map { s/^\Q$ident_char\E?(.*?)\Q$ident_char\E?$/$1/; $_ } - @table_columns; - - my ($total) = $source_db->selectrow_array("SELECT COUNT(*) FROM $table"); - my $select_query = "SELECT " . join(',', @table_columns) . " FROM $table"; - my $select_sth = $source_db->prepare($select_query); - $select_sth->execute(); - - my $insert_query = "INSERT INTO $table ( " . join(',', @table_columns) - . " ) VALUES ("; - $insert_query .= '?,' foreach (@table_columns); - # Remove the last comma. - chop($insert_query); - $insert_query .= ")"; - my $insert_sth = $target_db->prepare($insert_query); - - print "Clearing out the target '$table' table on " - . TARGET_DB_TYPE . "...\n"; - $target_db->do("DELETE FROM $table"); - - # Oracle doesn't like us manually inserting into tables that have - # auto-increment PKs set, because of the way we made auto-increment - # fields work. - if ($target_db->isa('Bugzilla::DB::Oracle')) { - foreach my $column (@table_columns) { - my $col_info = $source_db->bz_column_info($table, $column); - if ($col_info && $col_info->{TYPE} =~ /SERIAL/i) { - print "Dropping the sequence + trigger on $table.$column...\n"; - $target_db->do("DROP TRIGGER ${table}_${column}_TR"); - $target_db->do("DROP SEQUENCE ${table}_${column}_SEQ"); - } - } + my @serial_cols; + print "Reading data from the source '$table' table on " + . SOURCE_DB_TYPE . "...\n"; + my @table_columns = $target_db->bz_table_columns_real($table); + + # The column names could be quoted using the quote identifier char + # Remove these chars as different databases use different quote chars + @table_columns + = map { s/^\Q$ident_char\E?(.*?)\Q$ident_char\E?$/$1/; $_ } @table_columns; + + my ($total) = $source_db->selectrow_array("SELECT COUNT(*) FROM $table"); + my $select_query = "SELECT " . join(',', @table_columns) . " FROM $table"; + my $select_sth = $source_db->prepare($select_query); + $select_sth->execute(); + + my $insert_query + = "INSERT INTO $table ( " . join(',', @table_columns) . " ) VALUES ("; + $insert_query .= '?,' foreach (@table_columns); + + # Remove the last comma. + chop($insert_query); + $insert_query .= ")"; + my $insert_sth = $target_db->prepare($insert_query); + + print "Clearing out the target '$table' table on " . TARGET_DB_TYPE . "...\n"; + $target_db->do("DELETE FROM $table"); + + # Oracle doesn't like us manually inserting into tables that have + # auto-increment PKs set, because of the way we made auto-increment + # fields work. + if ($target_db->isa('Bugzilla::DB::Oracle')) { + foreach my $column (@table_columns) { + my $col_info = $source_db->bz_column_info($table, $column); + if ($col_info && $col_info->{TYPE} =~ /SERIAL/i) { + print "Dropping the sequence + trigger on $table.$column...\n"; + $target_db->do("DROP TRIGGER ${table}_${column}_TR"); + $target_db->do("DROP SEQUENCE ${table}_${column}_SEQ"); + } } - - print "Writing data to the target '$table' table on " - . TARGET_DB_TYPE . "...\n"; - my $count = 0; - while (my $row = $select_sth->fetchrow_arrayref) { - # Each column needs to be bound separately, because - # many columns need to be dealt with specially. - my $colnum = 0; - foreach my $column (@table_columns) { - # bind_param args start at 1, but arrays start at 0. - my $param_num = $colnum + 1; - my $already_bound; - - # Certain types of columns need special handling. - my $col_info = $source_db->bz_column_info($table, $column); - if ($col_info && $col_info->{TYPE} eq 'LONGBLOB') { - $insert_sth->bind_param($param_num, - $row->[$colnum], $target_db->BLOB_TYPE); - $already_bound = 1; - } - elsif ($col_info && $col_info->{TYPE} =~ /decimal/) { - # In MySQL, decimal cols can be too long. - my $col_type = $col_info->{TYPE}; - $col_type =~ /decimal\((\d+),(\d+)\)/; - my ($precision, $decimals) = ($1, $2); - # If it's longer than precision + decimal point - if ( length($row->[$colnum]) > ($precision + 1) ) { - # Truncate it to the highest allowed value. - my $orig_value = $row->[$colnum]; - $row->[$colnum] = ''; - my $non_decimal = $precision - $decimals; - $row->[$colnum] .= '9' while ($non_decimal--); - $row->[$colnum] .= '.'; - $row->[$colnum] .= '9' while ($decimals--); - print "Truncated value $orig_value to " . $row->[$colnum] - . " for $table.$column.\n"; - } - } - elsif ($col_info && $col_info->{TYPE} =~ /DATETIME/i) { - my $date = $row->[$colnum]; - # MySQL can have strange invalid values for Datetimes. - $row->[$colnum] = '1901-01-01 00:00:00' - if $date && $date eq '0000-00-00 00:00:00'; - } - - $insert_sth->bind_param($param_num, $row->[$colnum]) - unless $already_bound; - $colnum++; - } + } - $insert_sth->execute(); - $count++; - indicate_progress({ current => $count, total => $total, every => 100 }); - } + print "Writing data to the target '$table' table on " + . TARGET_DB_TYPE . "...\n"; + my $count = 0; + while (my $row = $select_sth->fetchrow_arrayref) { - # For some DBs, we have to do clever things with auto-increment fields. + # Each column needs to be bound separately, because + # many columns need to be dealt with specially. + my $colnum = 0; foreach my $column (@table_columns) { - next if $target_db->isa('Bugzilla::DB::Mysql'); - my $col_info = $source_db->bz_column_info($table, $column); - if ($col_info && $col_info->{TYPE} =~ /SERIAL/i) { - my ($max_val) = $target_db->selectrow_array( - "SELECT MAX($column) FROM $table"); - # Set the sequence to the current max value + 1. - $max_val = 0 if !defined $max_val; - $max_val++; - print "\nSetting the next value for $table.$column to $max_val."; - if ($target_db->isa('Bugzilla::DB::Pg')) { - # PostgreSQL doesn't like it when you insert values into - # a serial field; it doesn't increment the counter - # automatically. - $target_db->bz_set_next_serial_value($table, $column); - } - elsif ($target_db->isa('Bugzilla::DB::Oracle')) { - # Oracle increments the counter on every insert, and *always* - # sets the field, even if you gave it a value. So if there - # were already rows in the target DB (like the default rows - # created by checksetup), you'll get crazy values in your - # id columns. So we just dropped the sequences above and - # we re-create them here, starting with the right number. - my @sql = $target_db->_bz_real_schema->_get_create_seq_ddl( - $table, $column, $max_val); - $target_db->do($_) foreach @sql; - } + + # bind_param args start at 1, but arrays start at 0. + my $param_num = $colnum + 1; + my $already_bound; + + # Certain types of columns need special handling. + my $col_info = $source_db->bz_column_info($table, $column); + if ($col_info && $col_info->{TYPE} eq 'LONGBLOB') { + $insert_sth->bind_param($param_num, $row->[$colnum], $target_db->BLOB_TYPE); + $already_bound = 1; + } + elsif ($col_info && $col_info->{TYPE} =~ /decimal/) { + + # In MySQL, decimal cols can be too long. + my $col_type = $col_info->{TYPE}; + $col_type =~ /decimal\((\d+),(\d+)\)/; + my ($precision, $decimals) = ($1, $2); + + # If it's longer than precision + decimal point + if (length($row->[$colnum]) > ($precision + 1)) { + + # Truncate it to the highest allowed value. + my $orig_value = $row->[$colnum]; + $row->[$colnum] = ''; + my $non_decimal = $precision - $decimals; + $row->[$colnum] .= '9' while ($non_decimal--); + $row->[$colnum] .= '.'; + $row->[$colnum] .= '9' while ($decimals--); + print "Truncated value $orig_value to " + . $row->[$colnum] + . " for $table.$column.\n"; } + } + elsif ($col_info && $col_info->{TYPE} =~ /DATETIME/i) { + my $date = $row->[$colnum]; + + # MySQL can have strange invalid values for Datetimes. + $row->[$colnum] = '1901-01-01 00:00:00' + if $date && $date eq '0000-00-00 00:00:00'; + } + + $insert_sth->bind_param($param_num, $row->[$colnum]) unless $already_bound; + $colnum++; + } + + $insert_sth->execute(); + $count++; + indicate_progress({current => $count, total => $total, every => 100}); + } + + # For some DBs, we have to do clever things with auto-increment fields. + foreach my $column (@table_columns) { + next if $target_db->isa('Bugzilla::DB::Mysql'); + my $col_info = $source_db->bz_column_info($table, $column); + if ($col_info && $col_info->{TYPE} =~ /SERIAL/i) { + my ($max_val) = $target_db->selectrow_array("SELECT MAX($column) FROM $table"); + + # Set the sequence to the current max value + 1. + $max_val = 0 if !defined $max_val; + $max_val++; + print "\nSetting the next value for $table.$column to $max_val."; + if ($target_db->isa('Bugzilla::DB::Pg')) { + + # PostgreSQL doesn't like it when you insert values into + # a serial field; it doesn't increment the counter + # automatically. + $target_db->bz_set_next_serial_value($table, $column); + } + elsif ($target_db->isa('Bugzilla::DB::Oracle')) { + + # Oracle increments the counter on every insert, and *always* + # sets the field, even if you gave it a value. So if there + # were already rows in the target DB (like the default rows + # created by checksetup), you'll get crazy values in your + # id columns. So we just dropped the sequences above and + # we re-create them here, starting with the right number. + my @sql + = $target_db->_bz_real_schema->_get_create_seq_ddl($table, $column, $max_val); + $target_db->do($_) foreach @sql; + } } + } - print "\n\n"; + print "\n\n"; } print "Committing changes to the target database...\n"; diff --git a/contrib/console.pl b/contrib/console.pl index fe2342cd9..a3e042236 100755 --- a/contrib/console.pl +++ b/contrib/console.pl @@ -20,115 +20,120 @@ use Bugzilla::Bug; use Term::ReadLine; use Data::Dumper; $Data::Dumper::Sortkeys = 1; -$Data::Dumper::Terse = 1; -$Data::Dumper::Indent = 1; -$Data::Dumper::Useqq = 1; +$Data::Dumper::Terse = 1; +$Data::Dumper::Indent = 1; +$Data::Dumper::Useqq = 1; $Data::Dumper::Maxdepth = 1; -$Data::Dumper::Deparse = 0; +$Data::Dumper::Deparse = 0; my $sysname = get_text('term', {term => 'Bugzilla'}); my $term = new Term::ReadLine "$sysname Console"; read_history($term); END { write_history($term) } -while ( defined (my $input = $term->readline("$sysname> ")) ) { - my @res = eval($input); - if ($@) { - warn $@; - } - else { - print Dumper(@res); - } +while (defined(my $input = $term->readline("$sysname> "))) { + my @res = eval($input); + if ($@) { + warn $@; + } + else { + print Dumper(@res); + } } print STDERR "\n"; exit 0; # d: full dump (normal behavior is limited to depth of 1) sub d { - local $Data::Dumper::Maxdepth = 0; - local $Data::Dumper::Deparse = 1; - print Dumper(@_); - return (); + local $Data::Dumper::Maxdepth = 0; + local $Data::Dumper::Deparse = 1; + print Dumper(@_); + return (); } # p: print as a single string (normal behavior puts list items on separate lines) sub p { - no warnings; # suppress possible undefined var message - print(@_, "\n"); - return (); + no warnings; # suppress possible undefined var message + print(@_, "\n"); + return (); } sub filter { - my $name = shift; - my $filter = Bugzilla->template->{SERVICE}->{CONTEXT}->{CONFIG}->{FILTERS}->{$name}; - if (scalar @_) { - return $filter->(@_); - } - else { - return $filter; - } + my $name = shift; + my $filter + = Bugzilla->template->{SERVICE}->{CONTEXT}->{CONFIG}->{FILTERS}->{$name}; + if (scalar @_) { + return $filter->(@_); + } + else { + return $filter; + } } -sub b { get_object('Bugzilla::Bug', @_) } -sub u { get_object('Bugzilla::User', @_) } +sub b { get_object('Bugzilla::Bug', @_) } +sub u { get_object('Bugzilla::User', @_) } sub f { get_object('Bugzilla::Field', @_) } sub get_object { - my $class = shift; - $_ = shift; - my @results = (); - - if (ref $_ eq 'HASH' && keys %$_) { - @results = @{$class->match($_)}; - } - elsif (m/^\d+$/) { - @results = ($class->new($_)); - } - elsif (m/\w/i && grep {$_ eq 'name'} ($class->_get_db_columns)) { - @results = @{$class->match({name => $_})}; - } - else { - @results = (); - } - - if (wantarray) { - return @results; - } - else { - return shift @results; - } + my $class = shift; + $_ = shift; + my @results = (); + + if (ref $_ eq 'HASH' && keys %$_) { + @results = @{$class->match($_)}; + } + elsif (m/^\d+$/) { + @results = ($class->new($_)); + } + elsif (m/\w/i && grep { $_ eq 'name' } ($class->_get_db_columns)) { + @results = @{$class->match({name => $_})}; + } + else { + @results = (); + } + + if (wantarray) { + return @results; + } + else { + return shift @results; + } } sub read_history { - my ($term) = @_; - - if (open HIST, "<$ENV{HOME}/.bugzilla_console_history") { - foreach (<HIST>) { - chomp; - $term->addhistory($_); - } - close HIST; + my ($term) = @_; + + if (open HIST, "<$ENV{HOME}/.bugzilla_console_history") { + foreach (<HIST>) { + chomp; + $term->addhistory($_); } + close HIST; + } } sub write_history { - my ($term) = @_; - - if ($term->can('GetHistory') && open HIST, ">$ENV{HOME}/.bugzilla_console_history") { - my %seen_hist = (); - my @hist = (); - foreach my $line (reverse $term->GetHistory()) { - next unless $line =~ m/\S/; - next if $seen_hist{$line}; - $seen_hist{$line} = 1; - push @hist, $line; - last if (scalar @hist > 500); - } - foreach (reverse @hist) { - print HIST $_, "\n"; - } - close HIST; + my ($term) = @_; + + if ( + $term->can('GetHistory') && open HIST, + ">$ENV{HOME}/.bugzilla_console_history" + ) + { + my %seen_hist = (); + my @hist = (); + foreach my $line (reverse $term->GetHistory()) { + next unless $line =~ m/\S/; + next if $seen_hist{$line}; + $seen_hist{$line} = 1; + push @hist, $line; + last if (scalar @hist > 500); + } + foreach (reverse @hist) { + print HIST $_, "\n"; } + close HIST; + } } __END__ diff --git a/contrib/convert-workflow.pl b/contrib/convert-workflow.pl index d9bffb7bb..f25bb0ea7 100755 --- a/contrib/convert-workflow.pl +++ b/contrib/convert-workflow.pl @@ -18,14 +18,14 @@ use Bugzilla::Search::Saved; use Bugzilla::Status; use Getopt::Long; -my $confirmed = new Bugzilla::Status({ name => 'CONFIRMED' }); -my $in_progress = new Bugzilla::Status({ name => 'IN_PROGRESS' }); +my $confirmed = new Bugzilla::Status({name => 'CONFIRMED'}); +my $in_progress = new Bugzilla::Status({name => 'IN_PROGRESS'}); if ($confirmed and $in_progress) { - print "You are already using the new workflow.\n"; - exit 1; + print "You are already using the new workflow.\n"; + exit 1; } -my $enable_unconfirmed = 0; +my $enable_unconfirmed = 0; my $result = GetOptions("enable-unconfirmed" => \$enable_unconfirmed); print <<END; @@ -44,9 +44,10 @@ Emails will not be sent for the change. END if ($enable_unconfirmed) { - print "UNCONFIRMED will be enabled in all products.\n"; -} else { - print <<END; + print "UNCONFIRMED will be enabled in all products.\n"; +} +else { + print <<END; If you also want to enable the UNCONFIRMED status in every product, restart this script with the --enable-unconfirmed option. END @@ -55,103 +56,116 @@ print "\nTo continue, press any key, or press Ctrl-C to stop this program..."; getc; my $dbh = Bugzilla->dbh; + # This is an array instead of a hash so that we can be sure that # the translation happens in the right order. In particular, we # want NEW to be renamed to CONFIRMED, instead of having REOPENED # be the one that gets renamed. my @translation = ( - [NEW => 'CONFIRMED'], - [ASSIGNED => 'IN_PROGRESS'], - [REOPENED => 'CONFIRMED'], - [CLOSED => 'VERIFIED'], + [NEW => 'CONFIRMED'], + [ASSIGNED => 'IN_PROGRESS'], + [REOPENED => 'CONFIRMED'], + [CLOSED => 'VERIFIED'], ); my $status_field = Bugzilla::Field->check('bug_status'); $dbh->bz_start_transaction(); foreach my $pair (@translation) { - my ($from, $to) = @$pair; - print "Converting $from to $to...\n"; - # There is no FK on bugs.bug_status pointing to bug_status.value, - # so it's fine to update the bugs table first. - $dbh->do('UPDATE bugs SET bug_status = ? WHERE bug_status = ?', - undef, $to, $from); - - if (Bugzilla->params->{'duplicate_or_move_bug_status'} eq $from) { - SetParam('duplicate_or_move_bug_status', $to); - write_params(); - } - - foreach my $what (qw(added removed)) { - $dbh->do("UPDATE bugs_activity SET $what = ? - WHERE fieldid = ? AND $what = ?", - undef, $to, $status_field->id, $from); - } - - # Delete any transitions where it now appears that - # a bug moved from a status to itself. - $dbh->do('DELETE FROM bugs_activity WHERE fieldid = ? AND added = removed', - undef, $status_field->id); - - # If the new status already exists, just delete the old one, but retain - # the workflow items from it. - my $new_status = new Bugzilla::Status({ name => $to }); - my $old_status = new Bugzilla::Status({ name => $from }); - - if ($new_status && $old_status) { - my $to_id = $new_status->id; - my $from_id = $old_status->id; - # The subselect collects existing transitions from the target bug status. - # The main select collects existing transitions from the renamed bug status. - # The diff tells us which transitions are missing from the target bug status. - my $missing_transitions = - $dbh->selectcol_arrayref('SELECT sw1.new_status + my ($from, $to) = @$pair; + print "Converting $from to $to...\n"; + + # There is no FK on bugs.bug_status pointing to bug_status.value, + # so it's fine to update the bugs table first. + $dbh->do('UPDATE bugs SET bug_status = ? WHERE bug_status = ?', + undef, $to, $from); + + if (Bugzilla->params->{'duplicate_or_move_bug_status'} eq $from) { + SetParam('duplicate_or_move_bug_status', $to); + write_params(); + } + + foreach my $what (qw(added removed)) { + $dbh->do( + "UPDATE bugs_activity SET $what = ? + WHERE fieldid = ? AND $what = ?", undef, $to, $status_field->id, + $from + ); + } + + # Delete any transitions where it now appears that + # a bug moved from a status to itself. + $dbh->do('DELETE FROM bugs_activity WHERE fieldid = ? AND added = removed', + undef, $status_field->id); + + # If the new status already exists, just delete the old one, but retain + # the workflow items from it. + my $new_status = new Bugzilla::Status({name => $to}); + my $old_status = new Bugzilla::Status({name => $from}); + + if ($new_status && $old_status) { + my $to_id = $new_status->id; + my $from_id = $old_status->id; + + # The subselect collects existing transitions from the target bug status. + # The main select collects existing transitions from the renamed bug status. + # The diff tells us which transitions are missing from the target bug status. + my $missing_transitions = $dbh->selectcol_arrayref( + 'SELECT sw1.new_status FROM status_workflow sw1 WHERE sw1.old_status = ? AND sw1.new_status NOT IN (SELECT sw2.new_status FROM status_workflow sw2 WHERE sw2.old_status = ?)', - undef, ($from_id, $to_id)); - - $dbh->do('UPDATE status_workflow SET old_status = ? WHERE old_status = ? AND ' - . $dbh->sql_in('new_status', $missing_transitions), - undef, ($to_id, $from_id)) if @$missing_transitions; - - # The subselect collects existing transitions to the target bug status. - # The main select collects existing transitions to the renamed bug status. - # The diff tells us which transitions are missing to the target bug status. - # We have to explicitly exclude NULL from the subselect, because NOT IN - # doesn't know what to do with it (neither true nor false) and no data is returned. - $missing_transitions = - $dbh->selectcol_arrayref('SELECT sw1.old_status + undef, ($from_id, $to_id) + ); + + $dbh->do( + 'UPDATE status_workflow SET old_status = ? WHERE old_status = ? AND ' + . $dbh->sql_in('new_status', $missing_transitions), + undef, + ($to_id, $from_id) + ) if @$missing_transitions; + + # The subselect collects existing transitions to the target bug status. + # The main select collects existing transitions to the renamed bug status. + # The diff tells us which transitions are missing to the target bug status. + # We have to explicitly exclude NULL from the subselect, because NOT IN + # doesn't know what to do with it (neither true nor false) and no data is returned. + $missing_transitions = $dbh->selectcol_arrayref( + 'SELECT sw1.old_status FROM status_workflow sw1 WHERE sw1.new_status = ? AND sw1.old_status NOT IN (SELECT sw2.old_status FROM status_workflow sw2 WHERE sw2.new_status = ? AND sw2.old_status IS NOT NULL)', - undef, ($from_id, $to_id)); - - $dbh->do('UPDATE status_workflow SET new_status = ? WHERE new_status = ? AND ' - . $dbh->sql_in('old_status', $missing_transitions), - undef, ($to_id, $from_id)) if @$missing_transitions; - - # Delete rows where old_status = new_status, and then the old status itself. - $dbh->do('DELETE FROM status_workflow WHERE old_status = new_status'); - $dbh->do('DELETE FROM bug_status WHERE value = ?', undef, $from); - } - # Otherwise, rename the old status to the new one. - elsif ($old_status) { - $dbh->do('UPDATE bug_status SET value = ? WHERE value = ?', - undef, $to, $from); - } - - Bugzilla::Search::Saved->rename_field_value('bug_status', $from, $to); - Bugzilla::Series->Bugzilla::Search::Saved::rename_field_value('bug_status', - $from, $to); + undef, ($from_id, $to_id) + ); + + $dbh->do( + 'UPDATE status_workflow SET new_status = ? WHERE new_status = ? AND ' + . $dbh->sql_in('old_status', $missing_transitions), + undef, + ($to_id, $from_id) + ) if @$missing_transitions; + + # Delete rows where old_status = new_status, and then the old status itself. + $dbh->do('DELETE FROM status_workflow WHERE old_status = new_status'); + $dbh->do('DELETE FROM bug_status WHERE value = ?', undef, $from); + } + + # Otherwise, rename the old status to the new one. + elsif ($old_status) { + $dbh->do('UPDATE bug_status SET value = ? WHERE value = ?', undef, $to, $from); + } + + Bugzilla::Search::Saved->rename_field_value('bug_status', $from, $to); + Bugzilla::Series->Bugzilla::Search::Saved::rename_field_value('bug_status', + $from, $to); } if ($enable_unconfirmed) { - print "Enabling UNCONFIRMED in all products...\n"; - $dbh->do('UPDATE products SET allows_unconfirmed = 1'); + print "Enabling UNCONFIRMED in all products...\n"; + $dbh->do('UPDATE products SET allows_unconfirmed = 1'); } $dbh->bz_commit_transaction(); Bugzilla->memcached->clear_all(); diff --git a/contrib/extension-convert.pl b/contrib/extension-convert.pl index 91a77b839..d0fc791b2 100755 --- a/contrib/extension-convert.pl +++ b/contrib/extension-convert.pl @@ -21,8 +21,7 @@ use File::Copy qw(move); use File::Find; use File::Path qw(mkpath rmtree); -my $from = $ARGV[0] - or die <<END; +my $from = $ARGV[0] or die <<END; You must specify the name of the extension you are converting from, as the first argument. END @@ -32,33 +31,33 @@ my $extdir = bz_locations()->{'extensionsdir'}; my $from_dir = "$extdir/$from"; if (!-d $from_dir) { - die "$from_dir does not exist.\n"; + die "$from_dir does not exist.\n"; } my $to_dir = "$extdir/$extension_name"; if (-d $to_dir) { - die "$to_dir already exists, not converting.\n"; + die "$to_dir already exists, not converting.\n"; } if (ON_WINDOWS) { - # There's no easy way to recursively copy a directory on Windows. - print "WARNING: This will modify the contents of $from_dir.\n", - "Press Ctrl-C to stop or any other key to continue...\n"; - getc; - move($from_dir, $to_dir) - || die "rename of $from_dir to $to_dir failed: $!"; + + # There's no easy way to recursively copy a directory on Windows. + print "WARNING: This will modify the contents of $from_dir.\n", + "Press Ctrl-C to stop or any other key to continue...\n"; + getc; + move($from_dir, $to_dir) || die "rename of $from_dir to $to_dir failed: $!"; } else { - print "Copying $from_dir to $to_dir...\n"; - system("cp", "-r", $from_dir, $to_dir); + print "Copying $from_dir to $to_dir...\n"; + system("cp", "-r", $from_dir, $to_dir); } -# Make sure we don't accidentally modify the $from_dir anywhere else +# Make sure we don't accidentally modify the $from_dir anywhere else # in this script. undef $from_dir; if (!-d $to_dir) { - die "$to_dir was not created.\n"; + die "$to_dir was not created.\n"; } my $version = get_version($to_dir); @@ -96,7 +95,7 @@ END open(my $config_fh, '>', "$to_dir/Config.pm") || die "$to_dir/Config.pm: $!"; print $config_fh $config_pm; close($config_fh); -open(my $extension_fh, '>', "$to_dir/Extension.pm") +open(my $extension_fh, '>', "$to_dir/Extension.pm") || die "$to_dir/Extension.pm: $!"; print $extension_fh $extension_pm; close($extension_fh); @@ -109,176 +108,179 @@ unlink("$to_dir/info.pl"); ############### sub rename_module_packages { - my ($dir, $name) = @_; - my $lib_dir = "$dir/lib"; - - # We don't want things like Bugzilla::Extension::Testopia::Testopia. - if (-d "$lib_dir/$name") { - print "Moving contents of $lib_dir/$name into $lib_dir...\n"; - foreach my $file (glob("$lib_dir/$name/*")) { - my $dirname = dirname($file); - my $basename = basename($file); - rename($file, "$dirname/../$basename") || warn "$file: $!\n"; - } + my ($dir, $name) = @_; + my $lib_dir = "$dir/lib"; + + # We don't want things like Bugzilla::Extension::Testopia::Testopia. + if (-d "$lib_dir/$name") { + print "Moving contents of $lib_dir/$name into $lib_dir...\n"; + foreach my $file (glob("$lib_dir/$name/*")) { + my $dirname = dirname($file); + my $basename = basename($file); + rename($file, "$dirname/../$basename") || warn "$file: $!\n"; } + } - my @modules; - find({ wanted => sub { $_ =~ /\.pm$/i and push(@modules, $_) }, - no_chdir => 1 }, $lib_dir); - my %module_rename; - foreach my $file (@modules) { - open(my $fh, '<', $file) || die "$file: $!"; - my $content = do { local $/ = undef; <$fh> }; - close($fh); - if ($content =~ /^package (\S+);/m) { - my $package = $1; - my $new_name = $file; - $new_name =~ s/^$lib_dir\///; - $new_name =~ s/\.pm$//; - $new_name = join('::', File::Spec->splitdir($new_name)); - $new_name = "Bugzilla::Extension::${name}::$new_name"; - print "Renaming $package to $new_name...\n"; - $content =~ s/^package \Q$package\E;/package \Q$new_name\E;/; - open(my $write_fh, '>', $file) || die "$file: $!"; - print $write_fh $content; - close($write_fh); - $module_rename{$package} = $new_name; - } + my @modules; + find({wanted => sub { $_ =~ /\.pm$/i and push(@modules, $_) }, no_chdir => 1}, + $lib_dir); + my %module_rename; + foreach my $file (@modules) { + open(my $fh, '<', $file) || die "$file: $!"; + my $content = do { local $/ = undef; <$fh> }; + close($fh); + if ($content =~ /^package (\S+);/m) { + my $package = $1; + my $new_name = $file; + $new_name =~ s/^$lib_dir\///; + $new_name =~ s/\.pm$//; + $new_name = join('::', File::Spec->splitdir($new_name)); + $new_name = "Bugzilla::Extension::${name}::$new_name"; + print "Renaming $package to $new_name...\n"; + $content =~ s/^package \Q$package\E;/package \Q$new_name\E;/; + open(my $write_fh, '>', $file) || die "$file: $!"; + print $write_fh $content; + close($write_fh); + $module_rename{$package} = $new_name; } + } - print "Renaming module names inside of library and code files...\n"; - my @code_files = glob("$dir/code/*.pl"); - rename_modules_internally(\%module_rename, [@modules, @code_files]); + print "Renaming module names inside of library and code files...\n"; + my @code_files = glob("$dir/code/*.pl"); + rename_modules_internally(\%module_rename, [@modules, @code_files]); } sub rename_modules_internally { - my ($rename, $files) = @_; - - # We can't use \b because :: matches \b. - my $break = qr/^|[^\w:]|$/; - foreach my $file (@$files) { - open(my $fh, '<', $file) || die "$file: $!"; - my $content = do { local $/ = undef; <$fh> }; - close($fh); - foreach my $old_name (keys %$rename) { - my $new_name = $rename->{$old_name}; - $content =~ s/($break)\Q$old_name\E($break)/$1$new_name$2/gms; - } - open(my $write_fh, '>', $file) || die "$file: $!"; - print $write_fh $content; - close($write_fh); + my ($rename, $files) = @_; + + # We can't use \b because :: matches \b. + my $break = qr/^|[^\w:]|$/; + foreach my $file (@$files) { + open(my $fh, '<', $file) || die "$file: $!"; + my $content = do { local $/ = undef; <$fh> }; + close($fh); + foreach my $old_name (keys %$rename) { + my $new_name = $rename->{$old_name}; + $content =~ s/($break)\Q$old_name\E($break)/$1$new_name$2/gms; } + open(my $write_fh, '>', $file) || die "$file: $!"; + print $write_fh $content; + close($write_fh); + } } sub get_version { - my ($dir) = @_; - print "Getting version info from info.pl...\n"; - my $info; - { - local @INC = ("$dir/lib", @INC); - $info = do "$dir/info.pl"; die $@ if $@; - } - return $info->{version}; + my ($dir) = @_; + print "Getting version info from info.pl...\n"; + my $info; + { + local @INC = ("$dir/lib", @INC); + $info = do "$dir/info.pl"; + die $@ if $@; + } + return $info->{version}; } sub get_install_requirements { - my ($dir) = @_; - my $file = "$dir/code/install-requirements.pl"; - return '' if !-f $file; - - print "Moving install-requirements.pl code into Config.pm...\n"; - my ($modules, $code) = process_code_file($file); - $modules = join('', @$modules); - $code = join('', @$code); - if ($modules) { - return "$modules\n\n$code"; - } - return $code; + my ($dir) = @_; + my $file = "$dir/code/install-requirements.pl"; + return '' if !-f $file; + + print "Moving install-requirements.pl code into Config.pm...\n"; + my ($modules, $code) = process_code_file($file); + $modules = join('', @$modules); + $code = join('', @$code); + if ($modules) { + return "$modules\n\n$code"; + } + return $code; } sub process_code_file { - my ($file) = @_; - open(my $fh, '<', $file) || die "$file: $!"; - my $stuff_started; - my (@modules, @code); - foreach my $line (<$fh>) { - $stuff_started = 1 if $line !~ /^#/; - next if !$stuff_started; - next if $line =~ /^use (warnings|strict|lib|Bugzilla)[^\w:]/; - if ($line =~ /^(?:use|require)\b/) { - push(@modules, $line); - } - else { - push(@code, $line); - } + my ($file) = @_; + open(my $fh, '<', $file) || die "$file: $!"; + my $stuff_started; + my (@modules, @code); + foreach my $line (<$fh>) { + $stuff_started = 1 if $line !~ /^#/; + next if !$stuff_started; + next if $line =~ /^use (warnings|strict|lib|Bugzilla)[^\w:]/; + if ($line =~ /^(?:use|require)\b/) { + push(@modules, $line); + } + else { + push(@code, $line); } - close $fh; - return (\@modules, \@code); + } + close $fh; + return (\@modules, \@code); } sub code_files_to_subroutines { - my ($dir) = @_; - - my @dir_files = glob("$dir/code/*.pl"); - my (@all_modules, @subroutines); - foreach my $file (@dir_files) { - next if $file =~ /install-requirements/; - print "Moving $file code into Extension.pm...\n"; - my ($modules, $code) = process_code_file($file); - my @code_lines = map { " $_" } @$code; - my $code_string = join('', @code_lines); - $code_string =~ s/Bugzilla->hook_args/\$args/g; - $code_string =~ s/my\s+\$args\s+=\s+\$args;//gs; - chomp($code_string); - push(@all_modules, @$modules); - my $name = basename($file); - $name =~ s/-/_/; - $name =~ s/\.pl$//; - - my $subroutine = <<END; + my ($dir) = @_; + + my @dir_files = glob("$dir/code/*.pl"); + my (@all_modules, @subroutines); + foreach my $file (@dir_files) { + next if $file =~ /install-requirements/; + print "Moving $file code into Extension.pm...\n"; + my ($modules, $code) = process_code_file($file); + my @code_lines = map {" $_"} @$code; + my $code_string = join('', @code_lines); + $code_string =~ s/Bugzilla->hook_args/\$args/g; + $code_string =~ s/my\s+\$args\s+=\s+\$args;//gs; + chomp($code_string); + push(@all_modules, @$modules); + my $name = basename($file); + $name =~ s/-/_/; + $name =~ s/\.pl$//; + + my $subroutine = <<END; sub $name { my (\$self, \$args) = \@_; $code_string } END - push(@subroutines, $subroutine); - } + push(@subroutines, $subroutine); + } - my %seen_modules = map { trim($_) => 1 } @all_modules; - my $module_string = join("\n", sort keys %seen_modules); - my $subroutine_string = join("\n", @subroutines); - return ($module_string, $subroutine_string); + my %seen_modules = map { trim($_) => 1 } @all_modules; + my $module_string = join("\n", sort keys %seen_modules); + my $subroutine_string = join("\n", @subroutines); + return ($module_string, $subroutine_string); } sub move_template_hooks { - my ($dir) = @_; - foreach my $lang (glob("$dir/template/*")) { - next if !_file_matters($lang); - my $hook_container = "$lang/default/hook"; - mkpath($hook_container) || warn "$hook_container: $!"; - # Hooks can be in all sorts of weird places, including - # template/default/hook. - foreach my $file (glob("$lang/*")) { - next if !_file_matters($file, 1); - my $dirname = basename($file); - print "Moving $file to $hook_container/$dirname...\n"; - rename($file, "$hook_container/$dirname") || die "move failed: $!"; - } + my ($dir) = @_; + foreach my $lang (glob("$dir/template/*")) { + next if !_file_matters($lang); + my $hook_container = "$lang/default/hook"; + mkpath($hook_container) || warn "$hook_container: $!"; + + # Hooks can be in all sorts of weird places, including + # template/default/hook. + foreach my $file (glob("$lang/*")) { + next if !_file_matters($file, 1); + my $dirname = basename($file); + print "Moving $file to $hook_container/$dirname...\n"; + rename($file, "$hook_container/$dirname") || die "move failed: $!"; } + } } sub _file_matters { - my ($path, $tmpl) = @_; - my @ignore = qw(default custom CVS); - my $file = basename($path); - return 0 if grep(lc($_) eq lc($file), @ignore); - # Hidden files - return 0 if $file =~ /^\./; - if ($tmpl) { - return 1 if $file =~ /\.tmpl$/; - } - return 0 if !-d $path; - return 1; + my ($path, $tmpl) = @_; + my @ignore = qw(default custom CVS); + my $file = basename($path); + return 0 if grep(lc($_) eq lc($file), @ignore); + + # Hidden files + return 0 if $file =~ /^\./; + if ($tmpl) { + return 1 if $file =~ /\.tmpl$/; + } + return 0 if !-d $path; + return 1; } __END__ diff --git a/contrib/merge-users.pl b/contrib/merge-users.pl index 86b209ab2..dbc9b10fe 100755 --- a/contrib/merge-users.pl +++ b/contrib/merge-users.pl @@ -44,7 +44,7 @@ use Pod::Usage; my $dbh = Bugzilla->dbh; # Display the help if called with --help or -?. -my $help = 0; +my $help = 0; my $result = GetOptions("help|?" => \$help); pod2usage(0) if $help; @@ -53,49 +53,54 @@ pod2usage(0) if $help; my $old = $ARGV[0] || die "You must specify an old user account.\n"; my $old_id; if ($old =~ /^id:(\d+)$/) { - # As the old user account may be a deleted one, we don't - # check whether this user ID is valid or not. - # If it never existed, no damage will be done. - $old_id = $1; + + # As the old user account may be a deleted one, we don't + # check whether this user ID is valid or not. + # If it never existed, no damage will be done. + $old_id = $1; } else { - trick_taint($old); - $old_id = $dbh->selectrow_array('SELECT userid FROM profiles - WHERE login_name = ?', - undef, $old); + trick_taint($old); + $old_id = $dbh->selectrow_array( + 'SELECT userid FROM profiles + WHERE login_name = ?', undef, $old + ); } if ($old_id) { - print "OK, old user account $old found; user ID: $old_id.\n"; + print "OK, old user account $old found; user ID: $old_id.\n"; } else { - die "The old user account $old does not exist.\n"; + die "The old user account $old does not exist.\n"; } my $new = $ARGV[1] || die "You must specify a new user account.\n"; my $new_id; if ($new =~ /^id:(\d+)$/) { - $new_id = $1; - # Make sure this user ID exists. - $new_id = $dbh->selectrow_array('SELECT userid FROM profiles - WHERE userid = ?', - undef, $new_id); + $new_id = $1; + + # Make sure this user ID exists. + $new_id = $dbh->selectrow_array( + 'SELECT userid FROM profiles + WHERE userid = ?', undef, $new_id + ); } else { - trick_taint($new); - $new_id = $dbh->selectrow_array('SELECT userid FROM profiles - WHERE login_name = ?', - undef, $new); + trick_taint($new); + $new_id = $dbh->selectrow_array( + 'SELECT userid FROM profiles + WHERE login_name = ?', undef, $new + ); } if ($new_id) { - print "OK, new user account $new found; user ID: $new_id.\n"; + print "OK, new user account $new found; user ID: $new_id.\n"; } else { - die "The new user account $new does not exist.\n"; + die "The new user account $new does not exist.\n"; } # Make sure the old and new accounts are different. if ($old_id == $new_id) { - die "\nBoth accounts are identical. There is nothing to migrate.\n"; + die "\nBoth accounts are identical. There is nothing to migrate.\n"; } @@ -112,32 +117,34 @@ if ($old_id == $new_id) { # We set the tables that require custom stuff (multiple columns to check) # here, but the simple stuff is all handled below by bz_get_related_fks. my %changes = ( - cc => ['who bug_id'], - # Tables affecting global behavior / other users. - component_cc => ['user_id component_id'], - watch => ['watcher watched', 'watched watcher'], - # Tables affecting the user directly. - namedqueries => ['userid name'], - namedqueries_link_in_footer => ['user_id namedquery_id'], - user_group_map => ['user_id group_id isbless grant_type'], - email_setting => ['user_id relationship event'], - profile_setting => ['user_id setting_name'], - - # Only do it if mailto_type = 0, i.e is pointing to a user account! - # This requires to be done separately due to this condition. - whine_schedules => [], # ['mailto'], + cc => ['who bug_id'], + + # Tables affecting global behavior / other users. + component_cc => ['user_id component_id'], + watch => ['watcher watched', 'watched watcher'], + + # Tables affecting the user directly. + namedqueries => ['userid name'], + namedqueries_link_in_footer => ['user_id namedquery_id'], + user_group_map => ['user_id group_id isbless grant_type'], + email_setting => ['user_id relationship event'], + profile_setting => ['user_id setting_name'], + + # Only do it if mailto_type = 0, i.e is pointing to a user account! + # This requires to be done separately due to this condition. + whine_schedules => [], # ['mailto'], ); my $userid_fks = $dbh->bz_get_related_fks('profiles', 'userid'); foreach my $item (@$userid_fks) { - my ($table, $column) = @$item; - $changes{$table} ||= []; - push(@{ $changes{$table} }, $column); + my ($table, $column) = @$item; + $changes{$table} ||= []; + push(@{$changes{$table}}, $column); } # Delete all old records for these tables; no migration. foreach my $table (qw(logincookies tokens profiles)) { - $changes{$table} = []; + $changes{$table} = []; } # Start the transaction @@ -145,7 +152,7 @@ $dbh->bz_start_transaction(); # Delete old records from logincookies and tokens tables. $dbh->do('DELETE FROM logincookies WHERE userid = ?', undef, $old_id); -$dbh->do('DELETE FROM tokens WHERE userid = ?', undef, $old_id); +$dbh->do('DELETE FROM tokens WHERE userid = ?', undef, $old_id); # Special care needs to be done with bug_user_last_visit table as the # source user and destination user may have visited the same bug id at one time. @@ -158,78 +165,87 @@ my $dupe_ids = $dbh->selectcol_arrayref(" AND earlier.last_visit_ts < later.last_visit_ts AND earlier.bug_id = later.bug_id) WHERE (earlier.user_id = ? OR earlier.user_id = ?) - AND (later.user_id = ? OR later.user_id = ?)", - undef, $old_id, $new_id, $old_id, $new_id); + AND (later.user_id = ? OR later.user_id = ?)", undef, $old_id, + $new_id, $old_id, $new_id); if (@$dupe_ids) { - $dbh->do("DELETE FROM bug_user_last_visit WHERE " . - $dbh->sql_in('id', $dupe_ids)); + $dbh->do( + "DELETE FROM bug_user_last_visit WHERE " . $dbh->sql_in('id', $dupe_ids)); } # Migrate records from old user to new user. foreach my $table (keys %changes) { - foreach my $column_list (@{ $changes{$table} }) { - # Get all columns to consider. There is always at least - # one column given: the one to update. - my @columns = split(/[\s]+/, $column_list); - my $cols_to_check = join(' AND ', map {"$_ = ?"} @columns); - # The first column of the list is the one to update. - my $col_to_update = shift @columns; - - # Will be used to migrate the old user account to the new one. - my $sth_update = $dbh->prepare("UPDATE $table + foreach my $column_list (@{$changes{$table}}) { + + # Get all columns to consider. There is always at least + # one column given: the one to update. + my @columns = split(/[\s]+/, $column_list); + my $cols_to_check = join(' AND ', map {"$_ = ?"} @columns); + + # The first column of the list is the one to update. + my $col_to_update = shift @columns; + + # Will be used to migrate the old user account to the new one. + my $sth_update = $dbh->prepare( + "UPDATE $table SET $col_to_update = ? - WHERE $cols_to_check"); + WHERE $cols_to_check" + ); - # Do we have additional columns to take care of? - if (scalar(@columns)) { - my $cols_to_query = join(', ', @columns); + # Do we have additional columns to take care of? + if (scalar(@columns)) { + my $cols_to_query = join(', ', @columns); - # Get existing entries for the old user account. - my $old_entries = - $dbh->selectall_arrayref("SELECT $cols_to_query + # Get existing entries for the old user account. + my $old_entries = $dbh->selectall_arrayref( + "SELECT $cols_to_query FROM $table - WHERE $col_to_update = ?", - undef, $old_id); + WHERE $col_to_update = ?", undef, $old_id + ); - # Will be used to check whether the same entry exists - # for the new user account. - my $sth_select = $dbh->prepare("SELECT COUNT(*) + # Will be used to check whether the same entry exists + # for the new user account. + my $sth_select = $dbh->prepare( + "SELECT COUNT(*) FROM $table - WHERE $cols_to_check"); - - # Will be used to delete duplicated entries. - my $sth_delete = $dbh->prepare("DELETE FROM $table - WHERE $cols_to_check"); - - foreach my $entry (@$old_entries) { - my $exists = $dbh->selectrow_array($sth_select, undef, - ($new_id, @$entry)); - - if ($exists) { - $sth_delete->execute($old_id, @$entry); - } - else { - $sth_update->execute($new_id, $old_id, @$entry); - } - } + WHERE $cols_to_check" + ); + + # Will be used to delete duplicated entries. + my $sth_delete = $dbh->prepare( + "DELETE FROM $table + WHERE $cols_to_check" + ); + + foreach my $entry (@$old_entries) { + my $exists = $dbh->selectrow_array($sth_select, undef, ($new_id, @$entry)); + + if ($exists) { + $sth_delete->execute($old_id, @$entry); } - # No check required. Update the column directly. else { - $sth_update->execute($new_id, $old_id); + $sth_update->execute($new_id, $old_id, @$entry); } - print "OK, records in the '$col_to_update' column of the '$table' table\n" . - "have been migrated to the new user account.\n"; + } } + + # No check required. Update the column directly. + else { + $sth_update->execute($new_id, $old_id); + } + print "OK, records in the '$col_to_update' column of the '$table' table\n" + . "have been migrated to the new user account.\n"; + } } # Only update 'whine_schedules' if mailto_type = 0. # (i.e. is pointing to a user ID). -$dbh->do('UPDATE whine_schedules SET mailto = ? - WHERE mailto = ? AND mailto_type = ?', - undef, ($new_id, $old_id, 0)); -print "OK, records in the 'mailto' column of the 'whine_schedules' table\n" . - "have been migrated to the new user account.\n"; +$dbh->do( + 'UPDATE whine_schedules SET mailto = ? + WHERE mailto = ? AND mailto_type = ?', undef, ($new_id, $old_id, 0) +); +print "OK, records in the 'mailto' column of the 'whine_schedules' table\n" + . "have been migrated to the new user account.\n"; # Delete the old record from the profiles table. $dbh->do('DELETE FROM profiles WHERE userid = ?', undef, $old_id); diff --git a/contrib/mysqld-watcher.pl b/contrib/mysqld-watcher.pl index be93dcbb5..5dbbe320a 100755 --- a/contrib/mysqld-watcher.pl +++ b/contrib/mysqld-watcher.pl @@ -8,12 +8,12 @@ # mysqld-watcher.pl - a script that watches the running instance of # mysqld and kills off any long-running SELECTs against the shadow_db -# +# use 5.10.1; use strict; use warnings; -# some configurables: +# some configurables: # length of time before a thread is eligible to be killed, in seconds # @@ -40,65 +40,70 @@ my $long = {}; # queries so we know which queries are taking too long to run, but complete # queries with line breaks get missed by this script, so we get abbreviated # queries as well to make sure we don't miss any. -foreach my $command ("/opt/mysql/bin/mysqladmin --verbose processlist", - "/opt/mysql/bin/mysqladmin processlist") +foreach my $command ( + "/opt/mysql/bin/mysqladmin --verbose processlist", + "/opt/mysql/bin/mysqladmin processlist" + ) { - close(STDIN); - open(STDIN, "$command |"); + close(STDIN); + open(STDIN, "$command |"); - # iterate through the running threads - # - while ( <STDIN> ) { - my @F = split(/\|/); + # iterate through the running threads + # + while (<STDIN>) { + my @F = split(/\|/); - # if this line is not the correct number of fields, or if the thread-id - # field contains Id, skip this line. both these cases indicate that this - # line contains pretty-printing gunk and not thread info. - # - next if ( $#F != 9 || $F[1] =~ /Id/); + # if this line is not the correct number of fields, or if the thread-id + # field contains Id, skip this line. both these cases indicate that this + # line contains pretty-printing gunk and not thread info. + # + next if ($#F != 9 || $F[1] =~ /Id/); - if ( $F[4] =~ /shadow_bugs/ # shadowbugs database in use - && $F[5] =~ /Query/ # this is actually a query - && $F[6] > $long_query_time # this query has taken too long - && $F[8] =~ /(select|SELECT)/ # only kill a select - && !defined($long->{$F[1]}) ) # haven't seen this one already - { - $long->{$F[1]} = \@F; - system("/opt/mysql/bin/mysqladmin", "kill", $F[1]); - } + if ( + $F[4] =~ /shadow_bugs/ # shadowbugs database in use + && $F[5] =~ /Query/ # this is actually a query + && $F[6] > $long_query_time # this query has taken too long + && $F[8] =~ /(select|SELECT)/ # only kill a select + && !defined($long->{$F[1]}) + ) # haven't seen this one already + { + $long->{$F[1]} = \@F; + system("/opt/mysql/bin/mysqladmin", "kill", $F[1]); } + } } # send an email message # -# should perhaps be moved to somewhere more global for use in bugzilla as a +# should perhaps be moved to somewhere more global for use in bugzilla as a # whole; should also do more error-checking # sub sendEmail($$$$) { - ($#_ == 3) || die("sendEmail: invalid number of arguments"); - my ($from, $to, $subject, $body) = @_; + ($#_ == 3) || die("sendEmail: invalid number of arguments"); + my ($from, $to, $subject, $body) = @_; + + open(MTA, "|$mta_program"); + print MTA "From: $from\n"; + print MTA "To: $to\n"; + print MTA "Subject: $subject\n"; + print MTA "\n"; + print MTA $body; + print MTA "\n"; + close(MTA); - open(MTA, "|$mta_program"); - print MTA "From: $from\n"; - print MTA "To: $to\n"; - print MTA "Subject: $subject\n"; - print MTA "\n"; - print MTA $body; - print MTA "\n"; - close(MTA); - } # if we found anything, kill the database thread and send mail about it # if (scalar(keys(%$long))) { - my $message = ""; - foreach my $process_id (keys(%$long)) { - my $qry = $long->{$process_id}; - $message .= join(" ", @$qry) . "\n\n"; - } + my $message = ""; + foreach my $process_id (keys(%$long)) { + my $qry = $long->{$process_id}; + $message .= join(" ", @$qry) . "\n\n"; + } - # fire off an email telling the maintainer that we had to kill some threads - # - sendEmail($mail_from, $mail_to, "long running MySQL thread(s) killed", $message); + # fire off an email telling the maintainer that we had to kill some threads + # + sendEmail($mail_from, $mail_to, "long running MySQL thread(s) killed", + $message); } diff --git a/contrib/recode.pl b/contrib/recode.pl index e6da47b92..9dc1d1bf5 100755 --- a/contrib/recode.pl +++ b/contrib/recode.pl @@ -32,21 +32,26 @@ use constant MAX_STRING_LEN => 25; # For certain tables, we can't automatically determine their Primary Key. # So, we specify it here as a string. use constant SPECIAL_KEYS => { - # bugs_activity since 4.4 has a unique primary key added - bugs_activity => 'bug_id,bug_when,fieldid', - profile_setting => 'user_id,setting_name', - # profiles_activity since 4.4 has a unique primary key added - profiles_activity => 'userid,profiles_when,fieldid', - setting_value => 'name,value', - # longdescs didn't used to have a PK, before 2.20. - longdescs => 'bug_id,bug_when', - # The 2.16 versions table lacked a PK - versions => 'product_id,value', - # These are all for earlier versions of Bugzilla. On a modern - # version of Bugzilla, this script will ignore these (thanks to - # code further down). - components => 'program,value', - products => 'product', + + # bugs_activity since 4.4 has a unique primary key added + bugs_activity => 'bug_id,bug_when,fieldid', + profile_setting => 'user_id,setting_name', + + # profiles_activity since 4.4 has a unique primary key added + profiles_activity => 'userid,profiles_when,fieldid', + setting_value => 'name,value', + + # longdescs didn't used to have a PK, before 2.20. + longdescs => 'bug_id,bug_when', + + # The 2.16 versions table lacked a PK + versions => 'product_id,value', + + # These are all for earlier versions of Bugzilla. On a modern + # version of Bugzilla, this script will ignore these (thanks to + # code further down). + components => 'program,value', + products => 'product', }; ############### @@ -55,18 +60,18 @@ use constant SPECIAL_KEYS => { # "truncate" is a file operation in perl, so we can't use that name. sub trunc { - my ($str) = @_; - my $truncated = substr($str, 0, MAX_STRING_LEN); - if (length($truncated) ne length($str)) { - $truncated .= '...'; - } - return $truncated; + my ($str) = @_; + my $truncated = substr($str, 0, MAX_STRING_LEN); + if (length($truncated) ne length($str)) { + $truncated .= '...'; + } + return $truncated; } sub is_valid_utf8 { - my ($str) = @_; - Encode::_utf8_on($str); - return is_utf8($str, 1); + my ($str) = @_; + Encode::_utf8_on($str); + return is_utf8($str, 1); } ############### @@ -75,170 +80,172 @@ sub is_valid_utf8 { my %switch; GetOptions(\%switch, 'dry-run', 'guess', 'charset=s', 'show-failures', - 'overrides=s', 'help|h'); + 'overrides=s', 'help|h'); -pod2usage({ -verbose => 1 }) if $switch{'help'}; +pod2usage({-verbose => 1}) if $switch{'help'}; # You have to specify at least one of these switches. -pod2usage({ -verbose => 0 }) if (!$switch{'charset'} && !$switch{'guess'}); +pod2usage({-verbose => 0}) if (!$switch{'charset'} && !$switch{'guess'}); if (exists $switch{'charset'}) { - $switch{'charset'} = resolve_alias($switch{'charset'}) - || die "'$switch{charset}' is not a valid charset."; + $switch{'charset'} = resolve_alias($switch{'charset'}) + || die "'$switch{charset}' is not a valid charset."; } if ($switch{'guess'}) { - if (!eval { require Encode::Detect::Detector }) { - my $root = ROOT_USER; - print STDERR <<EOT; + if (!eval { require Encode::Detect::Detector }) { + my $root = ROOT_USER; + print STDERR <<EOT; Using --guess requires that Encode::Detect be installed. To install Encode::Detect, run the following command: $^X install-module.pl Encode::Detect EOT - exit; - } + exit; + } } my %overrides; if (exists $switch{'overrides'}) { - my $file = new IO::File($switch{'overrides'}, 'r') - || die "$switch{overrides}: $!"; - my @lines = $file->getlines(); - $file->close(); - foreach my $line (@lines) { - chomp($line); - my ($digest, $encoding) = split(' ', $line); - $overrides{$digest} = $encoding; - } + my $file = new IO::File($switch{'overrides'}, 'r') + || die "$switch{overrides}: $!"; + my @lines = $file->getlines(); + $file->close(); + foreach my $line (@lines) { + chomp($line); + my ($digest, $encoding) = split(' ', $line); + $overrides{$digest} = $encoding; + } } my $dbh = Bugzilla->dbh; if ($dbh->isa('Bugzilla::DB::Mysql')) { - # Get the actual current encoding of the DB. - my $collation_data = $dbh->selectrow_arrayref( - "SHOW VARIABLES LIKE 'character_set_database'"); - my $db_charset = $collation_data->[1]; - # Set our connection encoding to *that* encoding, so that MySQL - # correctly accepts our changes. - $dbh->do("SET NAMES $db_charset"); - # Make the database give us raw bytes. - $dbh->do('SET character_set_results = NULL') + + # Get the actual current encoding of the DB. + my $collation_data + = $dbh->selectrow_arrayref("SHOW VARIABLES LIKE 'character_set_database'"); + my $db_charset = $collation_data->[1]; + + # Set our connection encoding to *that* encoding, so that MySQL + # correctly accepts our changes. + $dbh->do("SET NAMES $db_charset"); + + # Make the database give us raw bytes. + $dbh->do('SET character_set_results = NULL'); } $dbh->begin_work; foreach my $table ($dbh->bz_table_list_real) { - my @columns = $dbh->bz_table_columns($table); - - my $pk = SPECIAL_KEYS->{$table}; - if ($pk) { - # Assure that we're on a version of Bugzilla where those keys - # actually exist. - foreach my $column (split ',', $pk) { - $pk = undef if !$dbh->bz_column_info($table, $column); - } + my @columns = $dbh->bz_table_columns($table); + + my $pk = SPECIAL_KEYS->{$table}; + if ($pk) { + + # Assure that we're on a version of Bugzilla where those keys + # actually exist. + foreach my $column (split ',', $pk) { + $pk = undef if !$dbh->bz_column_info($table, $column); } + } - # Figure out the primary key. + # Figure out the primary key. + foreach my $column (@columns) { + my $def = $dbh->bz_column_info($table, $column); + $pk = $column if $def->{PRIMARYKEY}; + } + + # If there's no PK, it's defined by a UNIQUE index. + if (!$pk) { foreach my $column (@columns) { - my $def = $dbh->bz_column_info($table, $column); - $pk = $column if $def->{PRIMARYKEY}; - } - # If there's no PK, it's defined by a UNIQUE index. - if (!$pk) { - foreach my $column (@columns) { - my $index = $dbh->bz_index_info($table, "${table}_${column}_idx"); - if ($index && ref($index) eq 'HASH') { - $pk = join(',', @{$index->{FIELDS}}) - if $index->{TYPE} eq 'UNIQUE'; - } - } + my $index = $dbh->bz_index_info($table, "${table}_${column}_idx"); + if ($index && ref($index) eq 'HASH') { + $pk = join(',', @{$index->{FIELDS}}) if $index->{TYPE} eq 'UNIQUE'; + } } + } - foreach my $column (@columns) { - my $def = $dbh->bz_column_info($table, $column); - # If this is a text column, it may need work. - if ($def->{TYPE} =~ /text|char/i) { - # If there's still no PK, we're upgrading from 2.14 or earlier. - # We can't reliably determine the PK (or at least, I don't want to - # maintain code to record what the PK was at all points in history). - # So instead we just use the field itself. - $pk = $column if !$pk; - - print "Converting $table.$column...\n"; - my $sth = $dbh->prepare("SELECT $column, $pk FROM $table + foreach my $column (@columns) { + my $def = $dbh->bz_column_info($table, $column); + + # If this is a text column, it may need work. + if ($def->{TYPE} =~ /text|char/i) { + + # If there's still no PK, we're upgrading from 2.14 or earlier. + # We can't reliably determine the PK (or at least, I don't want to + # maintain code to record what the PK was at all points in history). + # So instead we just use the field itself. + $pk = $column if !$pk; + + print "Converting $table.$column...\n"; + my $sth = $dbh->prepare( + "SELECT $column, $pk FROM $table WHERE $column IS NOT NULL - AND $column != ''"); - - my @pk_array = map {"$_ = ?"} split(',', $pk); - my $pk_where = join(' AND ', @pk_array); - my $update_sth = $dbh->prepare( - "UPDATE $table SET $column = ? WHERE $pk_where"); - - $sth->execute(); - - while (my @result = $sth->fetchrow_array) { - my $data = shift @result; - # Wide characters cause md5_base64() to die. - my $digest_data = utf8::is_utf8($data) - ? Encode::encode_utf8($data) : $data; - my $digest = md5_base64($digest_data); - - my @primary_keys = reverse split(',', $pk); - # We copy the array so that we can pop things from it without - # affecting the original. - my @pk_data = @result; - my $pk_line = join (', ', - map { "$_ = " . pop @pk_data } @primary_keys); - - my $encoding; - if ($switch{'guess'}) { - $encoding = detect_encoding($data); - - # We only show failures if they don't appear to be - # ASCII. - if ($switch{'show-failures'} && !$encoding - && !is_valid_utf8($data)) - { - my $truncated = trunc($data); - print "Row: [$pk_line]\n", - "Failed to guess: Key: $digest", - " DATA: $truncated\n"; - } - - # If we fail a guess, and the data is valid UTF-8, - # just assume we failed because it's UTF-8. - next if is_valid_utf8($data); - } - - # If we couldn't detect the charset (or were instructed - # not to try), we fall back to --charset. If there's no - # fallback, we just do nothing. - if (!$encoding && $switch{'charset'}) { - $encoding = $switch{'charset'}; - } - - $encoding = $overrides{$digest} if $overrides{$digest}; - - # We only fix it if it's not ASCII or UTF-8 already. - if ($encoding && !grep($_ eq $encoding, IGNORE_ENCODINGS)) { - my $decoded = encode('utf8', decode($encoding, $data)); - if ($switch{'dry-run'} && $data ne $decoded) { - print "Row: [$pk_line]\n", - "From: [" . trunc($data) . "] Key: $digest\n", - "To: [" . trunc($decoded) . "]", - " Encoding : $encoding\n"; - } - else { - $update_sth->execute($decoded, @result); - } - } - } # while (my @result = $sth->fetchrow_array) - } # if ($column->{TYPE} =~ /text|char/i) - } # foreach my $column (@columns) + AND $column != ''" + ); + + my @pk_array = map {"$_ = ?"} split(',', $pk); + my $pk_where = join(' AND ', @pk_array); + my $update_sth = $dbh->prepare("UPDATE $table SET $column = ? WHERE $pk_where"); + + $sth->execute(); + + while (my @result = $sth->fetchrow_array) { + my $data = shift @result; + + # Wide characters cause md5_base64() to die. + my $digest_data = utf8::is_utf8($data) ? Encode::encode_utf8($data) : $data; + my $digest = md5_base64($digest_data); + + my @primary_keys = reverse split(',', $pk); + + # We copy the array so that we can pop things from it without + # affecting the original. + my @pk_data = @result; + my $pk_line = join(', ', map { "$_ = " . pop @pk_data } @primary_keys); + + my $encoding; + if ($switch{'guess'}) { + $encoding = detect_encoding($data); + + # We only show failures if they don't appear to be + # ASCII. + if ($switch{'show-failures'} && !$encoding && !is_valid_utf8($data)) { + my $truncated = trunc($data); + print "Row: [$pk_line]\n", "Failed to guess: Key: $digest", + " DATA: $truncated\n"; + } + + # If we fail a guess, and the data is valid UTF-8, + # just assume we failed because it's UTF-8. + next if is_valid_utf8($data); + } + + # If we couldn't detect the charset (or were instructed + # not to try), we fall back to --charset. If there's no + # fallback, we just do nothing. + if (!$encoding && $switch{'charset'}) { + $encoding = $switch{'charset'}; + } + + $encoding = $overrides{$digest} if $overrides{$digest}; + + # We only fix it if it's not ASCII or UTF-8 already. + if ($encoding && !grep($_ eq $encoding, IGNORE_ENCODINGS)) { + my $decoded = encode('utf8', decode($encoding, $data)); + if ($switch{'dry-run'} && $data ne $decoded) { + print "Row: [$pk_line]\n", "From: [" . trunc($data) . "] Key: $digest\n", + "To: [" . trunc($decoded) . "]", " Encoding : $encoding\n"; + } + else { + $update_sth->execute($decoded, @result); + } + } + } # while (my @result = $sth->fetchrow_array) + } # if ($column->{TYPE} =~ /text|char/i) + } # foreach my $column (@columns) } $dbh->commit; diff --git a/contrib/sendbugmail.pl b/contrib/sendbugmail.pl index 223d91f6c..b1b5fa8a5 100755 --- a/contrib/sendbugmail.pl +++ b/contrib/sendbugmail.pl @@ -20,16 +20,16 @@ use Bugzilla::User; my $dbh = Bugzilla->dbh; sub usage { - say STDERR "Usage: $0 bug_id user_email"; - exit; + say STDERR "Usage: $0 bug_id user_email"; + exit; } if (($#ARGV < 1) || ($#ARGV > 2)) { - usage(); + usage(); } # Get the arguments. -my $bugnum = $ARGV[0]; +my $bugnum = $ARGV[0]; my $changer = $ARGV[1]; # Validate the bug number. @@ -40,8 +40,8 @@ if (!($bugnum =~ /^(\d+)$/)) { detaint_natural($bugnum); -my ($id) = $dbh->selectrow_array("SELECT bug_id FROM bugs WHERE bug_id = ?", - undef, $bugnum); +my ($id) = $dbh->selectrow_array("SELECT bug_id FROM bugs WHERE bug_id = ?", + undef, $bugnum); if (!$id) { say STDERR "Bug number $bugnum does not exist."; @@ -51,25 +51,26 @@ if (!$id) { # Validate the changer address. my $match = Bugzilla->params->{'emailregexp'}; if ($changer !~ /$match/) { - say STDERR "Changer \"$changer\" doesn't match email regular expression."; - usage(); + say STDERR "Changer \"$changer\" doesn't match email regular expression."; + usage(); } -my $changer_user = new Bugzilla::User({ name => $changer }); +my $changer_user = new Bugzilla::User({name => $changer}); unless ($changer_user) { - say STDERR "\"$changer\" is not a valid user."; - usage(); + say STDERR "\"$changer\" is not a valid user."; + usage(); } # Send the email. -my $outputref = Bugzilla::BugMail::Send($bugnum, {'changer' => $changer_user }); +my $outputref = Bugzilla::BugMail::Send($bugnum, {'changer' => $changer_user}); # Report the results. my $sent = scalar(@{$outputref->{sent}}); if ($sent) { - say "email sent to $sent recipients:"; -} else { - say "No email sent."; + say "email sent to $sent recipients:"; +} +else { + say "No email sent."; } foreach my $sent (@{$outputref->{sent}}) { @@ -78,12 +79,12 @@ foreach my $sent (@{$outputref->{sent}}) { # This document is copyright (C) 2004 Perforce Software, Inc. All rights # reserved. -# +# # Redistribution and use of this document in any form, with or without # modification, is permitted provided that redistributions of this # document retain the above copyright notice, this condition and the # following disclaimer. -# +# # THIS DOCUMENT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A diff --git a/contrib/sendunsentbugmail.pl b/contrib/sendunsentbugmail.pl index b9034aa8d..58bde594c 100755 --- a/contrib/sendunsentbugmail.pl +++ b/contrib/sendunsentbugmail.pl @@ -19,28 +19,28 @@ use Bugzilla::BugMail; my $dbh = Bugzilla->dbh; my $list = $dbh->selectcol_arrayref( - 'SELECT bug_id FROM bugs + 'SELECT bug_id FROM bugs WHERE (lastdiffed IS NULL OR lastdiffed < delta_ts) AND delta_ts < ' - . $dbh->sql_date_math('NOW()', '-', 30, 'MINUTE') . - ' ORDER BY bug_id'); + . $dbh->sql_date_math('NOW()', '-', 30, 'MINUTE') . ' ORDER BY bug_id' +); if (scalar(@$list) > 0) { - say "OK, now attempting to send unsent mail"; - say scalar(@$list) . " bugs found with possibly unsent mail.\n"; - foreach my $bugid (@$list) { - my $start_time = time; - say "Sending mail for bug $bugid..."; - my $outputref = Bugzilla::BugMail::Send($bugid); - if ($ARGV[0] && $ARGV[0] eq "--report") { - say "Mail sent to:"; - say $_ foreach (sort @{$outputref->{sent}}); - } - else { - my $sent = scalar @{$outputref->{sent}}; - say "$sent mails sent."; - say "Took " . (time - $start_time) . " seconds.\n"; - } + say "OK, now attempting to send unsent mail"; + say scalar(@$list) . " bugs found with possibly unsent mail.\n"; + foreach my $bugid (@$list) { + my $start_time = time; + say "Sending mail for bug $bugid..."; + my $outputref = Bugzilla::BugMail::Send($bugid); + if ($ARGV[0] && $ARGV[0] eq "--report") { + say "Mail sent to:"; + say $_ foreach (sort @{$outputref->{sent}}); } - say "Unsent mail has been sent."; + else { + my $sent = scalar @{$outputref->{sent}}; + say "$sent mails sent."; + say "Took " . (time - $start_time) . " seconds.\n"; + } + } + say "Unsent mail has been sent."; } diff --git a/contrib/syncLDAP.pl b/contrib/syncLDAP.pl index f618624ec..0ffcba5be 100755 --- a/contrib/syncLDAP.pl +++ b/contrib/syncLDAP.pl @@ -19,47 +19,49 @@ use Bugzilla::User; my $cgi = Bugzilla->cgi; my $dbh = Bugzilla->dbh; -my $readonly = 0; +my $readonly = 0; my $nodisable = 0; -my $noupdate = 0; -my $nocreate = 0; -my $quiet = 0; +my $noupdate = 0; +my $nocreate = 0; +my $quiet = 0; ### # Do some preparations ### -foreach my $arg (@ARGV) -{ - if($arg eq '-r') { - $readonly = 1; - } - elsif($arg eq '-d') { - $nodisable = 1; - } - elsif($arg eq '-u') { - $noupdate = 1; - } - elsif($arg eq '-c') { - $nocreate = 1; - } - elsif($arg eq '-q') { - $quiet = 1; - } - else { - print "LDAP Sync Script\n"; - print "Syncronizes the users table from the LDAP server with the Bugzilla users.\n"; - print "Takes mail-attribute from preferences and description from 'cn' or,\n"; - print "if not available, from the uid-attribute.\n\n"; - print "usage:\n syncLDAP.pl [options]\n\n"; - print "options:\n"; - print " -r Readonly, do not make changes to Bugzilla tables\n"; - print " -d No disable, don't disable login by users who are not in LDAP\n"; - print " -u No update, don't update users, which have different description in LDAP\n"; - print " -c No create, don't create users, which are in LDAP but not in Bugzilla\n"; - print " -q Quiet mode, give less output\n"; - print "\n"; - exit; - } +foreach my $arg (@ARGV) { + if ($arg eq '-r') { + $readonly = 1; + } + elsif ($arg eq '-d') { + $nodisable = 1; + } + elsif ($arg eq '-u') { + $noupdate = 1; + } + elsif ($arg eq '-c') { + $nocreate = 1; + } + elsif ($arg eq '-q') { + $quiet = 1; + } + else { + print "LDAP Sync Script\n"; + print + "Syncronizes the users table from the LDAP server with the Bugzilla users.\n"; + print "Takes mail-attribute from preferences and description from 'cn' or,\n"; + print "if not available, from the uid-attribute.\n\n"; + print "usage:\n syncLDAP.pl [options]\n\n"; + print "options:\n"; + print " -r Readonly, do not make changes to Bugzilla tables\n"; + print " -d No disable, don't disable login by users who are not in LDAP\n"; + print + " -u No update, don't update users, which have different description in LDAP\n"; + print + " -c No create, don't create users, which are in LDAP but not in Bugzilla\n"; + print " -q Quiet mode, give less output\n"; + print "\n"; + exit; + } } my %ldap_users; @@ -67,13 +69,18 @@ my %ldap_users; ### # Get current bugzilla users ### -my %bugzilla_users = %{ $dbh->selectall_hashref( - 'SELECT login_name AS new_login_name, realname, disabledtext ' . - 'FROM profiles', 'new_login_name') }; +my %bugzilla_users = %{ + $dbh->selectall_hashref( + 'SELECT login_name AS new_login_name, realname, disabledtext ' + . 'FROM profiles', + 'new_login_name' + ) +}; foreach my $login_name (keys %bugzilla_users) { - # remove whitespaces - $bugzilla_users{$login_name}{'realname'} =~ s/^\s+|\s+$//g; + + # remove whitespaces + $bugzilla_users{$login_name}{'realname'} =~ s/^\s+|\s+$//g; } ### @@ -81,72 +88,79 @@ foreach my $login_name (keys %bugzilla_users) { ### my $LDAPserver = Bugzilla->params->{"LDAPserver"}; if ($LDAPserver eq "") { - print "No LDAP server defined in bugzilla preferences.\n"; - exit; + print "No LDAP server defined in bugzilla preferences.\n"; + exit; } my $LDAPconn; -if($LDAPserver =~ /:\/\//) { - # if the "LDAPserver" parameter is in uri scheme - $LDAPconn = Net::LDAP->new($LDAPserver, version => 3); -} else { - my $LDAPport = "389"; # default LDAP port - if($LDAPserver =~ /:/) { - ($LDAPserver, $LDAPport) = split(":",$LDAPserver); - } - $LDAPconn = Net::LDAP->new($LDAPserver, port => $LDAPport, version => 3); +if ($LDAPserver =~ /:\/\//) { + + # if the "LDAPserver" parameter is in uri scheme + $LDAPconn = Net::LDAP->new($LDAPserver, version => 3); +} +else { + my $LDAPport = "389"; # default LDAP port + if ($LDAPserver =~ /:/) { + ($LDAPserver, $LDAPport) = split(":", $LDAPserver); + } + $LDAPconn = Net::LDAP->new($LDAPserver, port => $LDAPport, version => 3); } -if(!$LDAPconn) { - print "Connecting to LDAP server failed. Check LDAPserver setting.\n"; - exit; +if (!$LDAPconn) { + print "Connecting to LDAP server failed. Check LDAPserver setting.\n"; + exit; } my $mesg; if (Bugzilla->params->{"LDAPbinddn"}) { - my ($LDAPbinddn,$LDAPbindpass) = split(":",Bugzilla->params->{"LDAPbinddn"}); - $mesg = $LDAPconn->bind($LDAPbinddn, password => $LDAPbindpass); + my ($LDAPbinddn, $LDAPbindpass) = split(":", Bugzilla->params->{"LDAPbinddn"}); + $mesg = $LDAPconn->bind($LDAPbinddn, password => $LDAPbindpass); } else { - $mesg = $LDAPconn->bind(); + $mesg = $LDAPconn->bind(); } -if($mesg->code) { - print "Binding to LDAP server failed: " . $mesg->error . "\nCheck LDAPbinddn setting.\n"; - exit; +if ($mesg->code) { + print "Binding to LDAP server failed: " + . $mesg->error + . "\nCheck LDAPbinddn setting.\n"; + exit; } # We've got our anonymous bind; let's look up the users. -$mesg = $LDAPconn->search( base => Bugzilla->params->{"LDAPBaseDN"}, - scope => "sub", - filter => '(&(' . Bugzilla->params->{"LDAPuidattribute"} . "=*)" . Bugzilla->params->{"LDAPfilter"} . ')', - ); - - -if(! $mesg->count) { - print "LDAP lookup failure. Check LDAPBaseDN setting.\n"; - exit; +$mesg = $LDAPconn->search( + base => Bugzilla->params->{"LDAPBaseDN"}, + scope => "sub", + filter => '(&(' + . Bugzilla->params->{"LDAPuidattribute"} . "=*)" + . Bugzilla->params->{"LDAPfilter"} . ')', +); + + +if (!$mesg->count) { + print "LDAP lookup failure. Check LDAPBaseDN setting.\n"; + exit; } - -my %val = %{ $mesg->as_struct }; - -while( my ($key, $value) = each(%val) ) { - - my @login_name = @{ $value->{Bugzilla->params->{"LDAPmailattribute"}} }; - my @realname = @{ $value->{"cn"} }; - - # no mail entered? go to next - if(! @login_name) { - print "$key has no valid mail address\n"; - next; - } - - # no cn entered? use uid instead - if(! @realname) { - @realname = @{ $value->{Bugzilla->params->{"LDAPuidattribute"}} }; - } - - my $login = shift @login_name; - my $real = shift @realname; - $ldap_users{$login} = { realname => $real }; + +my %val = %{$mesg->as_struct}; + +while (my ($key, $value) = each(%val)) { + + my @login_name = @{$value->{Bugzilla->params->{"LDAPmailattribute"}}}; + my @realname = @{$value->{"cn"}}; + + # no mail entered? go to next + if (!@login_name) { + print "$key has no valid mail address\n"; + next; + } + + # no cn entered? use uid instead + if (!@realname) { + @realname = @{$value->{Bugzilla->params->{"LDAPuidattribute"}}}; + } + + my $login = shift @login_name; + my $real = shift @realname; + $ldap_users{$login} = {realname => $real}; } print "\n" unless $quiet; @@ -159,120 +173,125 @@ my %update_users; my %create_users; print "Bugzilla-Users: \n" unless $quiet; -while( my ($key, $value) = each(%bugzilla_users) ) { - print " " . $key . " '" . $value->{'realname'} . "' " . $value->{'disabledtext'} ."\n" unless $quiet==1; - if(!exists $ldap_users{$key}){ - if($value->{'disabledtext'} eq '') { - $disable_users{$key} = $value; - } +while (my ($key, $value) = each(%bugzilla_users)) { + print " " + . $key . " '" + . $value->{'realname'} . "' " + . $value->{'disabledtext'} . "\n" + unless $quiet == 1; + if (!exists $ldap_users{$key}) { + if ($value->{'disabledtext'} eq '') { + $disable_users{$key} = $value; + } } } print "\nLDAP-Users: \n" unless $quiet; -while( my ($key, $value) = each(%ldap_users) ) { - print " " . $key . " '" . $value->{'realname'} . "'\n" unless $quiet==1; - if(!defined $bugzilla_users{$key}){ +while (my ($key, $value) = each(%ldap_users)) { + print " " . $key . " '" . $value->{'realname'} . "'\n" unless $quiet == 1; + if (!defined $bugzilla_users{$key}) { $create_users{$key} = $value; } - else { + else { my $bugzilla_user_value = $bugzilla_users{$key}; - if($bugzilla_user_value->{'realname'} ne $value->{'realname'}) { + if ($bugzilla_user_value->{'realname'} ne $value->{'realname'}) { $update_users{$key} = $value; } } } print "\nDetecting email changes: \n" unless $quiet; -while( my ($create_key, $create_value) = each(%create_users) ) { - while( my ($disable_key, $disable_value) = each(%disable_users) ) { - if($create_value->{'realname'} eq $disable_value->{'realname'}) { - print " " . $disable_key . " => " . $create_key ."'\n" unless $quiet==1; - $update_users{$disable_key} = { realname => $create_value->{'realname'}, - new_login_name => $create_key }; - delete $create_users{$create_key}; - delete $disable_users{$disable_key}; +while (my ($create_key, $create_value) = each(%create_users)) { + while (my ($disable_key, $disable_value) = each(%disable_users)) { + if ($create_value->{'realname'} eq $disable_value->{'realname'}) { + print " " . $disable_key . " => " . $create_key . "'\n" unless $quiet == 1; + $update_users{$disable_key} + = {realname => $create_value->{'realname'}, new_login_name => $create_key}; + delete $create_users{$create_key}; + delete $disable_users{$disable_key}; } } } -if($quiet == 0) { - print "\nUsers to disable login for: \n"; - while( my ($key, $value) = each(%disable_users) ) { - print " " . $key . " '" . $value->{'realname'} . "'\n"; - } - - print "\nUsers to update: \n"; - while( my ($key, $value) = each(%update_users) ) { - print " " . $key . " '" . $value->{'realname'} . "' "; - if(defined $value->{'new_login_name'}) { - print "has changed email to " . $value->{'new_login_name'}; - } - print "\n"; - } - - print "\nUsers to create: \n"; - while( my ($key, $value) = each(%create_users) ) { - print " " . $key . " '" . $value->{'realname'} . "'\n"; - } - - print "\n\n"; +if ($quiet == 0) { + print "\nUsers to disable login for: \n"; + while (my ($key, $value) = each(%disable_users)) { + print " " . $key . " '" . $value->{'realname'} . "'\n"; + } + + print "\nUsers to update: \n"; + while (my ($key, $value) = each(%update_users)) { + print " " . $key . " '" . $value->{'realname'} . "' "; + if (defined $value->{'new_login_name'}) { + print "has changed email to " . $value->{'new_login_name'}; + } + print "\n"; + } + + print "\nUsers to create: \n"; + while (my ($key, $value) = each(%create_users)) { + print " " . $key . " '" . $value->{'realname'} . "'\n"; + } + + print "\n\n"; } ### # now do the DB-Update ### -if($readonly == 0) { - print "Performing DB update:\nPhase 1: disabling login for users not in LDAP... " unless $quiet; +if ($readonly == 0) { + print + "Performing DB update:\nPhase 1: disabling login for users not in LDAP... " + unless $quiet; - my $sth_disable = $dbh->prepare( - 'UPDATE profiles + my $sth_disable = $dbh->prepare( + 'UPDATE profiles SET disabledtext = ? - WHERE ' . $dbh->sql_istrcmp('login_name', '?')); + WHERE ' . $dbh->sql_istrcmp('login_name', '?') + ); - if($nodisable == 0) { - while( my ($key, $value) = each(%disable_users) ) { - $sth_disable->execute('auto-disabled by ldap sync', $key); - } - print "done!\n" unless $quiet; - } - else { - print "disabled!\n" unless $quiet; - } - - print "Phase 2: updating existing users... " unless $quiet; - - if($noupdate == 0) { - while( my ($key, $value) = each(%update_users) ) { - my $user = Bugzilla::User->check($key); - if(defined $value->{'new_login_name'}) { - $user->set_login($value->{'new_login_name'}); - } else { - $user->set_name($value->{'realname'}); - } - $user->update(); + if ($nodisable == 0) { + while (my ($key, $value) = each(%disable_users)) { + $sth_disable->execute('auto-disabled by ldap sync', $key); + } + print "done!\n" unless $quiet; + } + else { + print "disabled!\n" unless $quiet; + } + + print "Phase 2: updating existing users... " unless $quiet; + + if ($noupdate == 0) { + while (my ($key, $value) = each(%update_users)) { + my $user = Bugzilla::User->check($key); + if (defined $value->{'new_login_name'}) { + $user->set_login($value->{'new_login_name'}); } - print "done!\n" unless $quiet; - } - else { - print "disabled!\n" unless $quiet; - } - - print "Phase 3: creating new users... " unless $quiet; - if($nocreate == 0) { - while( my ($key, $value) = each(%create_users) ) { - Bugzilla::User->create({ - login_name => $key, - realname => $value->{'realname'}, - cryptpassword => '*'}); + else { + $user->set_name($value->{'realname'}); } - print "done!\n" unless $quiet; - } - else { - print "disabled!\n" unless $quiet; - } + $user->update(); + } + print "done!\n" unless $quiet; + } + else { + print "disabled!\n" unless $quiet; + } + + print "Phase 3: creating new users... " unless $quiet; + if ($nocreate == 0) { + while (my ($key, $value) = each(%create_users)) { + Bugzilla::User->create( + {login_name => $key, realname => $value->{'realname'}, cryptpassword => '*'}); + } + print "done!\n" unless $quiet; + } + else { + print "disabled!\n" unless $quiet; + } } -else -{ - print "No changes to DB because readonly mode\n" unless $quiet; +else { + print "No changes to DB because readonly mode\n" unless $quiet; } |