]> git.uio.no Git - usit-rt.git/blame - sbin/rt-test-dependencies
Upgrade to 4.2.2
[usit-rt.git] / sbin / rt-test-dependencies
CommitLineData
84fb5b46
MKG
1#!/usr/bin/perl
2# BEGIN BPS TAGGED BLOCK {{{
3#
4# COPYRIGHT:
5#
320f0092 6# This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC
84fb5b46
MKG
7# <sales@bestpractical.com>
8#
9# (Except where explicitly superseded by other copyright notices)
10#
11#
12# LICENSE:
13#
14# This work is made available to you under the terms of Version 2 of
15# the GNU General Public License. A copy of that license should have
16# been provided with this software, but in any event can be snarfed
17# from www.gnu.org.
18#
19# This work is distributed in the hope that it will be useful, but
20# WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22# General Public License for more details.
23#
24# You should have received a copy of the GNU General Public License
25# along with this program; if not, write to the Free Software
26# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27# 02110-1301 or visit their web page on the internet at
28# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
29#
30#
31# CONTRIBUTION SUBMISSION POLICY:
32#
33# (The following paragraph is not intended to limit the rights granted
34# to you to modify and distribute this software under the terms of
35# the GNU General Public License and is only of importance to you if
36# you choose to contribute your changes and enhancements to the
37# community by submitting them to Best Practical Solutions, LLC.)
38#
39# By intentionally submitting any modifications, corrections or
40# derivatives to this work, or any other work intended for use with
41# Request Tracker, to Best Practical Solutions, LLC, you confirm that
42# you are the copyright holder for those contributions and you grant
43# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
44# royalty-free, perpetual, license to use, copy, create derivative
45# works based on those contributions, and sublicense and distribute
46# those contributions and any derivatives thereof.
47#
48# END BPS TAGGED BLOCK }}}
49#
50# This is just a basic script that checks to make sure that all
51# the modules needed by RT before you can install it.
52#
53
54use strict;
403d7b0b 55use warnings;
84fb5b46
MKG
56no warnings qw(numeric redefine);
57use Getopt::Long;
58my %args;
59my %deps;
dab09ea8 60my @orig_argv = @ARGV;
84fb5b46
MKG
61GetOptions(
62 \%args, 'v|verbose',
af59614d
MKG
63 'install!',
64 'with-MYSQL', 'with-PG', 'with-SQLITE', 'with-ORACLE',
65 'with-FASTCGI', 'with-MODPERL1', 'with-MODPERL2', 'with-STANDALONE',
84fb5b46 66
af59614d 67 'with-DEVELOPER',
84fb5b46
MKG
68
69 'with-GPG',
70 'with-ICAL',
84fb5b46
MKG
71 'with-GRAPHVIZ',
72 'with-GD',
73 'with-DASHBOARDS',
74 'with-USERLOGO',
dab09ea8 75 'with-HTML-DOC',
84fb5b46 76
84fb5b46
MKG
77 'list-deps',
78 'help|h',
79);
80
81if ( $args{help} ) {
82 require Pod::Usage;
83 Pod::Usage::pod2usage( { verbose => 2 } );
84 exit;
85}
86
87# Set up defaults
88my %default = (
84fb5b46
MKG
89 'with-CORE' => 1,
90 'with-CLI' => 1,
91 'with-MAILGATE' => 1,
af59614d 92 'with-DEVELOPER' => 0,
84fb5b46 93 'with-GPG' => 0,
af59614d 94 'with-SMIME' => 1,
84fb5b46 95 'with-ICAL' => 1,
84fb5b46 96 'with-GRAPHVIZ' => 0,
af59614d 97 'with-GD' => 0,
84fb5b46
MKG
98 'with-DASHBOARDS' => 1,
99 'with-USERLOGO' => 1,
dab09ea8 100 'with-HTML-DOC' => 0,
84fb5b46
MKG
101);
102$args{$_} = $default{$_} foreach grep !exists $args{$_}, keys %default;
103
104{
105 my $section;
106 my %always_show_sections = (
107 perl => 1,
108 users => 1,
109 );
110
111 sub section {
112 my $s = shift;
113 $section = $s;
114 print "$s:\n" unless $args{'list-deps'};
115 }
116
117 sub print_found {
118 my $msg = shift;
119 my $test = shift;
120 my $extra = shift;
121
122 unless ( $args{'list-deps'} ) {
123 if ( $args{'v'} or not $test or $always_show_sections{$section} ) {
124 print "\t$msg ...";
125 print $test ? "found" : "MISSING";
126 print "\n";
127 }
128
129 print "\t\t$extra\n" if defined $extra;
130 }
131 }
132}
133
134sub conclude {
135 my %missing_by_type = @_;
136
137 unless ( $args{'list-deps'} ) {
138 unless ( keys %missing_by_type ) {
139 print "\nAll dependencies have been found.\n";
140 return;
141 }
142
143 print "\nSOME DEPENDENCIES WERE MISSING.\n";
144
145 for my $type ( keys %missing_by_type ) {
146 my $missing = $missing_by_type{$type};
147
148 print "$type missing dependencies:\n";
149 for my $name ( keys %$missing ) {
150 my $module = $missing->{$name};
151 my $version = $module->{version};
152 my $error = $module->{error};
153 print_found( $name . ( $version && !$error ? " >= $version" : "" ),
154 0, $module->{error} );
155 }
156 }
af59614d
MKG
157
158 print "\nPerl library path for /usr/bin/perl:\n";
159 print " $_\n" for @INC;
160
84fb5b46
MKG
161 exit 1;
162 }
163}
164
165sub text_to_hash {
166 my %hash;
167 for my $line ( split /\n/, $_[0] ) {
168 my($key, $value) = $line =~ /(\S+)\s*(\S*)/;
169 $value ||= '';
170 $hash{$key} = $value;
171 }
172
173 return %hash;
174}
175
176$deps{'CORE'} = [ text_to_hash( << '.') ];
af59614d
MKG
177Apache::Session 1.53
178CGI 3.38
179CGI::Cookie 1.20
180CGI::Emulate::PSGI
181CGI::PSGI 0.12
84fb5b46 182Class::Accessor 0.34
af59614d
MKG
183Crypt::Eksblowfish
184CSS::Squish 0.06
185Data::GUID
186Date::Extract 0.02
187Date::Manip
84fb5b46 188DateTime 0.44
af59614d 189DateTime::Format::Natural 0.67
84fb5b46 190DateTime::Locale 0.40
af59614d
MKG
191DBI 1.37
192DBIx::SearchBuilder 1.65
193Devel::GlobalDestruction
194Devel::StackTrace 1.19
84fb5b46
MKG
195Digest::base
196Digest::MD5 2.27
197Digest::SHA
af59614d
MKG
198Email::Address 1.897
199Email::Address::List
200Encode 2.39
201Errno
202File::Glob
84fb5b46
MKG
203File::ShareDir
204File::Spec 0.8
af59614d
MKG
205File::Temp 0.19
206HTML::Entities
207HTML::FormatText::WithLinks 0.14
208HTML::FormatText::WithLinks::AndTables
209HTML::Mason 1.43
210HTML::Mason::PSGIHandler 0.52
84fb5b46 211HTML::Quoted
af59614d 212HTML::RewriteAttributes 0.05
84fb5b46 213HTML::Scrubber 0.08
af59614d
MKG
214HTTP::Message 6.0
215IPC::Run3
216JSON
217LWP::Simple
218List::MoreUtils
84fb5b46 219Locale::Maketext 1.06
af59614d 220Locale::Maketext::Fuzzy 0.11
84fb5b46 221Locale::Maketext::Lexicon 0.32
af59614d
MKG
222Log::Dispatch 2.30
223Mail::Header 2.12
84fb5b46 224Mail::Mailer 1.57
af59614d
MKG
225MIME::Entity 5.504
226Module::Refresh 0.03
84fb5b46 227Module::Versions::Report 1.05
84fb5b46 228Net::CIDR
af59614d
MKG
229Plack 1.0002
230Plack::Handler::Starlet
231Regexp::Common
84fb5b46
MKG
232Regexp::Common::net::CIDR
233Regexp::IPv6
af59614d
MKG
234Role::Basic 0.12
235Scalar::Util
84fb5b46 236Storable 2.08
af59614d
MKG
237Symbol::Global::Name 0.04
238Sys::Syslog 0.16
239Text::Password::Pronounceable
240Text::Quoted 2.07
241Text::Template 1.44
84fb5b46 242Text::WikiFormat 0.76
af59614d
MKG
243Text::Wrapper
244Time::HiRes
245Time::ParseDate
246Tree::Simple 1.04
247UNIVERSAL::require
248XML::RSS 1.05
84fb5b46
MKG
249.
250
251$deps{'MAILGATE'} = [ text_to_hash( << '.') ];
84fb5b46 252Crypt::SSLeay
af59614d 253Getopt::Long
84fb5b46 254LWP::Protocol::https
af59614d 255LWP::UserAgent 6.0
84fb5b46 256Mozilla::CA
af59614d
MKG
257Net::SSL
258Pod::Usage
84fb5b46
MKG
259.
260
261$deps{'CLI'} = [ text_to_hash( << '.') ];
262Getopt::Long 2.24
84fb5b46 263HTTP::Request::Common
af59614d 264LWP
84fb5b46 265Term::ReadKey
af59614d
MKG
266Term::ReadLine
267Text::ParseWords
84fb5b46
MKG
268.
269
af59614d 270$deps{'DEVELOPER'} = [ text_to_hash( << '.') ];
84fb5b46 271Email::Abstract
84fb5b46 272File::Find
af59614d
MKG
273File::Which
274Locale::PO
84fb5b46 275Log::Dispatch::Perl
af59614d 276Mojo::DOM
b5747ff2 277Plack::Middleware::Test::StashWarnings 0.06
af59614d
MKG
278Set::Tiny
279String::ShellQuote 0 # needed for gnupg-incoming.t
280Test::Builder 0.90 # needed for is_passing
281Test::Deep 0 # needed for shredder tests
282Test::Email
283Test::Expect 0.31
84fb5b46 284Test::LongString
af59614d 285Test::MockTime
403d7b0b 286Test::NoWarnings
af59614d
MKG
287Test::Warn
288Test::WWW::Mechanize 1.30
289Test::WWW::Mechanize::PSGI
290WWW::Mechanize 1.52
291XML::Simple
84fb5b46
MKG
292.
293
294$deps{'FASTCGI'} = [ text_to_hash( << '.') ];
dab09ea8 295FCGI 0.74
84fb5b46
MKG
296FCGI::ProcManager
297.
298
299$deps{'MODPERL1'} = [ text_to_hash( << '.') ];
84fb5b46 300Apache::DBI 0.92
af59614d 301Apache::Request
84fb5b46
MKG
302.
303
304$deps{'MODPERL2'} = [ text_to_hash( << '.') ];
305Apache::DBI
84fb5b46
MKG
306.
307
308$deps{'MYSQL'} = [ text_to_hash( << '.') ];
309DBD::mysql 2.1018
310.
311
312$deps{'ORACLE'} = [ text_to_hash( << '.') ];
313DBD::Oracle
314.
315
af59614d 316$deps{'PG'} = [ text_to_hash( << '.') ];
84fb5b46
MKG
317DBD::Pg 1.43
318.
319
320$deps{'SQLITE'} = [ text_to_hash( << '.') ];
321DBD::SQLite 1.00
322.
323
324$deps{'GPG'} = [ text_to_hash( << '.') ];
af59614d 325File::Which
84fb5b46
MKG
326GnuPG::Interface
327PerlIO::eol
328.
329
af59614d
MKG
330$deps{'SMIME'} = [ text_to_hash( << '.') ];
331Crypt::X509
332File::Which
333String::ShellQuote
84fb5b46
MKG
334.
335
af59614d
MKG
336$deps{'ICAL'} = [ text_to_hash( << '.') ];
337Data::ICal
84fb5b46
MKG
338.
339
340$deps{'DASHBOARDS'} = [ text_to_hash( << '.') ];
84fb5b46 341MIME::Types
b5747ff2 342URI 1.59
af59614d 343URI::QueryParam
84fb5b46
MKG
344.
345
346$deps{'GRAPHVIZ'} = [ text_to_hash( << '.') ];
347GraphViz
dab09ea8 348IPC::Run 0.90
84fb5b46
MKG
349.
350
351$deps{'GD'} = [ text_to_hash( << '.') ];
352GD
af59614d 353GD::Graph 1.47
84fb5b46
MKG
354GD::Text
355.
356
357$deps{'USERLOGO'} = [ text_to_hash( << '.') ];
358Convert::Color
359.
360
dab09ea8 361$deps{'HTML-DOC'} = [ text_to_hash( <<'.') ];
dab09ea8 362HTML::Entities
af59614d 363Pod::Simple 3.24
dab09ea8
MKG
364.
365
84fb5b46
MKG
366my %AVOID = (
367 'DBD::Oracle' => [qw(1.23)],
403d7b0b 368 'Devel::StackTrace' => [qw(1.28 1.29)],
84fb5b46
MKG
369);
370
371if ($args{'download'}) {
372 download_mods();
373}
374
375
376check_perl_version();
377
378check_users();
379
380my %Missing_By_Type = ();
381foreach my $type (sort grep $args{$_}, keys %args) {
382 next unless ($type =~ /^with-(.*?)$/) and $deps{$1};
383
384 $type = $1;
385 section("$type dependencies");
386
387 my @missing;
388 my @deps = @{ $deps{$type} };
389
390 my %missing = test_deps(@deps);
391
392 if ( $args{'install'} ) {
393 for my $module (keys %missing) {
394 resolve_dep($module, $missing{$module}{version});
395 my $m = $module . '.pm';
396 $m =~ s!::!/!g;
397 if ( delete $INC{$m} ) {
398 my $symtab = $module . '::';
399 no strict 'refs';
400 for my $symbol ( keys %{$symtab} ) {
401 next if substr( $symbol, -2, 2 ) eq '::';
402 delete $symtab->{$symbol};
403 }
404 }
405 delete $missing{$module}
406 if test_dep($module, $missing{$module}{version}, $AVOID{$module});
407 }
408 }
409
410 $Missing_By_Type{$type} = \%missing if keys %missing;
411}
412
dab09ea8
MKG
413if ( $args{'install'} && keys %Missing_By_Type ) {
414 exec($0, @orig_argv, '--no-install');
415}
416else {
417 conclude(%Missing_By_Type);
418}
84fb5b46
MKG
419
420sub test_deps {
421 my @deps = @_;
422
423 my %missing;
424 while(@deps) {
425 my $module = shift @deps;
426 my $version = shift @deps;
427 my($test, $error) = test_dep($module, $version, $AVOID{$module});
428 my $msg = $module . ($version && !$error ? " >= $version" : '');
429 print_found($msg, $test, $error);
430
431 $missing{$module} = { version => $version, error => $error } unless $test;
432 }
433
434 return %missing;
435}
436
437sub test_dep {
438 my $module = shift;
439 my $version = shift;
440 my $avoid = shift;
441
442 if ( $args{'list-deps'} ) {
443 print $module, ': ', $version || 0, "\n";
444 }
445 else {
af59614d 446 eval "{ local \$ENV{__WARN__}; use $module $version () }";
84fb5b46
MKG
447 if ( my $error = $@ ) {
448 return 0 unless wantarray;
449
450 $error =~ s/\n(.*)$//s;
451 $error =~ s/at \(eval \d+\) line \d+\.$//;
452 undef $error if $error =~ /this is only/;
453
af59614d
MKG
454 my $path = $module;
455 $path =~ s{::}{/}g;
456 undef $error if defined $error and $error =~ /^Can't locate $path\.pm in \@INC/;
457
84fb5b46
MKG
458 return ( 0, $error );
459 }
460
461 if ( $avoid ) {
462 my $version = $module->VERSION;
463 if ( grep $version eq $_, @$avoid ) {
464 return 0 unless wantarray;
465 return (0, "It's known that there are problems with RT and version '$version' of '$module' module. If it's the latest available version of the module then you have to downgrade manually.");
466 }
467 }
468
469 return 1;
470 }
471}
472
473sub resolve_dep {
474 my $module = shift;
475 my $version = shift;
476
477 print "\nInstall module $module\n";
478
479 my $ext = $ENV{'RT_FIX_DEPS_CMD'} || $ENV{'PERL_PREFER_CPAN_CLIENT'};
480 unless( $ext ) {
481 my $configured = 1;
482 {
483 local @INC = @INC;
484 if ( $ENV{'HOME'} ) {
485 unshift @INC, "$ENV{'HOME'}/.cpan";
486 }
487 $configured = eval { require CPAN::MyConfig } || eval { require CPAN::Config };
488 }
489 unless ( $configured ) {
490 print <<END;
491You haven't configured the CPAN shell yet.
492Please run `/usr/bin/perl -MCPAN -e shell` to configure it.
493END
494 exit(1);
495 }
496 my $rv = eval { require CPAN; CPAN::Shell->install($module) };
497 return $rv unless $@;
498
499 print <<END;
500Failed to load module CPAN.
501
502-------- Error ---------
503$@
504------------------------
505
506When we tried to start installing RT's perl dependencies,
507we were unable to load the CPAN client. This module is usually distributed
508with Perl. This usually indicates that your vendor has shipped an unconfigured
509or incorrectly configured CPAN client.
510The error above may (or may not) give you a hint about what went wrong
511
512You have several choices about how to install dependencies in
513this situatation:
514
5151) use a different tool to install dependencies by running setting the following
516 shell environment variable and rerunning this tool:
517 RT_FIX_DEPS_CMD='/usr/bin/perl -MCPAN -e"install %s"'
5182) Attempt to configure CPAN by running:
519 `/usr/bin/perl -MCPAN -e shell` program from shell.
520 If this fails, you may have to manually upgrade CPAN (see below)
5213) Try to update the CPAN client. Download it from:
522 http://search.cpan.org/dist/CPAN and try again
5234) Install each dependency manually by downloading them one by one from
524 http://search.cpan.org
525
526END
527 exit(1);
528 }
529
530 if( $ext =~ /\%s/) {
531 $ext =~ s/\%s/$module/g; # sprintf( $ext, $module );
532 } else {
533 $ext .= " $module";
534 }
535 print "\t\tcommand: '$ext'\n";
536 return scalar `$ext 1>&2`;
537}
538
84fb5b46
MKG
539sub check_perl_version {
540 section("perl");
af59614d 541 eval {require 5.010_001};
84fb5b46 542 if ($@) {
af59614d 543 print_found("5.10.1", 0, sprintf("RT requires Perl v5.10.1 or newer. Your current Perl is v%vd", $^V));
84fb5b46
MKG
544 exit(1);
545 } else {
af59614d 546 print_found( sprintf(">=5.10.1(%vd)", $^V), 1 );
84fb5b46
MKG
547 }
548}
549
550sub check_users {
551 section("users");
552 print_found("rt group (uio-rt)", defined getgrnam("uio-rt"));
553 print_found("bin owner (root)", defined getpwnam("root"));
554 print_found("libs owner (root)", defined getpwnam("root"));
555 print_found("libs group (bin)", defined getgrnam("bin"));
556 print_found("web owner (httpd)", defined getpwnam("httpd"));
557 print_found("web group (httpd)", defined getgrnam("httpd"));
558}
559
5601;
561
562__END__
563
564=head1 NAME
565
566rt-test-dependencies - test rt's dependencies
567
568=head1 SYNOPSIS
569
570 rt-test-dependencies
571 rt-test-dependencies --install
572 rt-test-dependencies --with-mysql --with-fastcgi
573
574=head1 DESCRIPTION
575
576by default, C<rt-test-dependencies> determines whether you have installed all
577the perl modules RT needs to run.
578
579the "RT_FIX_DEPS_CMD" environment variable, if set, will be used instead of
580the standard CPAN shell by --install to install any required modules. it will
581be called with the module name, or, if "RT_FIX_DEPS_CMD" contains a "%s", will
582replace the "%s" with the module name before calling the program.
583
584=head1 OPTIONS
585
586=over
587
588=item install
589
590 install missing modules
591
592=item verbose
593
594list the status of all dependencies, rather than just the missing ones.
595
596-v is equal to --verbose
597
598=item specify dependencies
599
600=over
601
602=item --with-mysql
603
af59614d
MKG
604database interface for mysql
605
606=item --with-pg
84fb5b46 607
af59614d 608database interface for postgresql
84fb5b46 609
af59614d 610=item --with-oracle
84fb5b46 611
af59614d 612database interface for oracle
84fb5b46 613
af59614d 614=item --with-sqlite
84fb5b46 615
af59614d 616database interface and driver for sqlite (unsupported)
84fb5b46 617
af59614d 618=item --with-fastcgi
84fb5b46 619
af59614d 620libraries needed to support the fastcgi handler
84fb5b46 621
af59614d 622=item --with-modperl1
84fb5b46 623
af59614d 624libraries needed to support the modperl 1 handler
84fb5b46 625
af59614d 626=item --with-modperl2
84fb5b46 627
af59614d 628libraries needed to support the modperl 2 handler
84fb5b46 629
af59614d 630=item --with-developer
84fb5b46 631
af59614d 632tools needed for RT development
84fb5b46
MKG
633
634=back
635
636=back
637