| 1 | #!/usr/bin/perl -w |
|---|
| 2 | |
|---|
| 3 | # |
|---|
| 4 | # This script is little more than a wrapper for CPAN that first ensures |
|---|
| 5 | # any module dependencies are first satisfied. All the 'real' shepherd |
|---|
| 6 | # logic is implemented in the 'shepherd' |
|---|
| 7 | # |
|---|
| 8 | # shepherd will only call this script whenever it installs any new |
|---|
| 9 | # programmes or whenever _this_ script is updated in some manner. |
|---|
| 10 | # |
|---|
| 11 | |
|---|
| 12 | my $progname = "install_deps"; |
|---|
| 13 | my $version = "0.01"; |
|---|
| 14 | my $CWD, my $MODULE_DIR; |
|---|
| 15 | |
|---|
| 16 | # we wrap this in a BEGIN prior to 'use CPAN' so as to trick |
|---|
| 17 | # CPAN into where to build our modules.. |
|---|
| 18 | BEGIN { |
|---|
| 19 | sub neatvalue { # from CPAN/HandleConfig.pm |
|---|
| 20 | my($v) = @_; |
|---|
| 21 | return "undef" unless defined $v; |
|---|
| 22 | my($t) = ref $v; |
|---|
| 23 | return "q[$v]" unless $t; |
|---|
| 24 | if ($t eq 'ARRAY') { |
|---|
| 25 | my(@m, @neat); |
|---|
| 26 | push @m, "["; |
|---|
| 27 | foreach my $elem (@$v) { |
|---|
| 28 | push @neat, "q[$elem]"; |
|---|
| 29 | } |
|---|
| 30 | push @m, join ", ", @neat; |
|---|
| 31 | push @m, "]"; |
|---|
| 32 | return join "", @m; |
|---|
| 33 | } |
|---|
| 34 | return "$v" unless $t eq 'HASH'; |
|---|
| 35 | my(@m, $key, $val); |
|---|
| 36 | while (($key,$val) = each %$v){ |
|---|
| 37 | last unless defined $key; # cautious programming in case (undef,undef) is true |
|---|
| 38 | push(@m,"q[$key]=>".neatvalue($val)) ; |
|---|
| 39 | } |
|---|
| 40 | return "{ ".join(', ',@m)." }"; |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | $| = 1; |
|---|
| 45 | my $shepherd_progname = 'shepherd'; |
|---|
| 46 | |
|---|
| 47 | # By default, Shepherd runs from ~/.shepherd/. If it's not run as a user, |
|---|
| 48 | # it will try /opt/shepherd/ instead. |
|---|
| 49 | $CWD = ($ENV{HOME} ? $ENV{HOME} . "/." : "/opt/") . $shepherd_progname; |
|---|
| 50 | -d $CWD or mkdir $CWD or die "Cannot create directory $CWD: $!"; |
|---|
| 51 | chdir($CWD); |
|---|
| 52 | $MODULE_DIR = "$CWD/CPAN"; |
|---|
| 53 | -d $MODULE_DIR or mkdir $MODULE_DIR or die "Cannot create directory $MODULE_DIR: $!"; |
|---|
| 54 | |
|---|
| 55 | # |
|---|
| 56 | # first check that we have important environment variables set |
|---|
| 57 | # |
|---|
| 58 | if (!defined $ENV{HAVE_INSTALLED_SHEPHERD_VARS}) { |
|---|
| 59 | $ENV{HAVE_INSTALLED_SHEPHERD_VARS} = 1; |
|---|
| 60 | $ENV{PERL5LIB} = "" if (!defined $ENV{PERL5LIB}); |
|---|
| 61 | $ENV{PERL5LIB} = "$MODULE_DIR:".$ENV{PERL5LIB}; |
|---|
| 62 | $ENV{JS_THREADSAFE} = "n"; # stop JavaScript asking us this question.. |
|---|
| 63 | system($0); # calls ourselves again |
|---|
| 64 | exit $?; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | # find the standard CPAN/Config.pm |
|---|
| 68 | my $loc; |
|---|
| 69 | foreach my $systemdir (@INC) { |
|---|
| 70 | if (-r "$systemdir/CPAN/Config.pm") { |
|---|
| 71 | $loc = $systemdir; |
|---|
| 72 | last; |
|---|
| 73 | } |
|---|
| 74 | } |
|---|
| 75 | die "could not locate system-wide CPAN/Config.pm: is CPAN set up?\n" unless $loc; |
|---|
| 76 | eval { require CPAN::Config }; |
|---|
| 77 | |
|---|
| 78 | # create our own overrides for specific items |
|---|
| 79 | $CPAN::Config->{'build_dir'} = $MODULE_DIR."/build"; |
|---|
| 80 | $CPAN::Config->{'cpan_home'} = $MODULE_DIR; |
|---|
| 81 | $CPAN::Config->{'histfile'} = $MODULE_DIR."/histfile"; |
|---|
| 82 | $CPAN::Config->{'inhibit_startup_message'} = 1; |
|---|
| 83 | $CPAN::Config->{'keep_source_where'} = $MODULE_DIR."/sources"; |
|---|
| 84 | $CPAN::Config->{'prerequisites_policy'} = "follow"; |
|---|
| 85 | $CPAN::Config->{'makepl_arg'} = "PREFIX=$MODULE_DIR/mod SITELIBEXP=$MODULE_DIR/mod LIB=$MODULE_DIR/mod INSTALLMAN1DIR=$MODULE_DIR/man INSTALLMAN3DIR=$MODULE_DIR/man INSTALLSITEMAN1DIR=$MODULE_DIR/man INSTALLSITEMAN3DIR=$MODULE_DIR/man"; |
|---|
| 86 | |
|---|
| 87 | open(F,">$MODULE_DIR/MyConfig.pm") || die "can't write to $MODULE_DIR/MyConfig.pm: $!\n"; |
|---|
| 88 | print F "\$"."CPAN::Config = \{\n"; |
|---|
| 89 | foreach my $k (keys %{$CPAN::Config}) { |
|---|
| 90 | my $v = $CPAN::Config->{$k}; |
|---|
| 91 | printf F " '%s' => %s,\n",$k,neatvalue($v); |
|---|
| 92 | } |
|---|
| 93 | print F "};\n1;\n__END__\n"; |
|---|
| 94 | close(F); |
|---|
| 95 | } |
|---|
| 96 | |
|---|
| 97 | #undef @INC; |
|---|
| 98 | push (@INC,$MODULE_DIR); |
|---|
| 99 | |
|---|
| 100 | require CPAN; |
|---|
| 101 | |
|---|
| 102 | print "$progname v$version (operating in $CWD, modules in $MODULE_DIR)\n\n"; |
|---|
| 103 | |
|---|
| 104 | print "CPAN home seems to be $CPAN::Config->{cpan_home}\n"; |
|---|
| 105 | |
|---|
| 106 | |
|---|
| 107 | # required modules list |
|---|
| 108 | # (generated from "grep '^use' ./shepherd */* | cut -d: -f2-100 | cut -d' ' -f2-100 | sort | uniq") |
|---|
| 109 | my @mod_list = |
|---|
| 110 | ( "Algorithm::Diff", "Compress::Zlib", "Cwd", "Data::Dumper", "Date::Manip", |
|---|
| 111 | "DateTime::Format::Strptime", "File::Basename", "File::Path", "Getopt::Long", |
|---|
| 112 | "HTML::Entities", "HTML::TokeParser", "HTML::TreeBuilder", |
|---|
| 113 | "Sub::Uplevel", "Test::Builder", "Test::Builder::Tester", "Test::Exception", |
|---|
| 114 | "HTTP::Request::Common", "IO::File", "JavaScript", "List::Compare", |
|---|
| 115 | "LWP::UserAgent", "Sort::Versions", "Storable", "Time::HiRes", |
|---|
| 116 | "XML::DOM", "XMLTV" ); |
|---|
| 117 | |
|---|
| 118 | print "Checking dependencies..\n"; |
|---|
| 119 | |
|---|
| 120 | foreach my $mod (@mod_list) { |
|---|
| 121 | print " >>>> $mod .. "; |
|---|
| 122 | |
|---|
| 123 | my $modname = $mod.".pm"; |
|---|
| 124 | $modname =~ s/::/\//g; |
|---|
| 125 | |
|---|
| 126 | eval { require $modname; }; |
|---|
| 127 | if ($@) { |
|---|
| 128 | print "got $@\n"; |
|---|
| 129 | sleep 5; |
|---|
| 130 | print "installing ..\n"; |
|---|
| 131 | my $obj = CPAN::Shell->expand("Module", $mod); |
|---|
| 132 | |
|---|
| 133 | $obj->install; |
|---|
| 134 | } else { |
|---|
| 135 | print "ok.\n"; |
|---|
| 136 | } |
|---|
| 137 | } |
|---|
| 138 | |
|---|