diff options
Diffstat (limited to 'Bugzilla/Install')
-rw-r--r-- | Bugzilla/Install/CPAN.pm | 27 | ||||
-rw-r--r-- | Bugzilla/Install/DB.pm | 120 | ||||
-rw-r--r-- | Bugzilla/Install/Filesystem.pm | 180 | ||||
-rw-r--r-- | Bugzilla/Install/Localconfig.pm | 24 | ||||
-rw-r--r-- | Bugzilla/Install/Requirements.pm | 133 | ||||
-rw-r--r-- | Bugzilla/Install/Util.pm | 82 |
6 files changed, 421 insertions, 145 deletions
diff --git a/Bugzilla/Install/CPAN.pm b/Bugzilla/Install/CPAN.pm index 8a880df80..094784e1a 100644 --- a/Bugzilla/Install/CPAN.pm +++ b/Bugzilla/Install/CPAN.pm @@ -6,8 +6,12 @@ # defined by the Mozilla Public License, v. 2.0. package Bugzilla::Install::CPAN; + +use 5.10.1; use strict; -use base qw(Exporter); +use warnings; + +use parent qw(Exporter); our @EXPORT = qw( BZ_LIB @@ -161,20 +165,9 @@ sub install_module { if (!$module) { die install_string('no_such_module', { module => $name }) . "\n"; } - my $version = $module->cpan_version; - my $module_name = $name; - - if ($name eq 'LWP::UserAgent' && $^V lt v5.8.8) { - # LWP 6.x requires Perl 5.8.8 or newer. - # As PAUSE only indexes the very last version of each module, - # we have to specify the path to the tarball ourselves. - $name = 'GAAS/libwww-perl-5.837.tar.gz'; - # This tarball contains LWP::UserAgent 5.835. - $version = '5.835'; - } print install_string('install_module', - { module => $module_name, version => $version }) . "\n"; + { module => $name, version => $module->cpan_version }) . "\n"; if ($test) { CPAN::Shell->force('install', $name); @@ -336,3 +329,11 @@ Note that calling this function prints a B<lot> of information to STDOUT and STDERR. =back + +=head1 B<Methods in need of POD> + +=over + +=item check_cpan_requirements + +=back diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 023ef7523..96f14ec0f 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -10,7 +10,9 @@ package Bugzilla::Install::DB; # NOTE: This package may "use" any modules that it likes, # localconfig is available, and params are up to date. +use 5.10.1; use strict; +use warnings; use Bugzilla::Constants; use Bugzilla::Hook; @@ -23,6 +25,7 @@ use Bugzilla::Field; use Date::Parse; use Date::Format; +use Digest; use IO::File; use List::MoreUtils qw(uniq); use URI; @@ -270,10 +273,6 @@ sub update_table_definitions { $dbh->bz_add_column('attachments', 'isprivate', {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'}); - $dbh->bz_add_column("bugs", "alias", {TYPE => "varchar(20)"}); - $dbh->bz_add_index('bugs', 'bugs_alias_idx', - {TYPE => 'UNIQUE', FIELDS => [qw(alias)]}); - _move_quips_into_db(); $dbh->bz_drop_column("namedqueries", "watchfordiffs"); @@ -700,12 +699,36 @@ sub update_table_definitions { # 2012-08-01 koosha.khajeh@gmail.com - Bug 187753 _shorten_long_quips(); - # 2012-12-23 LpSolit@gmail.com - Bug 824361 + # 2012-12-29 reed@reedloden.com - Bug 785283 + _add_password_salt_separator(); + + # 2013-01-02 LpSolit@gmail.com - Bug 824361 _fix_longdescs_indexes(); # 2013-02-04 dkl@mozilla.com - Bug 824346 _fix_flagclusions_indexes(); + # 2013-08-26 sgreen@redhat.com - Bug 903895 + _fix_components_primary_key(); + + # 2014-06-09 dylan@mozilla.com - Bug 1022923 + $dbh->bz_add_index('bug_user_last_visit', + 'bug_user_last_visit_last_visit_ts_idx', + ['last_visit_ts']); + + # 2014-07-14 sgreen@redhat.com - Bug 726696 + $dbh->bz_alter_column('tokens', 'tokentype', + {TYPE => 'varchar(16)', NOTNULL => 1}); + + # 2014-07-27 LpSolit@gmail.com - Bug 1044561 + _fix_user_api_keys_indexes(); + + # 2014-08-11 sgreen@redhat.com - Bug 1012506 + _update_alias(); + + # 2014-11-10 dkl@mozilla.com - Bug 1093928 + $dbh->bz_drop_column('longdescs', 'is_markdown'); + ################################################################ # New --TABLE-- changes should go *** A B O V E *** this point # ################################################################ @@ -863,8 +886,8 @@ sub _populate_longdescs { if (!$who) { # This username doesn't exist. Maybe someone - # renamed him or something. Invent a new profile - # entry disabled, just to represent him. + # renamed them or something. Invent a new profile + # entry disabled, just to represent them. $dbh->do("INSERT INTO profiles (login_name, cryptpassword, disabledtext) VALUES (?,?,?)", undef, $name, '*', @@ -1424,9 +1447,9 @@ sub _use_ids_for_products_and_components { print "Updating the database to use component IDs.\n"; $dbh->bz_add_column("components", "id", - {TYPE => 'SMALLSERIAL', NOTNULL => 1, PRIMARYKEY => 1}); + {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1}); $dbh->bz_add_column("bugs", "component_id", - {TYPE => 'INT2', NOTNULL => 1}, 0); + {TYPE => 'INT3', NOTNULL => 1}, 0); my %components; $sth = $dbh->prepare("SELECT id, value, product_id FROM components"); @@ -2537,7 +2560,7 @@ sub _fix_whine_queries_title_and_op_sys_value { undef, "Other", "other"); if (Bugzilla->params->{'defaultopsys'} eq 'other') { # We can't actually fix the param here, because WriteParams() will - # make $datadir/params unwriteable to the webservergroup. + # make $datadir/params.json unwriteable to the webservergroup. # It's too much of an ugly hack to copy the permission-fixing code # down to here. (It would create more potential future bugs than # it would solve problems.) @@ -3785,6 +3808,39 @@ sub _shorten_long_quips { $dbh->bz_alter_column('quips', 'quip', { TYPE => 'varchar(512)', NOTNULL => 1}); } +sub _add_password_salt_separator { + my $dbh = Bugzilla->dbh; + + $dbh->bz_start_transaction(); + + my $profiles = $dbh->selectall_arrayref("SELECT userid, cryptpassword FROM profiles WHERE (" + . $dbh->sql_regexp("cryptpassword", "'^[^,]+{'") . ")"); + + if (@$profiles) { + say "Adding salt separator to password hashes..."; + + my $query = $dbh->prepare("UPDATE profiles SET cryptpassword = ? WHERE userid = ?"); + my %algo_sizes; + + foreach my $profile (@$profiles) { + my ($userid, $hash) = @$profile; + my ($algorithm) = $hash =~ /{([^}]+)}$/; + + $algo_sizes{$algorithm} ||= length(Digest->new($algorithm)->b64digest); + + # Calculate the salt length by taking the stored hash and + # subtracting the combined lengths of the hash size, the + # algorithm name, and 2 for the {} surrounding the name. + my $not_salt_len = $algo_sizes{$algorithm} + length($algorithm) + 2; + my $salt_len = length($hash) - $not_salt_len; + + substr($hash, $salt_len, 0, ','); + $query->execute($hash, $userid); + } + } + $dbh->bz_commit_transaction(); +} + sub _fix_flagclusions_indexes { my $dbh = Bugzilla->dbh; foreach my $table ('flaginclusions', 'flagexclusions') { @@ -3814,6 +3870,50 @@ sub _fix_flagclusions_indexes { } } +sub _fix_components_primary_key { + my $dbh = Bugzilla->dbh; + if ($dbh->bz_column_info('components', 'id')->{TYPE} ne 'MEDIUMSERIAL') { + $dbh->bz_drop_related_fks('components', 'id'); + $dbh->bz_alter_column("components", "id", + {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1}); + $dbh->bz_alter_column("flaginclusions", "component_id", + {TYPE => 'INT3'}); + $dbh->bz_alter_column("flagexclusions", "component_id", + {TYPE => 'INT3'}); + $dbh->bz_alter_column("bugs", "component_id", + {TYPE => 'INT3', NOTNULL => 1}); + $dbh->bz_alter_column("component_cc", "component_id", + {TYPE => 'INT3', NOTNULL => 1}); + } +} + +sub _fix_user_api_keys_indexes { + my $dbh = Bugzilla->dbh; + + if ($dbh->bz_index_info('user_api_keys', 'user_api_keys_key')) { + $dbh->bz_drop_index('user_api_keys', 'user_api_keys_key'); + $dbh->bz_add_index('user_api_keys', 'user_api_keys_api_key_idx', + { FIELDS => ['api_key'], TYPE => 'UNIQUE' }); + } + if ($dbh->bz_index_info('user_api_keys', 'user_api_keys_user_id')) { + $dbh->bz_drop_index('user_api_keys', 'user_api_keys_user_id'); + $dbh->bz_add_index('user_api_keys', 'user_api_keys_user_id_idx', ['user_id']); + } +} + +sub _update_alias { + my $dbh = Bugzilla->dbh; + return unless $dbh->bz_column_info('bugs', 'alias'); + + # We need to move the aliases from the bugs table to the bugs_aliases table + $dbh->do(q{ + INSERT INTO bugs_aliases (bug_id, alias) + SELECT bug_id, alias FROM bugs WHERE alias IS NOT NULL + }); + + $dbh->bz_drop_column('bugs', 'alias'); +} + 1; __END__ diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 9721c1702..5003047c3 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -15,7 +15,9 @@ package Bugzilla::Install::Filesystem; # * Files do not have the correct permissions. # * The database does not exist. +use 5.10.1; use strict; +use warnings; use Bugzilla::Constants; use Bugzilla::Error; @@ -28,10 +30,12 @@ use File::Find; use File::Path; use File::Basename; use File::Copy qw(move); +use File::Spec; +use File::Slurp; use IO::File; use POSIX (); -use base qw(Exporter); +use parent qw(Exporter); our @EXPORT = qw( update_filesystem create_htaccess @@ -57,7 +61,7 @@ use constant HT_DEFAULT_DENY => <<EOT; </IfVersion> </IfModule> <IfModule !mod_version.c> - Deny from all + Deny from all </IfModule> EOT @@ -130,6 +134,7 @@ sub FILESYSTEM { my $localconfig = bz_locations()->{'localconfig'}; my $template_cache = bz_locations()->{'template_cache'}; my $graphsdir = bz_locations()->{'graphsdir'}; + my $assetsdir = bz_locations()->{'assetsdir'}; # We want to set the permissions the same for all localconfig files # across all PROJECTs, so we do something special with $localconfig, @@ -165,6 +170,7 @@ sub FILESYSTEM { 'jobqueue.pl' => { perms => WS_EXECUTE }, 'migrate.pl' => { perms => OWNER_EXECUTE }, 'install-module.pl' => { perms => OWNER_EXECUTE }, + 'clean-bug-user-last-visit.pl' => { perms => WS_EXECUTE }, 'Bugzilla.pm' => { perms => CGI_READ }, "$localconfig*" => { perms => CGI_READ }, @@ -181,7 +187,7 @@ sub FILESYSTEM { 'docs/style.css' => { perms => WS_SERVE }, 'docs/*/rel_notes.txt' => { perms => WS_SERVE }, 'docs/*/README.docs' => { perms => OWNER_WRITE }, - "$datadir/params" => { perms => CGI_WRITE }, + "$datadir/params.json" => { perms => CGI_WRITE }, "$datadir/old-params.txt" => { perms => OWNER_WRITE }, "$extensionsdir/create.pl" => { perms => OWNER_EXECUTE }, "$extensionsdir/*/*.pl" => { perms => WS_EXECUTE }, @@ -211,6 +217,8 @@ sub FILESYSTEM { dirs => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE }, "$datadir/db" => { files => CGI_WRITE, dirs => DIR_CGI_WRITE }, + $assetsdir => { files => WS_SERVE, + dirs => DIR_CGI_OVERWRITE | DIR_ALSO_WS_SERVE }, # Readable directories "$datadir/mining" => { files => CGI_READ, @@ -270,7 +278,8 @@ sub FILESYSTEM { # The name of each directory that we should actually *create*, # pointing at its default permissions. my %create_dirs = ( - # This is DIR_ALSO_WS_SERVE because it contains $webdotdir. + # This is DIR_ALSO_WS_SERVE because it contains $webdotdir and + # $assetsdir. $datadir => DIR_CGI_OVERWRITE | DIR_ALSO_WS_SERVE, # Directories that are read-only for cgi scripts "$datadir/mining" => DIR_CGI_READ, @@ -281,6 +290,7 @@ sub FILESYSTEM { $attachdir => DIR_CGI_WRITE, $graphsdir => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE, $webdotdir => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE, + $assetsdir => DIR_CGI_WRITE | DIR_ALSO_WS_SERVE, # Directories that contain content served directly by the web server. "$skinsdir/custom" => DIR_WS_SERVE, "$skinsdir/contrib" => DIR_WS_SERVE, @@ -409,8 +419,8 @@ EOT </IfModule> </FilesMatch> -# Allow access to .png files created by a local copy of 'dot' -<FilesMatch \\.png\$> + # Allow access to .png files created by a local copy of 'dot' + <FilesMatch \\.png\$> <IfModule mod_version.c> <IfVersion < 2.4> Allow from all @@ -448,6 +458,48 @@ EOT </IfModule> EOT }, + + "$assetsdir/.htaccess" => { perms => WS_SERVE, contents => <<EOT +# Allow access to .css files +<FilesMatch \\.(css|js)\$> + <IfModule mod_version.c> + <IfVersion < 2.4> + Allow from all + </IfVersion> + <IfVersion >= 2.4> + <IfModule mod_perl.c> + Allow from all + </IfModule> + <IfModule !mod_perl.c> + Require all granted + </IfModule> + </IfVersion> + </IfModule> + <IfModule !mod_version.c> + Allow from all + </IfModule> +</FilesMatch> + +# And no directory listings, either. +<IfModule mod_version.c> + <IfVersion < 2.4> + Deny from all + </IfVersion> + <IfVersion >= 2.4> + <IfModule mod_perl.c> + Deny from all + </IfModule> + <IfModule !mod_perl.c> + Require all denied + </IfModule> + </IfVersion> +</IfModule> +<IfModule !mod_version.c> + Deny from all +</IfModule> +EOT + }, + ); Bugzilla::Hook::process('install_filesystem', { @@ -482,6 +534,7 @@ sub update_filesystem { my $datadir = bz_locations->{'datadir'}; my $graphsdir = bz_locations->{'graphsdir'}; + my $assetsdir = bz_locations->{'assetsdir'}; # If the graphs/ directory doesn't exist, we're upgrading from # a version old enough that we need to update the $datadir/mining # format. @@ -489,6 +542,13 @@ sub update_filesystem { _update_old_charts($datadir); } + # If there is a file named '-All-' in $datadir/mining, then we're still + # having mining files named by product name, and we need to convert them to + # files named by product ID. + if (-e File::Spec->catfile($datadir, 'mining', '-All-')) { + _update_old_mining_filenames(File::Spec->catdir($datadir, 'mining')); + } + # By sorting the dirs, we assure that shorter-named directories # (meaning parent directories) are always created before their # child directories. @@ -515,6 +575,13 @@ sub update_filesystem { _rename_file($oldparamsfile, "$datadir/$oldparamsfile"); } + # Remove old assets htaccess file to force recreation with correct values. + if (-e "$assetsdir/.htaccess") { + if (read_file("$assetsdir/.htaccess") =~ /<FilesMatch \\\.css\$>/) { + unlink("$assetsdir/.htaccess"); + } + } + _create_files(%files); if ($params->{index_html}) { _create_files(%{$fs->{index_html}}); @@ -558,6 +625,7 @@ EOT _remove_empty_css_files(); _convert_single_file_skins(); + _remove_dynamic_assets(); } sub _remove_empty_css_files { @@ -602,6 +670,27 @@ sub _convert_single_file_skins { } } +# delete all automatically generated css/js files to force recreation at the +# next request. +sub _remove_dynamic_assets { + my @files = ( + glob(bz_locations()->{assetsdir} . '/*.css'), + glob(bz_locations()->{assetsdir} . '/*.js'), + ); + foreach my $file (@files) { + unlink($file); + } + + # remove old skins/assets directory + my $old_path = bz_locations()->{skinsdir} . '/assets'; + if (-d $old_path) { + foreach my $file (glob("$old_path/*.css")) { + unlink($file); + } + rmdir($old_path); + } +} + sub create_htaccess { _create_files(%{FILESYSTEM()->{htaccess}}); @@ -730,6 +819,59 @@ sub _update_old_charts { } } +# The old naming scheme has product names as mining file names; we rename them +# to product IDs. +sub _update_old_mining_filenames { + my ($miningdir) = @_; + my @conversion_errors; + + require Bugzilla::Product; + + # We use a dummy product instance with ID 0, representing all products + my $product_all = {id => 0, name => '-All-'}; + bless($product_all, 'Bugzilla::Product'); + + print "Updating old charting data file names..."; + my @products = Bugzilla::Product->get_all(); + push(@products, $product_all); + foreach my $product (@products) { + if (-e File::Spec->catfile($miningdir, $product->id)) { + push(@conversion_errors, + { product => $product, + message => 'A file named "' . $product->id . + '" already exists.' }); + } + } + + if (! @conversion_errors) { + # Renaming mining files should work now without a hitch. + foreach my $product (@products) { + if (! rename(File::Spec->catfile($miningdir, $product->name), + File::Spec->catfile($miningdir, $product->id))) { + push(@conversion_errors, + { product => $product, + message => $! }); + } + } + } + + # Error reporting + if (! @conversion_errors) { + print " done.\n"; + } + else { + print " FAILED:\n"; + foreach my $error (@conversion_errors) { + printf "Cannot rename charting data file for product %d (%s): %s\n", + $error->{product}->id, $error->{product}->name, + $error->{message}; + } + print "You need to empty the \"$miningdir\" directory, then run\n", + " collectstats.pl --regenerate\n", + "in order to clean this up.\n"; + } +} + sub fix_dir_permissions { my ($dir) = @_; return if ON_WINDOWS; @@ -961,3 +1103,29 @@ how they are supposed to be set in Bugzilla's current configuration. If it fails to set the permissions, a warning will be printed to STDERR. =back + +=head1 B<Methods in need of POD> + +=over + +=item CGI_WRITE + +=item DIR_WS_SERVE + +=item DIR_ALSO_WS_SERVE + +=item WS_SERVE + +=item FILESYSTEM + +=item WS_EXECUTE + +=item CGI_READ + +=item DIR_CGI_READ + +=item DIR_CGI_WRITE + +=item DIR_CGI_OVERWRITE + +=back diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm index 881f6c956..7f473cc77 100644 --- a/Bugzilla/Install/Localconfig.pm +++ b/Bugzilla/Install/Localconfig.pm @@ -15,7 +15,9 @@ package Bugzilla::Install::Localconfig; # * Files do not have the correct permissions # * The database is not up to date +use 5.10.1; use strict; +use warnings; use Bugzilla::Constants; use Bugzilla::Install::Util qw(bin_loc install_string); @@ -26,7 +28,7 @@ use File::Basename qw(dirname); use Safe; use Term::ANSIColor; -use base qw(Exporter); +use parent qw(Exporter); our @EXPORT_OK = qw( read_localconfig @@ -79,12 +81,24 @@ use constant LOCALCONFIG_VARS => ( default => 1, }, { - name => 'index_html', - default => 0, + name => 'db_mysql_ssl_ca_file', + default => '', + }, + { + name => 'db_mysql_ssl_ca_path', + default => '', + }, + { + name => 'db_mysql_ssl_client_cert', + default => '', }, { - name => 'cvsbin', - default => sub { bin_loc('cvs') }, + name => 'db_mysql_ssl_client_key', + default => '', + }, + { + name => 'index_html', + default => 0, }, { name => 'interdiffbin', diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index fbd7d7882..f723543b8 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -13,23 +13,17 @@ package Bugzilla::Install::Requirements; # Subroutines may "require" and "import" from modules, but they # MUST NOT "use." +use 5.10.1; use strict; -use version; +use warnings; use Bugzilla::Constants; -use Bugzilla::Install::Util qw(vers_cmp install_string bin_loc +use Bugzilla::Install::Util qw(install_string bin_loc extension_requirement_packages); use List::Util qw(max); use Term::ANSIColor; -# Return::Value 1.666002 pollutes the error log with warnings about this -# deprecated module. We have to set NO_CLUCK = 1 before loading Email::Send -# in have_vers() to disable these warnings. -BEGIN { - $Return::Value::NO_CLUCK = 1; -} - -use base qw(Exporter); +use parent qw(Exporter); our @EXPORT = qw( REQUIRED_MODULES OPTIONAL_MODULES @@ -55,6 +49,8 @@ use constant APACHE_MODULES => { mod_headers => 'headers_module', mod_env => 'env_module', mod_expires => 'expires_module', + mod_rewrite => 'rewrite_module', + mod_version => 'version_module' }; # These are all of the binaries that we could possibly use that can @@ -86,7 +82,6 @@ use constant APACHE_PATH => [qw( # are 'blacklisted'--that is, even if the version is high enough, Bugzilla # will refuse to say that it's OK to run with that version. sub REQUIRED_MODULES { - my $perl_ver = sprintf('%vd', $^V); my @modules = ( { package => 'CGI.pm', @@ -106,40 +101,36 @@ sub REQUIRED_MODULES { module => 'Date::Format', version => '2.23' }, - # 0.28 fixed some important bugs in DateTime. + # 0.75 fixes a warning thrown with Perl 5.17 and newer. { package => 'DateTime', module => 'DateTime', - version => '0.28' + version => '0.75' }, - # 0.79 is required to work on Windows Vista and Windows Server 2008. - # As correctly detecting the flavor of Windows is not easy, - # we require this version for all Windows installations. - # 0.71 fixes a major bug affecting all platforms. + # 1.64 fixes a taint issue preventing the local timezone from + # being determined on some systems. { package => 'DateTime-TimeZone', module => 'DateTime::TimeZone', - version => ON_WINDOWS ? '0.79' : '0.71' + version => '1.64' }, # 1.54 is required for Perl 5.10+. It also makes DBD::Oracle happy. { package => 'DBI', module => 'DBI', - version => (vers_cmp($perl_ver, '5.13.3') > -1) ? '1.614' : '1.54' + version => ($^V >= v5.13.3) ? '1.614' : '1.54' }, - # 2.22 fixes various problems related to UTF8 strings in hash keys, - # as well as line endings on Windows. + # 2.24 contains several useful text virtual methods. { package => 'Template-Toolkit', module => 'Template', - version => '2.22' + version => '2.24' }, - # 2.04 implement the "Test" method (to write to data/mailer.testfile). + # 1.300011 has a debug mode for SMTP and automatically pass -i to sendmail. { - package => 'Email-Send', - module => 'Email::Send', - version => ON_WINDOWS ? '2.16' : '2.04', - blacklist => ['^2\.196$'] + package => 'Email-Sender', + module => 'Email::Sender', + version => '1.300011', }, { package => 'Email-MIME', @@ -150,9 +141,8 @@ sub REQUIRED_MODULES { { package => 'URI', module => 'URI', - # This version properly handles a semicolon as the delimiter - # in a URL query string. - version => '1.37', + # Follows RFC 3986 to escape characters in URI::Escape. + version => '1.55', }, # 0.32 fixes several memory leaks in the XS version of some functions. { @@ -165,10 +155,22 @@ sub REQUIRED_MODULES { module => 'Math::Random::ISAAC', version => '1.0.1', }, + { + package => 'File-Slurp', + module => 'File::Slurp', + version => '9999.13', + }, + { + package => 'JSON-XS', + module => 'JSON::XS', + # 2.0 is the first version that will work with JSON::RPC. + version => '2.01', + }, ); if (ON_WINDOWS) { - push(@modules, { + push(@modules, + { package => 'Win32', module => 'Win32', # 0.35 fixes a memory leak in GetOSVersion, which we use. @@ -179,7 +181,14 @@ sub REQUIRED_MODULES { module => 'Win32::API', # 0.55 fixes a bug with char* that might affect Bugzilla::RNG. version => '0.55', - }); + }, + { + package => 'DateTime-TimeZone-Local-Win32', + module => 'DateTime::TimeZone::Local::Win32', + # We require DateTime::TimeZone 1.64, so this version must match. + version => '1.64', + } + ); } my $extra_modules = _get_extension_requirements('REQUIRED_MODULES'); @@ -188,7 +197,6 @@ sub REQUIRED_MODULES { }; sub OPTIONAL_MODULES { - my $perl_ver = sprintf('%vd', $^V); my @modules = ( { package => 'GD', @@ -199,10 +207,9 @@ sub OPTIONAL_MODULES { { package => 'Chart', module => 'Chart::Lines', - # Versions below 2.1 cannot be detected accurately. - # There is no 2.1.0 release (it was 2.1), but .0 is required to fix + # Versions below 2.4.1 cannot be compared accurately, see # https://rt.cpan.org/Public/Bug/Display.html?id=28218. - version => '2.1.0', + version => '2.4.1', feature => [qw(new_charts old_charts)], }, { @@ -283,6 +290,8 @@ sub OPTIONAL_MODULES { # Fixes various bugs, including 542931 and 552353 + stops # throwing warnings with Perl 5.12. version => '0.712', + # SOAP::Transport::HTTP 1.12 is bogus. + blacklist => ['^1\.12$'], feature => ['xmlrpc'], }, # Since SOAP::Lite 1.0, XMLRPC::Lite is no longer included @@ -297,26 +306,20 @@ sub OPTIONAL_MODULES { package => 'JSON-RPC', module => 'JSON::RPC', version => 0, - feature => ['jsonrpc'], - }, - { - package => 'JSON-XS', - module => 'JSON::XS', - # 2.0 is the first version that will work with JSON::RPC. - version => '2.0', - feature => ['jsonrpc_faster'], + feature => ['jsonrpc', 'rest'], }, { package => 'Test-Taint', module => 'Test::Taint', - version => 0, - feature => ['jsonrpc', 'xmlrpc'], + # 1.06 no longer throws warnings with Perl 5.10+. + version => 1.06, + feature => ['jsonrpc', 'xmlrpc', 'rest'], }, { # We need the 'utf8_mode' method of HTML::Parser, for HTML::Scrubber. package => 'HTML-Parser', module => 'HTML::Parser', - version => (vers_cmp($perl_ver, '5.13.3') > -1) ? '3.67' : '3.40', + version => ($^V >= v5.13.3) ? '3.67' : '3.40', feature => ['html_desc'], }, { @@ -368,12 +371,6 @@ sub OPTIONAL_MODULES { version => 0, feature => ['jobqueue'], }, - { - package => 'File-Slurp', - module => 'File::Slurp', - version => '9999.13', - feature => ['jobqueue'], - }, # mod_perl { @@ -403,6 +400,22 @@ sub OPTIONAL_MODULES { version => '0', feature => ['typesniffer'], }, + + # memcached + { + package => 'Cache-Memcached', + module => 'Cache::Memcached', + version => '0', + feature => ['memcached'], + }, + + # Documentation + { + package => 'File-Copy-Recursive', + module => 'File::Copy::Recursive', + version => 0, + feature => ['documentation'], + } ); my $extra_modules = _get_extension_requirements('OPTIONAL_MODULES'); @@ -416,14 +429,18 @@ use constant FEATURE_FILES => ( jsonrpc => ['Bugzilla/WebService/Server/JSONRPC.pm', 'jsonrpc.cgi'], xmlrpc => ['Bugzilla/WebService/Server/XMLRPC.pm', 'xmlrpc.cgi', 'Bugzilla/WebService.pm', 'Bugzilla/WebService/*.pm'], + rest => ['Bugzilla/WebService/Server/REST.pm', 'rest.cgi', + 'Bugzilla/WebService/Server/REST/Resources/*.pm'], moving => ['importxml.pl'], auth_ldap => ['Bugzilla/Auth/Verify/LDAP.pm'], auth_radius => ['Bugzilla/Auth/Verify/RADIUS.pm'], + documentation => ['docs/makedocs.pl'], inbound_email => ['email_in.pl'], jobqueue => ['Bugzilla/Job/*', 'Bugzilla/JobQueue.pm', 'Bugzilla/JobQueue/*', 'jobqueue.pl'], patch_viewer => ['Bugzilla/Attachment/PatchReader.pm'], updates => ['Bugzilla/Update.pm'], + memcached => ['Bugzilla/Memcache.pm'], ); # This implements the REQUIRED_MODULES and OPTIONAL_MODULES stuff @@ -506,7 +523,7 @@ sub _missing_apache_modules { return []; } my @missing; - foreach my $module (keys %$modules) { + foreach my $module (sort keys %$modules) { my $ok = _check_apache_module($module, $modules->{$module}, $cmd_info, $output); push(@missing, $module) if !$ok; @@ -940,3 +957,11 @@ Returns a hashref where file names are the keys and the value is the feature that must be enabled in order to compile that file. =back + +=head1 B<Methods in need of POD> + +=over + +=item print_module_instructions + +=back diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm index cbc41db32..c05037061 100644 --- a/Bugzilla/Install/Util.pm +++ b/Bugzilla/Install/Util.pm @@ -11,7 +11,9 @@ package Bugzilla::Install::Util; # module may require *only* Bugzilla::Constants and built-in # perl modules. +use 5.10.1; use strict; +use warnings; use Bugzilla::Constants; @@ -23,7 +25,7 @@ use Scalar::Util qw(tainted); use Term::ANSIColor qw(colored); use PerlIO; -use base qw(Exporter); +use parent qw(Exporter); our @EXPORT_OK = qw( bin_loc get_version_and_os @@ -37,7 +39,6 @@ our @EXPORT_OK = qw( include_languages success template_include_path - vers_cmp init_console ); @@ -475,49 +476,6 @@ sub template_include_path { return \@include_path; } -# This is taken straight from Sort::Versions 1.5, which is not included -# with perl by default. -sub vers_cmp { - my ($a, $b) = @_; - - # Remove leading zeroes - Bug 344661 - $a =~ s/^0*(\d.+)/$1/; - $b =~ s/^0*(\d.+)/$1/; - - my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g); - my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g); - - my ($A, $B); - while (@A and @B) { - $A = shift @A; - $B = shift @B; - if ($A eq '-' and $B eq '-') { - next; - } elsif ( $A eq '-' ) { - return -1; - } elsif ( $B eq '-') { - return 1; - } elsif ($A eq '.' and $B eq '.') { - next; - } elsif ( $A eq '.' ) { - return -1; - } elsif ( $B eq '.' ) { - return 1; - } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { - if ($A =~ /^0/ || $B =~ /^0/) { - return $A cmp $B if $A cmp $B; - } else { - return $A <=> $B if $A <=> $B; - } - } else { - $A = uc $A; - $B = uc $B; - return $A cmp $B if $A cmp $B; - } - } - @A <=> @B; -} - sub no_checksetup_from_cgi { print "Content-Type: text/html; charset=UTF-8\r\n\r\n"; print install_string('no_checksetup_from_cgi'); @@ -893,26 +851,36 @@ Used by L<Bugzilla::Template> to determine the languages' list which are compiled with the browser's I<Accept-Language> and the languages of installed templates. -=item C<vers_cmp> +=back + +=head1 B<Methods in need of POD> =over -=item B<Description> +=item supported_languages -This is a comparison function, like you would use in C<sort>, except that -it compares two version numbers. So, for example, 2.10 would be greater -than 2.2. +=item extension_template_directory -It's based on versioncmp from L<Sort::Versions>, with some Bugzilla-specific -fixes. +=item extension_code_files -=item B<Params>: C<$a> and C<$b> - The versions you want to compare. +=item extension_web_directory -=item B<Returns> +=item trick_taint -C<-1> if C<$a> is less than C<$b>, C<0> if they are equal, or C<1> if C<$a> -is greater than C<$b>. +=item success -=back +=item trim + +=item extension_package_directory + +=item set_output_encoding + +=item extension_requirement_packages + +=item prevent_windows_dialog_boxes + +=item sortQvalue + +=item no_checksetup_from_cgi =back |