Upgrade to 4.0.8 with mod of ExternalAuth + absolute paths to ticket-menu.
[usit-rt.git] / sbin / rt-test-dependencies
CommitLineData
84fb5b46
MKG
1#!/usr/bin/perl
2# BEGIN BPS TAGGED BLOCK {{{
3#
4# COPYRIGHT:
5#
6# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
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;
55no warnings qw(numeric redefine);
56use Getopt::Long;
57my %args;
58my %deps;
dab09ea8 59my @orig_argv = @ARGV;
84fb5b46
MKG
60GetOptions(
61 \%args, 'v|verbose',
dab09ea8 62 'install!', 'with-MYSQL',
84fb5b46
MKG
63 'with-POSTGRESQL|with-pg|with-pgsql', 'with-SQLITE',
64 'with-ORACLE', 'with-FASTCGI',
65 'with-MODPERL1', 'with-MODPERL2',
66 'with-STANDALONE',
67
68 'with-DEV',
69
70 'with-GPG',
71 'with-ICAL',
72 'with-SMTP',
73 'with-GRAPHVIZ',
74 'with-GD',
75 'with-DASHBOARDS',
76 'with-USERLOGO',
77 'with-SSL-MAILGATE',
dab09ea8 78 'with-HTML-DOC',
84fb5b46
MKG
79
80 'download=s',
81 'repository=s',
82 'list-deps',
83 'help|h',
84);
85
86if ( $args{help} ) {
87 require Pod::Usage;
88 Pod::Usage::pod2usage( { verbose => 2 } );
89 exit;
90}
91
92# Set up defaults
93my %default = (
94 'with-MASON' => 1,
95 'with-PSGI' => 1,
96 'with-CORE' => 1,
97 'with-CLI' => 1,
98 'with-MAILGATE' => 1,
99 'with-DEV' => 0,
100 'with-GPG' => 0,
101 'with-ICAL' => 1,
102 'with-SMTP' => 1,
103 'with-GRAPHVIZ' => 0,
104 'with-GD' => 1,
105 'with-DASHBOARDS' => 1,
106 'with-USERLOGO' => 1,
107 'with-SSL-MAILGATE' => 0,
dab09ea8 108 'with-HTML-DOC' => 0,
84fb5b46
MKG
109);
110$args{$_} = $default{$_} foreach grep !exists $args{$_}, keys %default;
111
112{
113 my $section;
114 my %always_show_sections = (
115 perl => 1,
116 users => 1,
117 );
118
119 sub section {
120 my $s = shift;
121 $section = $s;
122 print "$s:\n" unless $args{'list-deps'};
123 }
124
125 sub print_found {
126 my $msg = shift;
127 my $test = shift;
128 my $extra = shift;
129
130 unless ( $args{'list-deps'} ) {
131 if ( $args{'v'} or not $test or $always_show_sections{$section} ) {
132 print "\t$msg ...";
133 print $test ? "found" : "MISSING";
134 print "\n";
135 }
136
137 print "\t\t$extra\n" if defined $extra;
138 }
139 }
140}
141
142sub conclude {
143 my %missing_by_type = @_;
144
145 unless ( $args{'list-deps'} ) {
146 unless ( keys %missing_by_type ) {
147 print "\nAll dependencies have been found.\n";
148 return;
149 }
150
151 print "\nSOME DEPENDENCIES WERE MISSING.\n";
152
153 for my $type ( keys %missing_by_type ) {
154 my $missing = $missing_by_type{$type};
155
156 print "$type missing dependencies:\n";
157 for my $name ( keys %$missing ) {
158 my $module = $missing->{$name};
159 my $version = $module->{version};
160 my $error = $module->{error};
161 print_found( $name . ( $version && !$error ? " >= $version" : "" ),
162 0, $module->{error} );
163 }
164 }
165 exit 1;
166 }
167}
168
169sub text_to_hash {
170 my %hash;
171 for my $line ( split /\n/, $_[0] ) {
172 my($key, $value) = $line =~ /(\S+)\s*(\S*)/;
173 $value ||= '';
174 $hash{$key} = $value;
175 }
176
177 return %hash;
178}
179
180$deps{'CORE'} = [ text_to_hash( << '.') ];
181Class::Accessor 0.34
182DateTime 0.44
183DateTime::Locale 0.40
184Digest::base
185Digest::MD5 2.27
186Digest::SHA
187DBI 1.37
188Class::ReturnValue 0.40
189DBIx::SearchBuilder 1.59
190Text::Template 1.44
191File::ShareDir
192File::Spec 0.8
193HTML::Quoted
194HTML::Scrubber 0.08
b5747ff2
MKG
195HTML::TreeBuilder
196HTML::FormatText
84fb5b46
MKG
197Log::Dispatch 2.23
198Sys::Syslog 0.16
199Locale::Maketext 1.06
200Locale::Maketext::Lexicon 0.32
201Locale::Maketext::Fuzzy
202MIME::Entity 5.425
203Mail::Mailer 1.57
204Email::Address
205Text::Wrapper
206Time::ParseDate
207Time::HiRes
208File::Temp 0.19
209Text::Quoted 2.02
210Tree::Simple 1.04
211UNIVERSAL::require
212Regexp::Common
213Scalar::Util
214Module::Versions::Report 1.05
215Cache::Simple::TimedExpiry
216Encode 2.39
217CSS::Squish 0.06
218File::Glob
219Devel::StackTrace 1.19
220Text::Password::Pronounceable
221Devel::GlobalDestruction
222List::MoreUtils
223Net::CIDR
224Regexp::Common::net::CIDR
225Regexp::IPv6
226.
227
228$deps{'MASON'} = [ text_to_hash( << '.') ];
229HTML::Mason 1.43
230Errno
231Digest::MD5 2.27
232CGI::Cookie 1.20
233Storable 2.08
234Apache::Session 1.53
235XML::RSS 1.05
236Text::WikiFormat 0.76
237CSS::Squish 0.06
238Devel::StackTrace 1.19
239JSON
240IPC::Run3
241.
242
243$deps{'PSGI'} = [ text_to_hash( << '.') ];
244CGI 3.38
245CGI::PSGI 0.12
246HTML::Mason::PSGIHandler 0.52
247Plack 0.9971
248Plack::Handler::Starlet
249CGI::Emulate::PSGI
250.
251
252$deps{'MAILGATE'} = [ text_to_hash( << '.') ];
84fb5b46
MKG
253Getopt::Long
254LWP::UserAgent
255Pod::Usage
256.
257
258$deps{'SSL-MAILGATE'} = [ text_to_hash( << '.') ];
259Crypt::SSLeay
260Net::SSL
261LWP::UserAgent 6.0
262LWP::Protocol::https
263Mozilla::CA
264.
265
266$deps{'CLI'} = [ text_to_hash( << '.') ];
267Getopt::Long 2.24
268LWP
269HTTP::Request::Common
270Text::ParseWords
271Term::ReadLine
272Term::ReadKey
273.
274
275$deps{'DEV'} = [ text_to_hash( << '.') ];
276Email::Abstract
277Test::Email
278HTML::Form
279HTML::TokeParser
280WWW::Mechanize 1.52
281Test::WWW::Mechanize 1.30
282Module::Refresh 0.03
283Test::Expect 0.31
284XML::Simple
285File::Find
286Test::Deep 0 # needed for shredder tests
287String::ShellQuote 0 # needed for gnupg-incoming.t
288Log::Dispatch::Perl
289Test::Warn
290Test::Builder 0.90 # needed for is_passing
291Test::MockTime
292Log::Dispatch::Perl
293Test::WWW::Mechanize::PSGI
b5747ff2 294Plack::Middleware::Test::StashWarnings 0.06
84fb5b46
MKG
295Test::LongString
296.
297
298$deps{'FASTCGI'} = [ text_to_hash( << '.') ];
dab09ea8 299FCGI 0.74
84fb5b46
MKG
300FCGI::ProcManager
301.
302
303$deps{'MODPERL1'} = [ text_to_hash( << '.') ];
304Apache::Request
305Apache::DBI 0.92
306.
307
308$deps{'MODPERL2'} = [ text_to_hash( << '.') ];
309Apache::DBI
310HTML::Mason 1.36
311.
312
313$deps{'MYSQL'} = [ text_to_hash( << '.') ];
314DBD::mysql 2.1018
315.
316
317$deps{'ORACLE'} = [ text_to_hash( << '.') ];
318DBD::Oracle
319.
320
321$deps{'POSTGRESQL'} = [ text_to_hash( << '.') ];
322DBD::Pg 1.43
323.
324
325$deps{'SQLITE'} = [ text_to_hash( << '.') ];
326DBD::SQLite 1.00
327.
328
329$deps{'GPG'} = [ text_to_hash( << '.') ];
330GnuPG::Interface
331PerlIO::eol
332.
333
334$deps{'ICAL'} = [ text_to_hash( << '.') ];
335Data::ICal
336.
337
338$deps{'SMTP'} = [ text_to_hash( << '.') ];
339Net::SMTP
340.
341
342$deps{'DASHBOARDS'} = [ text_to_hash( << '.') ];
343HTML::RewriteAttributes 0.04
344MIME::Types
b5747ff2 345URI 1.59
84fb5b46
MKG
346.
347
348$deps{'GRAPHVIZ'} = [ text_to_hash( << '.') ];
349GraphViz
dab09ea8 350IPC::Run 0.90
84fb5b46
MKG
351.
352
353$deps{'GD'} = [ text_to_hash( << '.') ];
354GD
355GD::Graph
356GD::Text
357.
358
359$deps{'USERLOGO'} = [ text_to_hash( << '.') ];
360Convert::Color
361.
362
dab09ea8
MKG
363$deps{'HTML-DOC'} = [ text_to_hash( <<'.') ];
364Pod::Simple 3.17
365HTML::Entities
366.
367
84fb5b46
MKG
368my %AVOID = (
369 'DBD::Oracle' => [qw(1.23)],
dab09ea8 370 'Email::Address' => [qw(1.893 1.894)],
84fb5b46
MKG
371);
372
373if ($args{'download'}) {
374 download_mods();
375}
376
377
378check_perl_version();
379
380check_users();
381
382my %Missing_By_Type = ();
383foreach my $type (sort grep $args{$_}, keys %args) {
384 next unless ($type =~ /^with-(.*?)$/) and $deps{$1};
385
386 $type = $1;
387 section("$type dependencies");
388
389 my @missing;
390 my @deps = @{ $deps{$type} };
391
392 my %missing = test_deps(@deps);
393
394 if ( $args{'install'} ) {
395 for my $module (keys %missing) {
396 resolve_dep($module, $missing{$module}{version});
397 my $m = $module . '.pm';
398 $m =~ s!::!/!g;
399 if ( delete $INC{$m} ) {
400 my $symtab = $module . '::';
401 no strict 'refs';
402 for my $symbol ( keys %{$symtab} ) {
403 next if substr( $symbol, -2, 2 ) eq '::';
404 delete $symtab->{$symbol};
405 }
406 }
407 delete $missing{$module}
408 if test_dep($module, $missing{$module}{version}, $AVOID{$module});
409 }
410 }
411
412 $Missing_By_Type{$type} = \%missing if keys %missing;
413}
414
dab09ea8
MKG
415if ( $args{'install'} && keys %Missing_By_Type ) {
416 exec($0, @orig_argv, '--no-install');
417}
418else {
419 conclude(%Missing_By_Type);
420}
84fb5b46
MKG
421
422sub test_deps {
423 my @deps = @_;
424
425 my %missing;
426 while(@deps) {
427 my $module = shift @deps;
428 my $version = shift @deps;
429 my($test, $error) = test_dep($module, $version, $AVOID{$module});
430 my $msg = $module . ($version && !$error ? " >= $version" : '');
431 print_found($msg, $test, $error);
432
433 $missing{$module} = { version => $version, error => $error } unless $test;
434 }
435
436 return %missing;
437}
438
439sub test_dep {
440 my $module = shift;
441 my $version = shift;
442 my $avoid = shift;
443
444 if ( $args{'list-deps'} ) {
445 print $module, ': ', $version || 0, "\n";
446 }
447 else {
448 eval "use $module $version ()";
449 if ( my $error = $@ ) {
450 return 0 unless wantarray;
451
452 $error =~ s/\n(.*)$//s;
453 $error =~ s/at \(eval \d+\) line \d+\.$//;
454 undef $error if $error =~ /this is only/;
455
456 return ( 0, $error );
457 }
458
459 if ( $avoid ) {
460 my $version = $module->VERSION;
461 if ( grep $version eq $_, @$avoid ) {
462 return 0 unless wantarray;
463 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.");
464 }
465 }
466
467 return 1;
468 }
469}
470
471sub resolve_dep {
472 my $module = shift;
473 my $version = shift;
474
475 print "\nInstall module $module\n";
476
477 my $ext = $ENV{'RT_FIX_DEPS_CMD'} || $ENV{'PERL_PREFER_CPAN_CLIENT'};
478 unless( $ext ) {
479 my $configured = 1;
480 {
481 local @INC = @INC;
482 if ( $ENV{'HOME'} ) {
483 unshift @INC, "$ENV{'HOME'}/.cpan";
484 }
485 $configured = eval { require CPAN::MyConfig } || eval { require CPAN::Config };
486 }
487 unless ( $configured ) {
488 print <<END;
489You haven't configured the CPAN shell yet.
490Please run `/usr/bin/perl -MCPAN -e shell` to configure it.
491END
492 exit(1);
493 }
494 my $rv = eval { require CPAN; CPAN::Shell->install($module) };
495 return $rv unless $@;
496
497 print <<END;
498Failed to load module CPAN.
499
500-------- Error ---------
501$@
502------------------------
503
504When we tried to start installing RT's perl dependencies,
505we were unable to load the CPAN client. This module is usually distributed
506with Perl. This usually indicates that your vendor has shipped an unconfigured
507or incorrectly configured CPAN client.
508The error above may (or may not) give you a hint about what went wrong
509
510You have several choices about how to install dependencies in
511this situatation:
512
5131) use a different tool to install dependencies by running setting the following
514 shell environment variable and rerunning this tool:
515 RT_FIX_DEPS_CMD='/usr/bin/perl -MCPAN -e"install %s"'
5162) Attempt to configure CPAN by running:
517 `/usr/bin/perl -MCPAN -e shell` program from shell.
518 If this fails, you may have to manually upgrade CPAN (see below)
5193) Try to update the CPAN client. Download it from:
520 http://search.cpan.org/dist/CPAN and try again
5214) Install each dependency manually by downloading them one by one from
522 http://search.cpan.org
523
524END
525 exit(1);
526 }
527
528 if( $ext =~ /\%s/) {
529 $ext =~ s/\%s/$module/g; # sprintf( $ext, $module );
530 } else {
531 $ext .= " $module";
532 }
533 print "\t\tcommand: '$ext'\n";
534 return scalar `$ext 1>&2`;
535}
536
537sub download_mods {
538 my %modules;
539 use CPAN;
540
541 foreach my $key (keys %deps) {
542 my @deps = (@{$deps{$key}});
543 while (@deps) {
544 my $mod = shift @deps;
545 my $ver = shift @deps;
546 next if ($mod =~ /^(DBD-|Apache-Request)/);
547 $modules{$mod} = $ver;
548 }
549 }
550 my @mods = keys %modules;
551 CPAN::get();
552 my $moddir = $args{'download'};
553 foreach my $mod (@mods) {
554 $CPAN::Config->{'build_dir'} = $moddir;
555 CPAN::get($mod);
556 }
557
558 opendir(DIR, $moddir);
559 while ( my $dir = readdir(DIR)) {
560 print "Dir is $dir\n";
561 next if ( $dir =~ /^\.\.?$/);
562
563 # Skip things we've previously tagged
564 my $out = `svn ls $args{'repository'}/tags/$dir`;
565 next if ($out);
566
567 if ($dir =~ /^(.*)-(.*?)$/) {
568 `svn_load_dirs -no_user_input -t tags/$dir -v $args{'repository'} dists/$1 $moddir/$dir`;
569 `rm -rf $moddir/$dir`;
570
571 }
572
573 }
574 closedir(DIR);
575 exit;
576}
577
578sub check_perl_version {
579 section("perl");
580 eval {require 5.008003};
581 if ($@) {
582 print_found("5.8.3", 0,"RT is known to be non-functional on versions of perl older than 5.8.3. Please upgrade to 5.8.3 or newer.");
583 exit(1);
584 } else {
585 print_found( sprintf(">=5.8.3(%vd)", $^V), 1 );
586 }
587}
588
589sub check_users {
590 section("users");
591 print_found("rt group (uio-rt)", defined getgrnam("uio-rt"));
592 print_found("bin owner (root)", defined getpwnam("root"));
593 print_found("libs owner (root)", defined getpwnam("root"));
594 print_found("libs group (bin)", defined getgrnam("bin"));
595 print_found("web owner (httpd)", defined getpwnam("httpd"));
596 print_found("web group (httpd)", defined getgrnam("httpd"));
597}
598
5991;
600
601__END__
602
603=head1 NAME
604
605rt-test-dependencies - test rt's dependencies
606
607=head1 SYNOPSIS
608
609 rt-test-dependencies
610 rt-test-dependencies --install
611 rt-test-dependencies --with-mysql --with-fastcgi
612
613=head1 DESCRIPTION
614
615by default, C<rt-test-dependencies> determines whether you have installed all
616the perl modules RT needs to run.
617
618the "RT_FIX_DEPS_CMD" environment variable, if set, will be used instead of
619the standard CPAN shell by --install to install any required modules. it will
620be called with the module name, or, if "RT_FIX_DEPS_CMD" contains a "%s", will
621replace the "%s" with the module name before calling the program.
622
623=head1 OPTIONS
624
625=over
626
627=item install
628
629 install missing modules
630
631=item verbose
632
633list the status of all dependencies, rather than just the missing ones.
634
635-v is equal to --verbose
636
637=item specify dependencies
638
639=over
640
641=item --with-mysql
642
643 database interface for mysql
644
645=item --with-postgresql
646
647 database interface for postgresql
648
649=item with-oracle
650
651 database interface for oracle
652
653=item with-sqlite
654
655 database interface and driver for sqlite (unsupported)
656
657=item with-fastcgi
658
659 libraries needed to support the fastcgi handler
660
661=item with-modperl1
662
663 libraries needed to support the modperl 1 handler
664
665=item with-modperl2
666
667 libraries needed to support the modperl 2 handler
668
669=item with-dev
670
671 tools needed for RT development
672
673=back
674
675=back
676