This commit was generated by cvs2svn to compensate for changes in r8593,
[freeside.git] / rt / sbin / rt-test-dependencies.in
1 #!@PERL@
2 # BEGIN BPS TAGGED BLOCK {{{
3
4 # COPYRIGHT:
5 #  
6 # This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC 
7 #                                          <jesse@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
54 use strict;
55 no warnings qw(numeric redefine);
56 use Getopt::Long;
57 my %args;
58 my %deps;
59 GetOptions(
60     \%args,                               'v|verbose',
61     'install',                            'with-MYSQL',
62     'with-POSTGRESQL|with-pg|with-pgsql', 'with-SQLITE',
63     'with-ORACLE',                        'with-FASTCGI',
64     'with-SPEEDYCGI',                     'with-MODPERL1',
65     'with-MODPERL2',                      'with-DEV',
66     'with-STANDALONE',
67     'download=s',
68     'repository=s'
69 );
70
71 unless (keys %args) {
72     help();
73     exit(0);
74 }
75 # Set up defaults
76 my %default = (
77     'with-MASON' => 1,
78     'with-CORE' => 1,
79     'with-CLI' => 1,
80     'with-MAILGATE' => 1, 
81     'with-DEV' => @RT_DEVEL_MODE@, 
82     'with-STANDALONE' => @RT_STANDALONE@,
83 );
84 $args{$_} = $default{$_} foreach grep !exists $args{$_}, keys %default;
85
86
87 {
88   my $section;
89   my %always_show_sections = (
90     perl => 1,
91     users => 1,
92   );
93
94   sub section {
95     my $s = shift;
96     $section = $s;
97     print "$s:\n";
98   }
99
100   my $any_missing = 0;
101   sub found {
102     my $msg = shift;
103     my $test = shift;
104     my $extra = shift;
105   
106     $any_missing = 1 unless $test;
107     if ($args{'v'} or not $test or $always_show_sections{$section}) {
108       print "\t$msg...";
109       print $test ? "found" : "MISSING";
110       print "\n";
111     }
112     
113     print "\t\t$extra\n" if defined $extra;
114   }
115
116   sub conclude {
117     if ($any_missing) {
118       print "\nSOMETHING WAS MISSING!\n";
119       exit 1;
120     } else {
121       print "\nEverything was found.\n";
122     }
123   }
124 }
125
126 sub help {
127
128     print <<'.';
129
130 By default, testdeps determine whether you have 
131 installed all the perl modules RT needs to run.
132
133         --install               Install missing modules
134
135 The following switches will tell the tool to check for specific dependencies
136
137         --with-mysql            Database interface for MySQL
138         --with-postgresql       Database interface for PostgreSQL 
139         --with-sqlite           Database interface and driver for SQLite (unsupported)
140         --with-oracle           Database interface for oracle (unsupported)
141
142         --with-standalone       Libraries needed to support the standalone simple pure perl server
143         --with-fastcgi          Libraries needed to support the fastcgi handler
144         --with-speedycgi        Libraries needed to support the speedycgi handler
145         --with-modperl1         Libraries needed to support the modperl 1 handler
146         --with-modperl2         Libraries needed to support the modperl 2 handler
147
148         --with-dev              Tools needed for RT development
149
150 You can also specify -v or --verbose to list the status of all dependencies,
151 rather than just the missing ones.
152
153 The "RT_FIX_DEPS_CMD" environment variable, if set, will be used
154 instead of the standard CPAN shell by --install to install any
155 required modules.  It will be called with the module name, or, if
156 "RT_FIX_DEPS_CMD" contains a "%s", will replace the "%s" with the
157 module name before calling the program.
158 .
159 }
160
161
162 sub text_to_hash {
163     my %hash;
164     for my $line ( split /\n/, $_[0] ) {
165         my($key, $value) = $line =~ /(\S+)\s*(\S*)/;
166         $value ||= '';
167         $hash{$key} = $value;
168     }
169
170     return %hash;
171 }
172
173 $deps{'CORE'} = [ text_to_hash( << '.') ];
174 Digest::base
175 Digest::MD5 2.27
176 DBI 1.37
177 Class::ReturnValue 0.40
178 Date::Format
179 DBIx::SearchBuilder 1.53
180 Text::Template
181 File::Spec 0.8
182 HTML::Entities 
183 HTML::Scrubber 0.08
184 Log::Dispatch 2.0
185 Locale::Maketext 1.06
186 Locale::Maketext::Lexicon 0.32
187 Locale::Maketext::Fuzzy
188 MIME::Entity 5.108
189 Mail::Mailer 1.57
190 Net::SMTP
191 Text::Wrapper 
192 Time::ParseDate
193 Time::HiRes 
194 File::Temp
195 Text::Autoformat
196 Text::Quoted 2.02
197 Tree::Simple 1.04
198 Regexp::Common
199 Scalar::Util
200 Module::Versions::Report 1.03
201 Cache::Simple::TimedExpiry
202 UNIVERSAL::require
203 Calendar::Simple
204 CSS::Squish 0.06
205 Devel::StackTrace 1.19
206 .
207
208 $deps{'MASON'} = [ text_to_hash( << '.') ];
209 HTML::Mason 1.23
210 Errno
211 Digest::MD5 2.27
212 CGI::Cookie 1.20
213 Storable 2.08
214 Apache::Session 1.53
215 XML::RSS 1.05
216 GD
217 GD::Graph
218 GD::Text
219 Text::WikiFormat 0.76
220 CSS::Squish 0.06
221 .
222
223 $deps{'STANDALONE'} = [ text_to_hash( << '.') ];
224 HTTP::Server::Simple 0.07
225 HTTP::Server::Simple::Mason 0.09
226 .
227
228 $deps{'MAILGATE'} = [ text_to_hash( << '.') ];
229 HTML::TreeBuilder
230 HTML::FormatText
231 Getopt::Long
232 LWP::UserAgent
233 Pod::Usage
234 .
235
236 $deps{'CLI'} = [ text_to_hash( << '.') ];
237 Getopt::Long 2.24
238 LWP
239 HTTP::Request::Common
240 Text::ParseWords
241 Term::ReadLine
242 Term::ReadKey
243 .
244
245 $deps{'DEV'} = [ text_to_hash( << '.') ];
246 Test::Inline 
247 Apache::Test
248 HTML::Form
249 HTML::TokeParser
250 WWW::Mechanize
251 Test::WWW::Mechanize 1.04
252 Module::Refresh 0.03
253 Test::Expect 0.30
254 XML::Simple
255 File::Find
256 .
257
258 $deps{'FASTCGI'} = [ text_to_hash( << '.') ];
259 CGI 2.92
260 FCGI
261 CGI::Fast 
262 .
263
264 $deps{'SPEEDYCGI'} = [ text_to_hash( << '.') ];
265 CGI 2.92
266 CGI::SpeedyCGI
267 .
268
269
270 $deps{'MODPERL1'} = [ text_to_hash( << '.') ];
271 CGI 2.92
272 Apache::Request
273 Apache::DBI 0.92
274 .
275
276 $deps{'MODPERL2'} = [ text_to_hash( << '.') ];
277 CGI 3.10
278 Apache::DBI
279 HTML::Mason 1.31
280 .
281
282 $deps{'MYSQL'} = [ text_to_hash( << '.') ];
283 DBD::mysql 2.1018
284 .
285 $deps{'ORACLE'} = [ text_to_hash( << '.') ];
286 DBD::Oracle
287 .
288 $deps{'POSTGRESQL'} = [ text_to_hash( << '.') ];
289 DBD::Pg 1.43
290 .
291
292 $deps{'SQLITE'} = [ text_to_hash( << '.') ];
293 DBD::SQLite 1.00
294 .
295
296 if ($args{'download'}) {
297
298     download_mods();
299 }
300
301
302 check_perl_version();
303
304 check_users();
305
306
307 foreach my $type (sort grep $args{$_}, keys %args) {
308     next unless ($type =~ /^with-(.*?)$/);
309
310     $type = $1;
311     section("$type dependencies");
312
313     my @missing;
314     my @deps = @{ $deps{$type} };
315     while (@deps) {
316         my $module = shift @deps;
317         my $version = shift @deps;
318         my $ret = test_dep($module, $version);
319
320         push @missing, $module, $version unless $ret;
321     }
322     if ( $args{'install'} ) {
323         while( @missing ) {
324             resolve_dep(shift @missing, shift @missing);
325         }
326     }
327 }
328
329 conclude();
330
331 sub test_dep {
332     my $module = shift;
333     my $version = shift;
334
335     eval "use $module $version ()";
336     if ($@) {
337         my $error = $@;
338         $error =~ s/\n(.*)$//s;
339         undef $error unless $error =~ /this is only/;
340         found("$module $version", 0, $error);
341
342         return undef;
343     } else {
344         my $msg = "$module";
345         $msg .= " >=$version" if $version;
346         found($msg, 1);
347         return 1;
348     }
349 }
350
351 sub resolve_dep {
352     my $module = shift;
353     my $version = shift;
354
355     print "\nInstall module $module\n";
356
357     my $ext = $ENV{'RT_FIX_DEPS_CMD'};
358     unless( $ext ) {
359         my $configured = 1;
360         {
361             local @INC = @INC;
362             if ( $ENV{'HOME'} ) {
363                 unshift @INC, "$ENV{'HOME'}/.cpan";
364             }
365             $configured = eval { require CPAN::MyConfig } || eval { require CPAN::Config };
366         }
367         unless ( $configured ) {
368             print <<END;
369 You didn't configure CPAN shell yet.
370 Please run `@PERL@ -MCPAN -e shell` tool and configure it.
371 END
372             exit(1);
373         }
374         my $rv = eval { require CPAN; CPAN::Shell->install($module) };
375         return $rv unless $@;
376
377         print <<END;
378 Failed to load module CPAN.
379
380 -------- Error ---------
381 $@
382 ------------------------
383
384 When we tried to start installing RT's perl dependencies, 
385 we were unable to load the CPAN client. This module is usually distributed
386 with Perl. This usually indicates that your vendor has shipped an unconfigured
387 or incorrectly configured CPAN client.
388 The error above may (or may not) give you a hint about what went wrong
389
390 You have several choices about how to install dependencies in 
391 this situatation:
392
393 1) use a different tool to install dependencies by running setting the following
394    shell environment variable and rerunning this tool:
395     RT_FIX_DEPS_CMD='@PERL@ -MCPAN -e"install %s"'
396 2) Attempt to configure CPAN by running:
397    `@PERL@ -MCPAN -e shell` program from shell.
398    If this fails, you may have to manually upgrade CPAN (see below)
399 3) Try to update the CPAN client. Download it from:
400    http://search.cpan.org/dist/CPAN and try again
401 4) Install each dependency manually by downloading them one by one from
402    http://search.cpan.org
403
404 END
405         exit(1);
406     }
407
408     if( $ext =~ /\%s/) {
409         $ext =~ s/\%s/$module/g; # sprintf( $ext, $module );
410     } else {
411         $ext .= " $module";
412     }
413     print "\t\tcommand: '$ext'\n";
414     return scalar `$ext 1>&2`;
415 }
416
417 sub download_mods {
418     my %modules;
419     use CPAN;
420     
421     foreach my $key (keys %deps) {
422         my @deps = (@{$deps{$key}});
423         while (@deps) {
424             my $mod = shift @deps;
425             my $ver = shift @deps;
426             next if ($mod =~ /^(DBD-|Apache-Request)/);
427             $modules{$mod} = $ver;
428         }
429     }
430     my @mods = keys %modules;
431     CPAN::get();
432     my $moddir = $args{'download'};
433     foreach my $mod (@mods) {
434         $CPAN::Config->{'build_dir'} = $moddir;
435         CPAN::get($mod);
436     }
437
438     opendir(DIR, $moddir);
439     while ( my $dir = readdir(DIR)) {
440         print "Dir is $dir\n";
441         next if ( $dir =~ /^\.\.?$/);
442
443         # Skip things we've previously tagged
444         my $out = `svn ls $args{'repository'}/tags/$dir`;
445         next if ($out);
446
447         if ($dir =~ /^(.*)-(.*?)$/) {
448             `svn_load_dirs -no_user_input -t tags/$dir -v $args{'repository'} dists/$1 $moddir/$dir`;
449             `rm -rf $moddir/$dir`;
450
451         }
452
453     }
454     closedir(DIR);
455     exit;
456 }
457
458 sub check_perl_version {
459   section("perl");
460   eval {require 5.008003};
461   if ($@) {
462     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.");
463     exit(1);
464   } else {
465     found( ">=5.8.3($])", 1);
466   }
467 }
468
469 sub check_users {
470   section("users");
471   found("rt group (@RTGROUP@)",      defined getgrnam("@RTGROUP@"));
472   found("bin owner (@BIN_OWNER@)",   defined getpwnam("@BIN_OWNER@"));
473   found("libs owner (@LIBS_OWNER@)", defined getpwnam("@LIBS_OWNER@"));
474   found("libs group (@LIBS_GROUP@)", defined getgrnam("@LIBS_GROUP@"));
475   found("web owner (@WEB_USER@)",    defined getpwnam("@WEB_USER@"));
476   found("web group (@WEB_GROUP@)",   defined getgrnam("@WEB_GROUP@"));
477 }
478
479
480
481 1;