Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
267 lines (211 sloc) 7.33 KB
#!/usr/bin/perl -w
=head1 Name - installation script to install CPAN modules
=head1 Description
This script is called during "make install" to install Perl modules
from CPAN.
=head1 Author
Sam Tregar <>
=head1 See Also
use strict;
use File::Spec::Functions qw(:ALL);
use Cwd;
our $MOD;
my $perl;
my $cwd;
BEGIN { $perl = $ENV{PERL} || $^X }
# Figure out where we are.
$cwd = getcwd;
# read in list of required modules
do "./modules.db" or die "Failed to read modules.db : $!";
# See if we need to install any modules.
my $need;
for my $i (0 .. $#$MOD) {
next if $MOD->[$i]{found};
$need = 1;
unless ($need) {
# Don't need to install any, no need to run
print "All modules installed. No need to install from CPAN.\n";
# try to figure out if has been configured. This mimics
# the logic in If this turns out not to be reliable
# another possibility would be to just `perl -MCPAN -e shell` and
# look for the "configuration required" text.
my $found_config = 0;
eval { require CPAN::Config };
$found_config = 1 unless $@;
unshift(@INC, catdir($ENV{HOME}, '.cpan'));
eval { require CPAN::MyConfig };
$found_config = 1 unless $@;
unless ($found_config) {
print "#" x 79, "\n\n", <<END, "\n", "#" x 79, "\n";
This installation system uses to automatically install CPAN
modules. I have detected that you have never used to install
Perl modules. Before I can proceed with this installation you must
configure the module. To do this, type the following command
as root:
$perl -MCPAN -e shell
You will be presented with a series of questions. At the end you will
be at a "cpan>" prompt. Next, you should install the latest
install CPAN
After this step you should quit the CPAN shell and run it one more
time to be certain it works. You may need to re-answer the
questionnaire at this time. Once you have a working come back
here are re-run "make install".
exit 1;
use Cwd;
use FindBin;
use lib "$FindBin::Bin/lib";
use Bric::Inst qw(:all);
use Data::Dumper;
use Config;
use CPAN;
# make sure this is a recent version of The stuff we're doing
# below is dependent on some recent fixes.
no warnings; # avoid blabber about "1.59_54" not being numeric
hard_fail(<<END) unless $CPAN::VERSION >= 1.59; version 1.59 or greater required. Please update your CPAN
installation using the command (as root):
$perl -MCPAN -e 'install CPAN'
After this step you should quit the CPAN shell and run it one more
time to be certain it works. You may need to re-answer the
questionnaire at this time. Once you have a working come back
here are re-run "make install".
# make sure we're root, otherwise uninformative errors result
unless ($> == 0) {
print "This process must (usually) be run as root.\n";
exit 1 unless ask_yesno("Continue as non-root user? ", 1);
print "\n\n==> Installing Modules From CPAN <==\n\n";
# setup flags for modules that need extra help to install
use constant FORCE => 1;
use constant PG_ENV => 2;
our %flags = (
'Net::Cmd' => FORCE,
'XML::Writer' => FORCE,
'Params::Validate' => FORCE,
'Cache::Cache' => FORCE,
'HTML::Mason' => FORCE,
our $DB;
do "./database.db" or die "Failed to read database.db : $!";
# loop through modules installing as we go
for my $i (0 .. $#$MOD) {
next if $MOD->[$i]{found};
install_module($MOD->[$i]{name}, $MOD->[$i]{req_version});
$MOD->[$i]{found} = 1;
# make sure we don't redo this work, even if we're run twice in a
# row after a failure.
print "\n\n==> Finished Installing Modules From CPAN <==\n\n";
exit 0;
# installs a single module from CPAN, following dependencies
sub install_module {
my ($name, $req_version) = @_;
# push onto the queue. This keeps everything simpler below
if ( CPAN::Queue->can('new') ) {
CPAN::Queue->new( $name );
} else {
CPAN::Queue->queue_item( qmod => $name, reqtype => 'r' );
# process the queue
while (my $q = CPAN::Queue->first) {
# get a module object one way or another
my $s = ref $q && $q->can('as_string')
? $q->as_string
: ref $q ? $q->id : $q;
my $m = $q->can('as_string')
? CPAN::Shell->expandany($s)
: ref $q ? $q : CPAN::Shell->expandany($q);
hard_fail(<<END) unless $m;
Could not find $s on CPAN. Your installation
may be broken. To debug manually, run:
$perl -MCPAN -e 'install $s'
print "Found $s Installing...\n";
# If dependencies were pushed in front of this module, undelay it
# so that it can now proceed.
# get name of module being installed
my $key = $m->isa('CPAN::Distribution') ? $m->called_for : $s;
# for some reason that doesn't work for HTML::Mason
$key = 'HTML::Mason' unless defined $key;
# sometimes I used a little too much force
$m->force('install') if $flags{$key} and $flags{$key} & FORCE;
# need PG env vars?
if ($flags{$key} and $flags{$key} & PG_ENV) {
$ENV{POSTGRES_INCLUDE} = $DB->{include_dir};
$ENV{POSTGRES_LIB} = $DB->{lib_dir};
# do the install. If prereqs are found they'll get put on the Queue
# and processed in turn.
print "Install\n";
if (
($m->can('uptodate') ? $m->uptodate : 0) # It's up-to-date
or ($m->{install} && $m->{install} eq 'YES') # It was installed
) {
# Done with that module!
print "Done\n";
} elsif (CPAN::Queue->first ne $q) {
# Prereqs need to be satisified.
} else {
# Something's fucked up.
exit 1;
if ($req_version && $m->can('inst_version')) {
# check to make sure it worked
print "Checking $name installation...\n";
my $inst = $m->inst_version or return undef;
local $^W = 0;
require CPAN::Version unless CPAN::Version->can('vcmp');
hard_fail(fail_msg( $perl, $name, $req_version))
unless CPAN::Version->vcmp( $inst, $req_version ) >= 0;
# remove self from the queue
# all done.
print "$name installed successfully.\n";
sub fail_msg {
my ($perl, $name, $req_version);
Installation of $name version $req_version failed. Your installation may be broken. To debug manually,
run (as root):
$perl -MCPAN -e shell
Then at the "cpan>" prompt:
look $name
You can then attempt to install the module manually with:
$perl Makefile.PL
make test
make install
# updates modules.db with progress
sub update_modules_db {
# update modules database with progress
chdir $cwd;
open(OUT, ">modules.db") or die "Unable to open modules.db : $!";
print OUT Data::Dumper->Dump([$MOD],['MOD']);
close OUT;
Something went wrong with that request. Please try again.