diff options
Diffstat (limited to 'Bugzilla/Install/Requirements.pm')
-rw-r--r-- | Bugzilla/Install/Requirements.pm | 1178 |
1 files changed, 599 insertions, 579 deletions
diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index 61496d843..852f7f78e 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -19,21 +19,21 @@ use warnings; use Bugzilla::Constants; use Bugzilla::Install::Util qw(install_string bin_loc - extension_requirement_packages); + extension_requirement_packages); use List::Util qw(max); use Term::ANSIColor; use parent qw(Exporter); our @EXPORT = qw( - REQUIRED_MODULES - OPTIONAL_MODULES - FEATURE_FILES - - check_requirements - check_graphviz - have_vers - install_command - map_files_to_features + REQUIRED_MODULES + OPTIONAL_MODULES + FEATURE_FILES + + check_requirements + check_graphviz + have_vers + install_command + map_files_to_features ); # This is how many *'s are in the top of each "box" message printed @@ -45,12 +45,12 @@ use constant TABLE_WIDTH => 71; # # The keys are the names of the modules, the values are what the module # is called in the output of "apachectl -t -D DUMP_MODULES". -use constant APACHE_MODULES => { - mod_headers => 'headers_module', - mod_env => 'env_module', - mod_expires => 'expires_module', - mod_rewrite => 'rewrite_module', - mod_version => 'version_module' +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 @@ -64,11 +64,11 @@ use constant APACHE => qw(apachectl httpd apache2 apache); # If we don't find any of the above binaries in the normal PATH, # these are extra places we look. use constant APACHE_PATH => [qw( - /usr/sbin + /usr/sbin /usr/local/sbin /usr/libexec /usr/local/libexec -)]; + )]; # The below two constants are subroutines so that they can implement # a hook. Other than that they are actually constants. @@ -82,737 +82,757 @@ 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 @modules = ( + my @modules = ( { - package => 'CGI.pm', - module => 'CGI', - # 3.51 fixes a security problem that affects Bugzilla. - # (bug 591165) - version => '3.51', - }, - { - package => 'Digest-SHA', - module => 'Digest::SHA', - version => 0 + package => 'CGI.pm', + module => 'CGI', + + # 3.51 fixes a security problem that affects Bugzilla. + # (bug 591165) + version => '3.51', }, + {package => 'Digest-SHA', module => 'Digest::SHA', version => 0}, + # 0.23 fixes incorrect handling of 1/2 & 3/4 timezones. - { - package => 'TimeDate', - module => 'Date::Format', - version => '2.23' - }, + {package => 'TimeDate', module => 'Date::Format', version => '2.23'}, + # 0.75 fixes a warning thrown with Perl 5.17 and newer. - { - package => 'DateTime', - module => 'DateTime', - version => '0.75' - }, + {package => 'DateTime', module => 'DateTime', version => '0.75'}, + # 1.64 fixes a taint issue preventing the local timezone from # being determined on some systems. { - package => 'DateTime-TimeZone', - module => 'DateTime::TimeZone', - version => '1.64' + package => 'DateTime-TimeZone', + module => 'DateTime::TimeZone', + version => '1.64' }, + # 1.54 is required for Perl 5.10+. It also makes DBD::Oracle happy. { - package => 'DBI', - module => 'DBI', - version => ($^V >= v5.13.3) ? '1.614' : '1.54' + package => 'DBI', + module => 'DBI', + version => ($^V >= v5.13.3) ? '1.614' : '1.54' }, + # 2.24 contains several useful text virtual methods. - { - package => 'Template-Toolkit', - module => 'Template', - version => '2.24' - }, + {package => 'Template-Toolkit', module => 'Template', version => '2.24'}, + # 1.300011 has a debug mode for SMTP and automatically pass -i to sendmail. + {package => 'Email-Sender', module => 'Email::Sender', version => '1.300011',}, { - package => 'Email-Sender', - module => 'Email::Sender', - version => '1.300011', - }, - { - package => 'Email-MIME', - module => 'Email::MIME', - # This fixes a memory leak in walk_parts that affected jobqueue.pl. - version => '1.904' + package => 'Email-MIME', + module => 'Email::MIME', + + # This fixes a memory leak in walk_parts that affected jobqueue.pl. + version => '1.904' }, { - package => 'URI', - module => 'URI', - # Follows RFC 3986 to escape characters in URI::Escape. - version => '1.55', + package => 'URI', + module => 'URI', + + # 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. + {package => 'List-MoreUtils', module => 'List::MoreUtils', version => 0.32,}, { - package => 'List-MoreUtils', - module => 'List::MoreUtils', - version => 0.32, + package => 'Math-Random-ISAAC', + module => 'Math::Random::ISAAC', + version => '1.0.1', }, { - package => 'Math-Random-ISAAC', - module => 'Math::Random::ISAAC', - version => '1.0.1', - }, - { - package => 'JSON-XS', - module => 'JSON::XS', - # 2.0 is the first version that will work with JSON::RPC. - version => '2.01', + 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, - { - package => 'Win32', - module => 'Win32', - # 0.35 fixes a memory leak in GetOSVersion, which we use. - version => 0.35, - }, - { - package => 'Win32-API', - 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', - } - ); - } + if (ON_WINDOWS) { + push( + @modules, + { + package => 'Win32', + module => 'Win32', - my $extra_modules = _get_extension_requirements('REQUIRED_MODULES'); - push(@modules, @$extra_modules); - return \@modules; -}; + # 0.35 fixes a memory leak in GetOSVersion, which we use. + version => 0.35, + }, + { + package => 'Win32-API', + 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'); + push(@modules, @$extra_modules); + return \@modules; +} sub OPTIONAL_MODULES { - my @modules = ( + my @modules = ( { - package => 'GD', - module => 'GD', - version => '1.20', - feature => [qw(graphical_reports new_charts old_charts)], + package => 'GD', + module => 'GD', + version => '1.20', + feature => [qw(graphical_reports new_charts old_charts)], }, { - package => 'Chart', - module => 'Chart::Lines', - # Versions below 2.4.1 cannot be compared accurately, see - # https://rt.cpan.org/Public/Bug/Display.html?id=28218. - version => '2.4.1', - feature => [qw(new_charts old_charts)], + package => 'Chart', + module => 'Chart::Lines', + + # Versions below 2.4.1 cannot be compared accurately, see + # https://rt.cpan.org/Public/Bug/Display.html?id=28218. + version => '2.4.1', + feature => [qw(new_charts old_charts)], }, { - package => 'Template-GD', - # This module tells us whether or not Template-GD is installed - # on Template-Toolkits after 2.14, and still works with 2.14 and lower. - module => 'Template::Plugin::GD::Image', - version => 0, - feature => ['graphical_reports'], + package => 'Template-GD', + + # This module tells us whether or not Template-GD is installed + # on Template-Toolkits after 2.14, and still works with 2.14 and lower. + module => 'Template::Plugin::GD::Image', + version => 0, + feature => ['graphical_reports'], }, { - package => 'GDTextUtil', - module => 'GD::Text', - version => 0, - feature => ['graphical_reports'], + package => 'GDTextUtil', + module => 'GD::Text', + version => 0, + feature => ['graphical_reports'], }, { - package => 'GDGraph', - module => 'GD::Graph', - version => 0, - feature => ['graphical_reports'], + package => 'GDGraph', + module => 'GD::Graph', + version => 0, + feature => ['graphical_reports'], }, { - package => 'MIME-tools', - # MIME::Parser is packaged as MIME::Tools on ActiveState Perl - module => ON_WINDOWS ? 'MIME::Tools' : 'MIME::Parser', - version => '5.406', - feature => ['moving'], + package => 'MIME-tools', + + # MIME::Parser is packaged as MIME::Tools on ActiveState Perl + module => ON_WINDOWS ? 'MIME::Tools' : 'MIME::Parser', + version => '5.406', + feature => ['moving'], }, { - package => 'libwww-perl', - module => 'LWP::UserAgent', - version => 0, - feature => ['updates'], + package => 'libwww-perl', + module => 'LWP::UserAgent', + version => 0, + feature => ['updates'], }, { - package => 'XML-Twig', - module => 'XML::Twig', - version => 0, - feature => ['moving', 'updates'], + package => 'XML-Twig', + module => 'XML::Twig', + version => 0, + feature => ['moving', 'updates'], }, { - package => 'PatchReader', - module => 'PatchReader', - # 0.9.6 fixes two notable bugs and significantly improves the UX. - version => '0.9.6', - feature => ['patch_viewer'], + package => 'PatchReader', + module => 'PatchReader', + + # 0.9.6 fixes two notable bugs and significantly improves the UX. + version => '0.9.6', + feature => ['patch_viewer'], }, { - package => 'perl-ldap', - module => 'Net::LDAP', - version => 0, - feature => ['auth_ldap'], + package => 'perl-ldap', + module => 'Net::LDAP', + version => 0, + feature => ['auth_ldap'], }, { - package => 'Authen-SASL', - module => 'Authen::SASL', - version => 0, - feature => ['smtp_auth'], + package => 'Authen-SASL', + module => 'Authen::SASL', + version => 0, + feature => ['smtp_auth'], }, { - package => 'Net-SMTP-SSL', - module => 'Net::SMTP::SSL', - version => 1.01, - feature => ['smtp_ssl'], + package => 'Net-SMTP-SSL', + module => 'Net::SMTP::SSL', + version => 1.01, + feature => ['smtp_ssl'], }, { - package => 'RadiusPerl', - module => 'Authen::Radius', - version => 0, - feature => ['auth_radius'], + package => 'RadiusPerl', + module => 'Authen::Radius', + version => 0, + feature => ['auth_radius'], }, + # XXX - Once we require XMLRPC::Lite 0.717 or higher, we can # remove SOAP::Lite from the list. { - package => 'SOAP-Lite', - module => 'SOAP::Lite', - # 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'], + package => 'SOAP-Lite', + module => 'SOAP::Lite', + + # 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 # and so it must be checked separately. { - package => 'XMLRPC-Lite', - module => 'XMLRPC::Lite', - version => '0.712', - feature => ['xmlrpc'], + package => 'XMLRPC-Lite', + module => 'XMLRPC::Lite', + version => '0.712', + feature => ['xmlrpc'], }, { - package => 'JSON-RPC', - module => 'JSON::RPC', - version => 0, - feature => ['jsonrpc', 'rest'], + package => 'JSON-RPC', + module => 'JSON::RPC', + version => 0, + feature => ['jsonrpc', 'rest'], }, { - package => 'Test-Taint', - module => 'Test::Taint', - # 1.06 no longer throws warnings with Perl 5.10+. - version => 1.06, - feature => ['jsonrpc', 'xmlrpc', 'rest'], + package => 'Test-Taint', + module => 'Test::Taint', + + # 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 => ($^V >= v5.13.3) ? '3.67' : '3.40', - feature => ['html_desc'], + # We need the 'utf8_mode' method of HTML::Parser, for HTML::Scrubber. + package => 'HTML-Parser', + module => 'HTML::Parser', + version => ($^V >= v5.13.3) ? '3.67' : '3.40', + feature => ['html_desc'], }, { - package => 'HTML-Scrubber', - module => 'HTML::Scrubber', - version => 0, - feature => ['html_desc'], + package => 'HTML-Scrubber', + module => 'HTML::Scrubber', + version => 0, + feature => ['html_desc'], }, { - # we need version 2.21 of Encode for mime_name - package => 'Encode', - module => 'Encode', - version => 2.21, - feature => ['detect_charset'], + # we need version 2.21 of Encode for mime_name + package => 'Encode', + module => 'Encode', + version => 2.21, + feature => ['detect_charset'], }, { - package => 'Encode-Detect', - module => 'Encode::Detect', - version => 0, - feature => ['detect_charset'], + package => 'Encode-Detect', + module => 'Encode::Detect', + version => 0, + feature => ['detect_charset'], }, # Inbound Email { - package => 'Email-Reply', - module => 'Email::Reply', - version => 0, - feature => ['inbound_email'], + package => 'Email-Reply', + module => 'Email::Reply', + version => 0, + feature => ['inbound_email'], }, { - package => 'HTML-FormatText-WithLinks', - module => 'HTML::FormatText::WithLinks', - # We need 0.13 to set the "bold" marker to "*". - version => '0.13', - feature => ['inbound_email'], + package => 'HTML-FormatText-WithLinks', + module => 'HTML::FormatText::WithLinks', + + # We need 0.13 to set the "bold" marker to "*". + version => '0.13', + feature => ['inbound_email'], }, # Mail Queueing { - package => 'TheSchwartz', - module => 'TheSchwartz', - # 1.07 supports the prioritization of jobs. - version => 1.07, - feature => ['jobqueue'], + package => 'TheSchwartz', + module => 'TheSchwartz', + + # 1.07 supports the prioritization of jobs. + version => 1.07, + feature => ['jobqueue'], }, { - package => 'Daemon-Generic', - module => 'Daemon::Generic', - version => 0, - feature => ['jobqueue'], + package => 'Daemon-Generic', + module => 'Daemon::Generic', + version => 0, + feature => ['jobqueue'], }, # mod_perl { - package => 'mod_perl', - module => 'mod_perl2', - version => '1.999022', - feature => ['mod_perl'], + package => 'mod_perl', + module => 'mod_perl2', + version => '1.999022', + feature => ['mod_perl'], }, { - package => 'Apache-SizeLimit', - module => 'Apache2::SizeLimit', - # 0.96 properly determines process size on Linux. - version => '0.96', - feature => ['mod_perl'], + package => 'Apache-SizeLimit', + module => 'Apache2::SizeLimit', + + # 0.96 properly determines process size on Linux. + version => '0.96', + feature => ['mod_perl'], }, # typesniffer { - package => 'File-MimeInfo', - module => 'File::MimeInfo::Magic', - version => '0', - feature => ['typesniffer'], + package => 'File-MimeInfo', + module => 'File::MimeInfo::Magic', + version => '0', + feature => ['typesniffer'], }, { - package => 'IO-stringy', - module => 'IO::Scalar', - version => '0', - feature => ['typesniffer'], + package => 'IO-stringy', + module => 'IO::Scalar', + version => '0', + feature => ['typesniffer'], }, # memcached { - package => 'Cache-Memcached', - module => 'Cache::Memcached', - version => '0', - feature => ['memcached'], + package => 'Cache-Memcached', + module => 'Cache::Memcached', + version => '0', + feature => ['memcached'], }, # Documentation { - package => 'File-Copy-Recursive', - module => 'File::Copy::Recursive', - version => 0, - feature => ['documentation'], + package => 'File-Copy-Recursive', + module => 'File::Copy::Recursive', + version => 0, + feature => ['documentation'], }, { - package => 'File-Which', - module => 'File::Which', - version => 0, - feature => ['documentation'], + package => 'File-Which', + module => 'File::Which', + version => 0, + feature => ['documentation'], }, - ); + ); - my $extra_modules = _get_extension_requirements('OPTIONAL_MODULES'); - push(@modules, @$extra_modules); - return \@modules; -}; + my $extra_modules = _get_extension_requirements('OPTIONAL_MODULES'); + push(@modules, @$extra_modules); + return \@modules; +} # This maps features to the files that require that feature in order # to compile. It is used by t/001compile.t and mod_perl.pl. 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'], + 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 # described in in Bugzilla::Extension. sub _get_extension_requirements { - my ($function) = @_; - - my $packages = extension_requirement_packages(); - my @modules; - foreach my $package (@$packages) { - if ($package->can($function)) { - my $extra_modules = $package->$function; - push(@modules, @$extra_modules); - } - } - return \@modules; -}; + my ($function) = @_; -sub check_requirements { - my ($output) = @_; - - print "\n", install_string('checking_modules'), "\n" if $output; - my $root = ROOT_USER; - my $missing = _check_missing(REQUIRED_MODULES, $output); - - print "\n", install_string('checking_dbd'), "\n" if $output; - my $have_one_dbd = 0; - my $db_modules = DB_MODULE; - foreach my $db (keys %$db_modules) { - my $dbd = $db_modules->{$db}->{dbd}; - $have_one_dbd = 1 if have_vers($dbd, $output); + my $packages = extension_requirement_packages(); + my @modules; + foreach my $package (@$packages) { + if ($package->can($function)) { + my $extra_modules = $package->$function; + push(@modules, @$extra_modules); } + } + return \@modules; +} - print "\n", install_string('checking_optional'), "\n" if $output; - my $missing_optional = _check_missing(OPTIONAL_MODULES, $output); - - my $missing_apache = _missing_apache_modules(APACHE_MODULES, $output); - - # If we're running on Windows, reset the input line terminator so that - # console input works properly - loading CGI tends to mess it up - $/ = "\015\012" if ON_WINDOWS; - - my $pass = !scalar(@$missing) && $have_one_dbd; - return { - pass => $pass, - one_dbd => $have_one_dbd, - missing => $missing, - optional => $missing_optional, - apache => $missing_apache, - any_missing => !$pass || scalar(@$missing_optional), - }; +sub check_requirements { + my ($output) = @_; + + print "\n", install_string('checking_modules'), "\n" if $output; + my $root = ROOT_USER; + my $missing = _check_missing(REQUIRED_MODULES, $output); + + print "\n", install_string('checking_dbd'), "\n" if $output; + my $have_one_dbd = 0; + my $db_modules = DB_MODULE; + foreach my $db (keys %$db_modules) { + my $dbd = $db_modules->{$db}->{dbd}; + $have_one_dbd = 1 if have_vers($dbd, $output); + } + + print "\n", install_string('checking_optional'), "\n" if $output; + my $missing_optional = _check_missing(OPTIONAL_MODULES, $output); + + my $missing_apache = _missing_apache_modules(APACHE_MODULES, $output); + + # If we're running on Windows, reset the input line terminator so that + # console input works properly - loading CGI tends to mess it up + $/ = "\015\012" if ON_WINDOWS; + + my $pass = !scalar(@$missing) && $have_one_dbd; + return { + pass => $pass, + one_dbd => $have_one_dbd, + missing => $missing, + optional => $missing_optional, + apache => $missing_apache, + any_missing => !$pass || scalar(@$missing_optional), + }; } # A helper for check_requirements sub _check_missing { - my ($modules, $output) = @_; + my ($modules, $output) = @_; - my @missing; - foreach my $module (@$modules) { - unless (have_vers($module, $output)) { - push(@missing, $module); - } + my @missing; + foreach my $module (@$modules) { + unless (have_vers($module, $output)) { + push(@missing, $module); } + } - return \@missing; + return \@missing; } sub _missing_apache_modules { - my ($modules, $output) = @_; - my $apachectl = _get_apachectl(); - return [] if !$apachectl; - my $command = "$apachectl -t -D DUMP_MODULES"; - my $cmd_info = `$command 2>&1`; - # If apachectl returned a value greater than 0, then there was an - # error parsing Apache's configuration, and we can't check modules. - my $retval = $?; - if ($retval > 0) { - print STDERR install_string('apachectl_failed', - { command => $command, root => ROOT_USER }), "\n"; - return []; - } - my @missing; - foreach my $module (sort keys %$modules) { - my $ok = _check_apache_module($module, $modules->{$module}, - $cmd_info, $output); - push(@missing, $module) if !$ok; - } - return \@missing; + my ($modules, $output) = @_; + my $apachectl = _get_apachectl(); + return [] if !$apachectl; + my $command = "$apachectl -t -D DUMP_MODULES"; + my $cmd_info = `$command 2>&1`; + + # If apachectl returned a value greater than 0, then there was an + # error parsing Apache's configuration, and we can't check modules. + my $retval = $?; + if ($retval > 0) { + print STDERR install_string('apachectl_failed', + {command => $command, root => ROOT_USER}), "\n"; + return []; + } + my @missing; + foreach my $module (sort keys %$modules) { + my $ok = _check_apache_module($module, $modules->{$module}, $cmd_info, $output); + push(@missing, $module) if !$ok; + } + return \@missing; } sub _get_apachectl { - foreach my $bin_name (APACHE) { - my $bin = bin_loc($bin_name); - return $bin if $bin; - } - # Try again with a possibly different path. - foreach my $bin_name (APACHE) { - my $bin = bin_loc($bin_name, APACHE_PATH); - return $bin if $bin; - } - return undef; + foreach my $bin_name (APACHE) { + my $bin = bin_loc($bin_name); + return $bin if $bin; + } + + # Try again with a possibly different path. + foreach my $bin_name (APACHE) { + my $bin = bin_loc($bin_name, APACHE_PATH); + return $bin if $bin; + } + return undef; } sub _check_apache_module { - my ($module, $config_name, $mod_info, $output) = @_; - my $ok; - if ($mod_info =~ /^\s+\Q$config_name\E\b/m) { - $ok = 1; - } - if ($output) { - _checking_for({ package => $module, ok => $ok }); - } - return $ok; + my ($module, $config_name, $mod_info, $output) = @_; + my $ok; + if ($mod_info =~ /^\s+\Q$config_name\E\b/m) { + $ok = 1; + } + if ($output) { + _checking_for({package => $module, ok => $ok}); + } + return $ok; } sub print_module_instructions { - my ($check_results, $output) = @_; - - # First we print the long explanatory messages. - - if (scalar @{$check_results->{missing}}) { - print install_string('modules_message_required'); - } - - if (!$check_results->{one_dbd}) { - print install_string('modules_message_db'); - } - - if (my @missing = @{$check_results->{optional}} and $output) { - print install_string('modules_message_optional'); - # Now we have to determine how large the table cols will be. - my $longest_name = max(map(length($_->{package}), @missing)); - - # The first column header is at least 11 characters long. - $longest_name = 11 if $longest_name < 11; - - # The table is TABLE_WIDTH characters long. There are seven mandatory - # characters (* and space) in the string. So, we have a total - # of TABLE_WIDTH - 7 characters to work with. - my $remaining_space = (TABLE_WIDTH - 7) - $longest_name; - print '*' x TABLE_WIDTH . "\n"; - printf "* \%${longest_name}s * %-${remaining_space}s *\n", - 'MODULE NAME', 'ENABLES FEATURE(S)'; - print '*' x TABLE_WIDTH . "\n"; - foreach my $package (@missing) { - printf "* \%${longest_name}s * %-${remaining_space}s *\n", - $package->{package}, - _translate_feature($package->{feature}); - } - } - - if (my @missing = @{ $check_results->{apache} }) { - print install_string('modules_message_apache'); - my $missing_string = join(', ', @missing); - my $size = TABLE_WIDTH - 7; - printf "* \%-${size}s *\n", $missing_string; - my $spaces = TABLE_WIDTH - 2; - print "*", (' ' x $spaces), "*\n"; - } - - my $need_module_instructions = - ( (!$output and @{$check_results->{missing}}) - or ($output and $check_results->{any_missing}) ) ? 1 : 0; - - if ($need_module_instructions or @{ $check_results->{apache} }) { - # If any output was required, we want to close the "table" - print "*" x TABLE_WIDTH . "\n"; - } - - # And now we print the actual installation commands. - - if (my @missing = @{$check_results->{optional}} and $output) { - print install_string('commands_optional') . "\n\n"; - foreach my $module (@missing) { - my $command = install_command($module); - printf "%15s: $command\n", $module->{package}; - } - print "\n"; - } - - if (!$check_results->{one_dbd}) { - print install_string('commands_dbd') . "\n"; - my %db_modules = %{DB_MODULE()}; - foreach my $db (keys %db_modules) { - my $command = install_command($db_modules{$db}->{dbd}); - printf "%10s: \%s\n", $db_modules{$db}->{name}, $command; - } - print "\n"; - } - - if (my @missing = @{$check_results->{missing}}) { - print colored(install_string('commands_required'), COLOR_ERROR), "\n"; - foreach my $package (@missing) { - my $command = install_command($package); - print " $command\n"; - } - } - - if ($output && $check_results->{any_missing} && !ON_ACTIVESTATE - && !$check_results->{hide_all}) - { - print install_string('install_all', { perl => $^X }); - } - if (!$check_results->{pass}) { - print colored(install_string('installation_failed'), COLOR_ERROR), - "\n\n"; - } + my ($check_results, $output) = @_; + + # First we print the long explanatory messages. + + if (scalar @{$check_results->{missing}}) { + print install_string('modules_message_required'); + } + + if (!$check_results->{one_dbd}) { + print install_string('modules_message_db'); + } + + if (my @missing = @{$check_results->{optional}} and $output) { + print install_string('modules_message_optional'); + + # Now we have to determine how large the table cols will be. + my $longest_name = max(map(length($_->{package}), @missing)); + + # The first column header is at least 11 characters long. + $longest_name = 11 if $longest_name < 11; + + # The table is TABLE_WIDTH characters long. There are seven mandatory + # characters (* and space) in the string. So, we have a total + # of TABLE_WIDTH - 7 characters to work with. + my $remaining_space = (TABLE_WIDTH - 7) - $longest_name; + print '*' x TABLE_WIDTH . "\n"; + printf "* \%${longest_name}s * %-${remaining_space}s *\n", 'MODULE NAME', + 'ENABLES FEATURE(S)'; + print '*' x TABLE_WIDTH . "\n"; + foreach my $package (@missing) { + printf "* \%${longest_name}s * %-${remaining_space}s *\n", $package->{package}, + _translate_feature($package->{feature}); + } + } + + if (my @missing = @{$check_results->{apache}}) { + print install_string('modules_message_apache'); + my $missing_string = join(', ', @missing); + my $size = TABLE_WIDTH - 7; + printf "* \%-${size}s *\n", $missing_string; + my $spaces = TABLE_WIDTH - 2; + print "*", (' ' x $spaces), "*\n"; + } + + my $need_module_instructions = ( + (!$output and @{$check_results->{missing}}) + or ($output and $check_results->{any_missing}) + ) ? 1 : 0; + + if ($need_module_instructions or @{$check_results->{apache}}) { + + # If any output was required, we want to close the "table" + print "*" x TABLE_WIDTH . "\n"; + } + + # And now we print the actual installation commands. + + if (my @missing = @{$check_results->{optional}} and $output) { + print install_string('commands_optional') . "\n\n"; + foreach my $module (@missing) { + my $command = install_command($module); + printf "%15s: $command\n", $module->{package}; + } + print "\n"; + } + + if (!$check_results->{one_dbd}) { + print install_string('commands_dbd') . "\n"; + my %db_modules = %{DB_MODULE()}; + foreach my $db (keys %db_modules) { + my $command = install_command($db_modules{$db}->{dbd}); + printf "%10s: \%s\n", $db_modules{$db}->{name}, $command; + } + print "\n"; + } + + if (my @missing = @{$check_results->{missing}}) { + print colored(install_string('commands_required'), COLOR_ERROR), "\n"; + foreach my $package (@missing) { + my $command = install_command($package); + print " $command\n"; + } + } + + if ( $output + && $check_results->{any_missing} + && !ON_ACTIVESTATE + && !$check_results->{hide_all}) + { + print install_string('install_all', {perl => $^X}); + } + if (!$check_results->{pass}) { + print colored(install_string('installation_failed'), COLOR_ERROR), "\n\n"; + } } sub _translate_feature { - my $features = shift; - my @strings; - foreach my $feature (@$features) { - push(@strings, install_string("feature_$feature")); - } - return join(', ', @strings); + my $features = shift; + my @strings; + foreach my $feature (@$features) { + push(@strings, install_string("feature_$feature")); + } + return join(', ', @strings); } sub check_graphviz { - my ($output) = @_; + my ($output) = @_; - my $webdotbase = Bugzilla->params->{'webdotbase'}; - return 1 if $webdotbase =~ /^https?:/; + my $webdotbase = Bugzilla->params->{'webdotbase'}; + return 1 if $webdotbase =~ /^https?:/; - my $return; - $return = 1 if -x $webdotbase; + my $return; + $return = 1 if -x $webdotbase; - if ($output) { - _checking_for({ package => 'GraphViz', ok => $return }); - } + if ($output) { + _checking_for({package => 'GraphViz', ok => $return}); + } - if (!$return) { - print install_string('bad_executable', { bin => $webdotbase }), "\n"; - } + if (!$return) { + print install_string('bad_executable', {bin => $webdotbase}), "\n"; + } + + my $webdotdir = bz_locations()->{'webdotdir'}; - my $webdotdir = bz_locations()->{'webdotdir'}; - # Check .htaccess allows access to generated images - if (-e "$webdotdir/.htaccess") { - my $htaccess = new IO::File("$webdotdir/.htaccess", 'r') - || die "$webdotdir/.htaccess: " . $!; - if (!grep(/png/, $htaccess->getlines)) { - print STDERR install_string('webdot_bad_htaccess', - { dir => $webdotdir }), "\n"; - } - $htaccess->close; + # Check .htaccess allows access to generated images + if (-e "$webdotdir/.htaccess") { + my $htaccess = new IO::File("$webdotdir/.htaccess", 'r') + || die "$webdotdir/.htaccess: " . $!; + if (!grep(/png/, $htaccess->getlines)) { + print STDERR install_string('webdot_bad_htaccess', {dir => $webdotdir}), "\n"; } + $htaccess->close; + } - return $return; + return $return; } # This was originally clipped from the libnet Makefile.PL, adapted here for # accurate version checking. sub have_vers { - my ($params, $output) = @_; - my $module = $params->{module}; - my $package = $params->{package}; - if (!$package) { - $package = $module; - $package =~ s/::/-/g; - } - my $wanted = $params->{version}; - - eval "require $module;"; - # Don't let loading a module change the output-encoding of STDOUT - # or STDERR. (CGI.pm tries to set "binmode" on these file handles when - # it's loaded, and other modules may do the same in the future.) - Bugzilla::Install::Util::set_output_encoding(); - - # VERSION is provided by UNIVERSAL::, and can be called even if - # the module isn't loaded. We eval'uate ->VERSION because it can die - # when the version is not valid (yes, this happens from time to time). - # In that case, we use an uglier method to get the version. - my $vnum = eval { $module->VERSION }; - if ($@) { - no strict 'refs'; - $vnum = ${"${module}::VERSION"}; - - # If we come here, then the version is not a valid one. - # We try to sanitize it. - if ($vnum =~ /^((\d+)(\.\d+)*)/) { - $vnum = $1; - } - } - $vnum ||= -1; - - # Must do a string comparison as $vnum may be of the form 5.10.1. - my $vok = ($vnum ne '-1' && version->new($vnum) >= version->new($wanted)) ? 1 : 0; - my $blacklisted; - if ($vok && $params->{blacklist}) { - $blacklisted = grep($vnum =~ /$_/, @{$params->{blacklist}}); - $vok = 0 if $blacklisted; - } - - if ($output) { - _checking_for({ - package => $package, ok => $vok, wanted => $wanted, - found => $vnum, blacklisted => $blacklisted - }); - } - - return $vok ? 1 : 0; + my ($params, $output) = @_; + my $module = $params->{module}; + my $package = $params->{package}; + if (!$package) { + $package = $module; + $package =~ s/::/-/g; + } + my $wanted = $params->{version}; + + eval "require $module;"; + + # Don't let loading a module change the output-encoding of STDOUT + # or STDERR. (CGI.pm tries to set "binmode" on these file handles when + # it's loaded, and other modules may do the same in the future.) + Bugzilla::Install::Util::set_output_encoding(); + + # VERSION is provided by UNIVERSAL::, and can be called even if + # the module isn't loaded. We eval'uate ->VERSION because it can die + # when the version is not valid (yes, this happens from time to time). + # In that case, we use an uglier method to get the version. + my $vnum = eval { $module->VERSION }; + if ($@) { + no strict 'refs'; + $vnum = ${"${module}::VERSION"}; + + # If we come here, then the version is not a valid one. + # We try to sanitize it. + if ($vnum =~ /^((\d+)(\.\d+)*)/) { + $vnum = $1; + } + } + $vnum ||= -1; + + # Must do a string comparison as $vnum may be of the form 5.10.1. + my $vok + = ($vnum ne '-1' && version->new($vnum) >= version->new($wanted)) ? 1 : 0; + my $blacklisted; + if ($vok && $params->{blacklist}) { + $blacklisted = grep($vnum =~ /$_/, @{$params->{blacklist}}); + $vok = 0 if $blacklisted; + } + + if ($output) { + _checking_for({ + package => $package, + ok => $vok, + wanted => $wanted, + found => $vnum, + blacklisted => $blacklisted + }); + } + + return $vok ? 1 : 0; } sub _checking_for { - my ($params) = @_; - my ($package, $ok, $wanted, $blacklisted, $found) = - @$params{qw(package ok wanted blacklisted found)}; - - my $ok_string = $ok ? install_string('module_ok') : ''; - - # If we're actually checking versions (like for Perl modules), then - # we have some rather complex logic to determine what we want to - # show. If we're not checking versions (like for GraphViz) we just - # show "ok" or "not found". - if (exists $params->{found}) { - my $found_string; - # We do a string compare in case it's non-numeric. We make sure - # it's not a version object as negative versions are forbidden. - if ($found && !ref($found) && $found eq '-1') { - $found_string = install_string('module_not_found'); - } - elsif ($found) { - $found_string = install_string('module_found', { ver => $found }); - } - else { - $found_string = install_string('module_unknown_version'); - } - $ok_string = $ok ? "$ok_string: $found_string" : $found_string; + my ($params) = @_; + my ($package, $ok, $wanted, $blacklisted, $found) + = @$params{qw(package ok wanted blacklisted found)}; + + my $ok_string = $ok ? install_string('module_ok') : ''; + + # If we're actually checking versions (like for Perl modules), then + # we have some rather complex logic to determine what we want to + # show. If we're not checking versions (like for GraphViz) we just + # show "ok" or "not found". + if (exists $params->{found}) { + my $found_string; + + # We do a string compare in case it's non-numeric. We make sure + # it's not a version object as negative versions are forbidden. + if ($found && !ref($found) && $found eq '-1') { + $found_string = install_string('module_not_found'); + } + elsif ($found) { + $found_string = install_string('module_found', {ver => $found}); } - elsif (!$ok) { - $ok_string = install_string('module_not_found'); + else { + $found_string = install_string('module_unknown_version'); } + $ok_string = $ok ? "$ok_string: $found_string" : $found_string; + } + elsif (!$ok) { + $ok_string = install_string('module_not_found'); + } - my $black_string = $blacklisted ? install_string('blacklisted') : ''; - my $want_string = $wanted ? "v$wanted" : install_string('any'); + my $black_string = $blacklisted ? install_string('blacklisted') : ''; + my $want_string = $wanted ? "v$wanted" : install_string('any'); - my $str = sprintf "%s %20s %-11s $ok_string $black_string\n", - install_string('checking_for'), $package, "($want_string)"; - print $ok ? $str : colored($str, COLOR_ERROR); + my $str = sprintf "%s %20s %-11s $ok_string $black_string\n", + install_string('checking_for'), $package, "($want_string)"; + print $ok ? $str : colored($str, COLOR_ERROR); } sub install_command { - my $module = shift; - my ($command, $package); - - if (ON_ACTIVESTATE) { - $command = 'ppm install %s'; - $package = $module->{package}; - } - else { - $command = "$^X install-module.pl \%s"; - # Non-Windows installations need to use module names, because - # CPAN doesn't understand package names. - $package = $module->{module}; - } - return sprintf $command, $package; + my $module = shift; + my ($command, $package); + + if (ON_ACTIVESTATE) { + $command = 'ppm install %s'; + $package = $module->{package}; + } + else { + $command = "$^X install-module.pl \%s"; + + # Non-Windows installations need to use module names, because + # CPAN doesn't understand package names. + $package = $module->{module}; + } + return sprintf $command, $package; } # This does a reverse mapping for FEATURE_FILES. sub map_files_to_features { - my %features = FEATURE_FILES; - my %files; - foreach my $feature (keys %features) { - my @my_files = @{ $features{$feature} }; - foreach my $pattern (@my_files) { - foreach my $file (glob $pattern) { - $files{$file} = $feature; - } - } - } - return \%files; + my %features = FEATURE_FILES; + my %files; + foreach my $feature (keys %features) { + my @my_files = @{$features{$feature}}; + foreach my $pattern (@my_files) { + foreach my $file (glob $pattern) { + $files{$file} = $feature; + } + } + } + return \%files; } 1; |