diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/CPAN.pm')
-rw-r--r-- | Master/tlpkg/tlperl/lib/CPAN.pm | 3774 |
1 files changed, 3774 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/CPAN.pm b/Master/tlpkg/tlperl/lib/CPAN.pm new file mode 100644 index 00000000000..9d09708afcc --- /dev/null +++ b/Master/tlpkg/tlperl/lib/CPAN.pm @@ -0,0 +1,3774 @@ +# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- +# vim: ts=4 sts=4 sw=4: +use strict; +package CPAN; +$CPAN::VERSION = '1.94_56'; +$CPAN::VERSION =~ s/_//; + +# we need to run chdir all over and we would get at wrong libraries +# there +use File::Spec (); +BEGIN { + if (File::Spec->can("rel2abs")) { + for my $inc (@INC) { + $inc = File::Spec->rel2abs($inc) unless ref $inc; + } + } +} +use CPAN::Author; +use CPAN::HandleConfig; +use CPAN::Version; +use CPAN::Bundle; +use CPAN::CacheMgr; +use CPAN::Complete; +use CPAN::Debug; +use CPAN::Distribution; +use CPAN::Distrostatus; +use CPAN::FTP; +use CPAN::Index 1.93; # https://rt.cpan.org/Ticket/Display.html?id=43349 +use CPAN::InfoObj; +use CPAN::Module; +use CPAN::Prompt; +use CPAN::URL; +use CPAN::Queue; +use CPAN::Tarzip; +use CPAN::DeferredCode; +use CPAN::Shell; +use CPAN::LWP::UserAgent; +use CPAN::Exception::RecursiveDependency; +use CPAN::Exception::yaml_not_installed; + +use Carp (); +use Config (); +use Cwd qw(chdir); +use DirHandle (); +use Exporter (); +use ExtUtils::MakeMaker qw(prompt); # for some unknown reason, + # 5.005_04 does not work without + # this +use File::Basename (); +use File::Copy (); +use File::Find; +use File::Path (); +use FileHandle (); +use Fcntl qw(:flock); +use Safe (); +use Sys::Hostname qw(hostname); +use Text::ParseWords (); +use Text::Wrap (); + +# protect against "called too early" +sub find_perl (); +sub anycwd (); +sub _uniq; + +no lib "."; + +require Mac::BuildTools if $^O eq 'MacOS'; +if ($ENV{PERL5_CPAN_IS_RUNNING} && $$ != $ENV{PERL5_CPAN_IS_RUNNING}) { + $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION} ||= $ENV{PERL5_CPAN_IS_RUNNING}; + my @rec = _uniq split(/,/, $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION}), $$; + $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION} = join ",", @rec; + # warn "# Note: Recursive call of CPAN.pm detected\n"; + my $w = sprintf "# Note: CPAN.pm is running in process %d now", pop @rec; + my %sleep = ( + 5 => 30, + 6 => 60, + 7 => 120, + ); + my $sleep = @rec > 7 ? 300 : ($sleep{scalar @rec}||0); + my $verbose = @rec >= 4; + while (@rec) { + $w .= sprintf " which has been called by process %d", pop @rec; + } + if ($sleep) { + $w .= ".\n\n# Sleeping $sleep seconds to protect other processes\n"; + } + if ($verbose) { + warn $w; + } + local $| = 1; + while ($sleep > 0) { + printf "\r#%5d", --$sleep; + sleep 1; + } + print "\n"; +} +$ENV{PERL5_CPAN_IS_RUNNING}=$$; +$ENV{PERL5_CPANPLUS_IS_RUNNING}=$$; # https://rt.cpan.org/Ticket/Display.html?id=23735 + +END { $CPAN::End++; &cleanup; } + +$CPAN::Signal ||= 0; +$CPAN::Frontend ||= "CPAN::Shell"; +unless (@CPAN::Defaultsites) { + @CPAN::Defaultsites = map { + CPAN::URL->new(TEXT => $_, FROM => "DEF") + } + "http://www.perl.org/CPAN/", + "ftp://ftp.perl.org/pub/CPAN/"; +} +# $CPAN::iCwd (i for initial) +$CPAN::iCwd ||= CPAN::anycwd(); +$CPAN::Perl ||= CPAN::find_perl(); +$CPAN::Defaultdocs ||= "http://search.cpan.org/perldoc?"; +$CPAN::Defaultrecent ||= "http://search.cpan.org/uploads.rdf"; +$CPAN::Defaultrecent ||= "http://cpan.uwinnipeg.ca/htdocs/cpan.xml"; + +# our globals are getting a mess +use vars qw( + $AUTOLOAD + $Be_Silent + $CONFIG_DIRTY + $Defaultdocs + $Echo_readline + $Frontend + $GOTOSHELL + $HAS_USABLE + $Have_warned + $MAX_RECURSION + $META + $RUN_DEGRADED + $Signal + $SQLite + $Suppress_readline + $VERSION + $autoload_recursion + $term + @Defaultsites + @EXPORT + ); + +$MAX_RECURSION = 32; + +@CPAN::ISA = qw(CPAN::Debug Exporter); + +# note that these functions live in CPAN::Shell and get executed via +# AUTOLOAD when called directly +@EXPORT = qw( + autobundle + bundle + clean + cvs_import + expand + force + fforce + get + install + install_tested + is_tested + make + mkmyconfig + notest + perldoc + readme + recent + recompile + report + shell + smoke + test + upgrade + ); + +sub soft_chdir_with_alternatives ($); + +{ + $autoload_recursion ||= 0; + + #-> sub CPAN::AUTOLOAD ; + sub AUTOLOAD { ## no critic + $autoload_recursion++; + my($l) = $AUTOLOAD; + $l =~ s/.*:://; + if ($CPAN::Signal) { + warn "Refusing to autoload '$l' while signal pending"; + $autoload_recursion--; + return; + } + if ($autoload_recursion > 1) { + my $fullcommand = join " ", map { "'$_'" } $l, @_; + warn "Refusing to autoload $fullcommand in recursion\n"; + $autoload_recursion--; + return; + } + my(%export); + @export{@EXPORT} = ''; + CPAN::HandleConfig->load unless $CPAN::Config_loaded++; + if (exists $export{$l}) { + CPAN::Shell->$l(@_); + } else { + die(qq{Unknown CPAN command "$AUTOLOAD". }. + qq{Type ? for help.\n}); + } + $autoload_recursion--; + } +} + +{ + my $x = *SAVEOUT; # avoid warning + open($x,">&STDOUT") or die "dup failed"; + my $redir = 0; + sub _redirect(@) { + #die if $redir; + local $_; + push(@_,undef); + while(defined($_=shift)) { + if (s/^\s*>//){ + my ($m) = s/^>// ? ">" : ""; + s/\s+//; + $_=shift unless length; + die "no dest" unless defined; + open(STDOUT,">$m$_") or die "open:$_:$!\n"; + $redir=1; + } elsif ( s/^\s*\|\s*// ) { + my $pipe="| $_"; + while(defined($_[0])){ + $pipe .= ' ' . shift; + } + open(STDOUT,$pipe) or die "open:$pipe:$!\n"; + $redir=1; + } else { + push(@_,$_); + } + } + return @_; + } + sub _unredirect { + return unless $redir; + $redir = 0; + ## redirect: unredirect and propagate errors. explicit close to wait for pipe. + close(STDOUT); + open(STDOUT,">&SAVEOUT"); + die "$@" if "$@"; + ## redirect: done + } +} + +sub _uniq { + my(@list) = @_; + my %seen; + return grep { !$seen{$_}++ } @list; +} + +#-> sub CPAN::shell ; +sub shell { + my($self) = @_; + $Suppress_readline = ! -t STDIN unless defined $Suppress_readline; + CPAN::HandleConfig->load unless $CPAN::Config_loaded++; + + my $oprompt = shift || CPAN::Prompt->new; + my $prompt = $oprompt; + my $commandline = shift || ""; + $CPAN::CurrentCommandId ||= 1; + + local($^W) = 1; + unless ($Suppress_readline) { + require Term::ReadLine; + if (! $term + or + $term->ReadLine eq "Term::ReadLine::Stub" + ) { + $term = Term::ReadLine->new('CPAN Monitor'); + } + if ($term->ReadLine eq "Term::ReadLine::Gnu") { + my $attribs = $term->Attribs; + $attribs->{attempted_completion_function} = sub { + &CPAN::Complete::gnu_cpl; + } + } else { + $readline::rl_completion_function = + $readline::rl_completion_function = 'CPAN::Complete::cpl'; + } + if (my $histfile = $CPAN::Config->{'histfile'}) {{ + unless ($term->can("AddHistory")) { + $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n"); + last; + } + $META->readhist($term,$histfile); + }} + for ($CPAN::Config->{term_ornaments}) { # alias + local $Term::ReadLine::termcap_nowarn = 1; + $term->ornaments($_) if defined; + } + # $term->OUT is autoflushed anyway + my $odef = select STDERR; + $| = 1; + select STDOUT; + $| = 1; + select $odef; + } + + $META->checklock(); + my @cwd = grep { defined $_ and length $_ } + CPAN::anycwd(), + File::Spec->can("tmpdir") ? File::Spec->tmpdir() : (), + File::Spec->rootdir(); + my $try_detect_readline; + $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub" if $term; + unless ($CPAN::Config->{inhibit_startup_message}) { + my $rl_avail = $Suppress_readline ? "suppressed" : + ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" : + "available (maybe install Bundle::CPAN or Bundle::CPANxxl?)"; + $CPAN::Frontend->myprint( + sprintf qq{ +cpan shell -- CPAN exploration and modules installation (v%s) +Enter 'h' for help. + +}, + $CPAN::VERSION, + $rl_avail + ) + } + my($continuation) = ""; + my $last_term_ornaments; + SHELLCOMMAND: while () { + if ($Suppress_readline) { + if ($Echo_readline) { + $|=1; + } + print $prompt; + last SHELLCOMMAND unless defined ($_ = <> ); + if ($Echo_readline) { + # backdoor: I could not find a way to record sessions + print $_; + } + chomp; + } else { + last SHELLCOMMAND unless + defined ($_ = $term->readline($prompt, $commandline)); + } + $_ = "$continuation$_" if $continuation; + s/^\s+//; + next SHELLCOMMAND if /^$/; + s/^\s*\?\s*/help /; + if (/^(?:q(?:uit)?|bye|exit)\s*$/i) { + last SHELLCOMMAND; + } elsif (s/\\$//s) { + chomp; + $continuation = $_; + $prompt = " > "; + } elsif (/^\!/) { + s/^\!//; + my($eval) = $_; + package + CPAN::Eval; # hide from the indexer + use strict; + use vars qw($import_done); + CPAN->import(':DEFAULT') unless $import_done++; + CPAN->debug("eval[$eval]") if $CPAN::DEBUG; + eval($eval); + warn $@ if $@; + $continuation = ""; + $prompt = $oprompt; + } elsif (/./) { + my(@line); + eval { @line = Text::ParseWords::shellwords($_) }; + warn($@), next SHELLCOMMAND if $@; + warn("Text::Parsewords could not parse the line [$_]"), + next SHELLCOMMAND unless @line; + $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG; + my $command = shift @line; + eval { + local (*STDOUT)=*STDOUT; + @line = _redirect(@line); + CPAN::Shell->$command(@line) + }; + my $command_error = $@; + _unredirect; + my $reported_error; + if ($command_error) { + my $err = $command_error; + if (ref $err and $err->isa('CPAN::Exception::blocked_urllist')) { + $CPAN::Frontend->mywarn("Client not fully configured, please proceed with configuring.$err"); + $reported_error = ref $err; + } else { + # I'd prefer never to arrive here and make all errors exception objects + if ($err =~ /\S/) { + require Carp; + require Dumpvalue; + my $dv = Dumpvalue->new(tick => '"'); + Carp::cluck(sprintf "Catching error: %s", $dv->stringify($err)); + } + } + } + if ($command =~ /^( + # classic commands + make + |test + |install + |clean + + # pragmas for classic commands + |ff?orce + |notest + + # compounds + |report + |smoke + |upgrade + )$/x) { + # only commands that tell us something about failed distros + # eval necessary for people without an urllist + eval {CPAN::Shell->failed($CPAN::CurrentCommandId,1);}; + if (my $err = $@) { + unless (ref $err and $reported_error eq ref $err) { + die $@; + } + } + } + soft_chdir_with_alternatives(\@cwd); + $CPAN::Frontend->myprint("\n"); + $continuation = ""; + $CPAN::CurrentCommandId++; + $prompt = $oprompt; + } + } continue { + $commandline = ""; # I do want to be able to pass a default to + # shell, but on the second command I see no + # use in that + $Signal=0; + CPAN::Queue->nullify_queue; + if ($try_detect_readline) { + if ($CPAN::META->has_inst("Term::ReadLine::Gnu") + || + $CPAN::META->has_inst("Term::ReadLine::Perl") + ) { + delete $INC{"Term/ReadLine.pm"}; + my $redef = 0; + local($SIG{__WARN__}) = CPAN::Shell::paintdots_onreload(\$redef); + require Term::ReadLine; + $CPAN::Frontend->myprint("\n$redef subroutines in ". + "Term::ReadLine redefined\n"); + $GOTOSHELL = 1; + } + } + if ($term and $term->can("ornaments")) { + for ($CPAN::Config->{term_ornaments}) { # alias + if (defined $_) { + if (not defined $last_term_ornaments + or $_ != $last_term_ornaments + ) { + local $Term::ReadLine::termcap_nowarn = 1; + $term->ornaments($_); + $last_term_ornaments = $_; + } + } else { + undef $last_term_ornaments; + } + } + } + for my $class (qw(Module Distribution)) { + # again unsafe meta access? + for my $dm (keys %{$CPAN::META->{readwrite}{"CPAN::$class"}}) { + next unless $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor}; + CPAN->debug("BUG: $class '$dm' was in command state, resetting"); + delete $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor}; + } + } + if ($GOTOSHELL) { + $GOTOSHELL = 0; # not too often + $META->savehist if $CPAN::term && $CPAN::term->can("GetHistory"); + @_ = ($oprompt,""); + goto &shell; + } + } + soft_chdir_with_alternatives(\@cwd); +} + +#-> CPAN::soft_chdir_with_alternatives ; +sub soft_chdir_with_alternatives ($) { + my($cwd) = @_; + unless (@$cwd) { + my $root = File::Spec->rootdir(); + $CPAN::Frontend->mywarn(qq{Warning: no good directory to chdir to! +Trying '$root' as temporary haven. +}); + push @$cwd, $root; + } + while () { + if (chdir $cwd->[0]) { + return; + } else { + if (@$cwd>1) { + $CPAN::Frontend->mywarn(qq{Could not chdir to "$cwd->[0]": $! +Trying to chdir to "$cwd->[1]" instead. +}); + shift @$cwd; + } else { + $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd->[0]": $!}); + } + } + } +} + +sub _flock { + my($fh,$mode) = @_; + if ( $Config::Config{d_flock} || $Config::Config{d_fcntl_can_lock} ) { + return flock $fh, $mode; + } elsif (!$Have_warned->{"d_flock"}++) { + $CPAN::Frontend->mywarn("Your OS does not seem to support locking; continuing and ignoring all locking issues\n"); + $CPAN::Frontend->mysleep(5); + return 1; + } else { + return 1; + } +} + +sub _yaml_module () { + my $yaml_module = $CPAN::Config->{yaml_module} || "YAML"; + if ( + $yaml_module ne "YAML" + && + !$CPAN::META->has_inst($yaml_module) + ) { + # $CPAN::Frontend->mywarn("'$yaml_module' not installed, falling back to 'YAML'\n"); + $yaml_module = "YAML"; + } + if ($yaml_module eq "YAML" + && + $CPAN::META->has_inst($yaml_module) + && + $YAML::VERSION < 0.60 + && + !$Have_warned->{"YAML"}++ + ) { + $CPAN::Frontend->mywarn("Warning: YAML version '$YAML::VERSION' is too low, please upgrade!\n". + "I'll continue but problems are *very* likely to happen.\n" + ); + $CPAN::Frontend->mysleep(5); + } + return $yaml_module; +} + +# CPAN::_yaml_loadfile +sub _yaml_loadfile { + my($self,$local_file) = @_; + return +[] unless -s $local_file; + my $yaml_module = _yaml_module; + if ($CPAN::META->has_inst($yaml_module)) { + # temporarly enable yaml code deserialisation + no strict 'refs'; + # 5.6.2 could not do the local() with the reference + # so we do it manually instead + my $old_loadcode = ${"$yaml_module\::LoadCode"}; + ${ "$yaml_module\::LoadCode" } = $CPAN::Config->{yaml_load_code} || 0; + + my ($code, @yaml); + if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) { + eval { @yaml = $code->($local_file); }; + if ($@) { + # this shall not be done by the frontend + die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@); + } + } elsif ($code = UNIVERSAL::can($yaml_module, "Load")) { + local *FH; + open FH, $local_file or die "Could not open '$local_file': $!"; + local $/; + my $ystream = <FH>; + eval { @yaml = $code->($ystream); }; + if ($@) { + # this shall not be done by the frontend + die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@); + } + } + ${"$yaml_module\::LoadCode"} = $old_loadcode; + return \@yaml; + } else { + # this shall not be done by the frontend + die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "parse"); + } + return +[]; +} + +# CPAN::_yaml_dumpfile +sub _yaml_dumpfile { + my($self,$local_file,@what) = @_; + my $yaml_module = _yaml_module; + if ($CPAN::META->has_inst($yaml_module)) { + my $code; + if (UNIVERSAL::isa($local_file, "FileHandle")) { + $code = UNIVERSAL::can($yaml_module, "Dump"); + eval { print $local_file $code->(@what) }; + } elsif ($code = UNIVERSAL::can($yaml_module, "DumpFile")) { + eval { $code->($local_file,@what); }; + } elsif ($code = UNIVERSAL::can($yaml_module, "Dump")) { + local *FH; + open FH, ">$local_file" or die "Could not open '$local_file': $!"; + print FH $code->(@what); + } + if ($@) { + die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"dump",$@); + } + } else { + if (UNIVERSAL::isa($local_file, "FileHandle")) { + # I think this case does not justify a warning at all + } else { + die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "dump"); + } + } +} + +sub _init_sqlite () { + unless ($CPAN::META->has_inst("CPAN::SQLite")) { + $CPAN::Frontend->mywarn(qq{CPAN::SQLite not installed, trying to work without\n}) + unless $Have_warned->{"CPAN::SQLite"}++; + return; + } + require CPAN::SQLite::META; # not needed since CVS version of 2006-12-17 + $CPAN::SQLite ||= CPAN::SQLite::META->new($CPAN::META); +} + +{ + my $negative_cache = {}; + sub _sqlite_running { + if ($negative_cache->{time} && time < $negative_cache->{time} + 60) { + # need to cache the result, otherwise too slow + return $negative_cache->{fact}; + } else { + $negative_cache = {}; # reset + } + my $ret = $CPAN::Config->{use_sqlite} && ($CPAN::SQLite || _init_sqlite()); + return $ret if $ret; # fast anyway + $negative_cache->{time} = time; + return $negative_cache->{fact} = $ret; + } +} + +$META ||= CPAN->new; # In case we re-eval ourselves we need the || + +# from here on only subs. +################################################################################ + +sub _perl_fingerprint { + my($self,$other_fingerprint) = @_; + my $dll = eval {OS2::DLLname()}; + my $mtime_dll = 0; + if (defined $dll) { + $mtime_dll = (-f $dll ? (stat(_))[9] : '-1'); + } + my $mtime_perl = (-f CPAN::find_perl ? (stat(_))[9] : '-1'); + my $this_fingerprint = { + '$^X' => CPAN::find_perl, + sitearchexp => $Config::Config{sitearchexp}, + 'mtime_$^X' => $mtime_perl, + 'mtime_dll' => $mtime_dll, + }; + if ($other_fingerprint) { + if (exists $other_fingerprint->{'stat($^X)'}) { # repair fp from rev. 1.88_57 + $other_fingerprint->{'mtime_$^X'} = $other_fingerprint->{'stat($^X)'}[9]; + } + # mandatory keys since 1.88_57 + for my $key (qw($^X sitearchexp mtime_dll mtime_$^X)) { + return unless $other_fingerprint->{$key} eq $this_fingerprint->{$key}; + } + return 1; + } else { + return $this_fingerprint; + } +} + +sub suggest_myconfig () { + SUGGEST_MYCONFIG: if(!$INC{'CPAN/MyConfig.pm'}) { + $CPAN::Frontend->myprint("You don't seem to have a user ". + "configuration (MyConfig.pm) yet.\n"); + my $new = CPAN::Shell::colorable_makemaker_prompt("Do you want to create a ". + "user configuration now? (Y/n)", + "yes"); + if($new =~ m{^y}i) { + CPAN::Shell->mkmyconfig(); + return &checklock; + } else { + $CPAN::Frontend->mydie("OK, giving up."); + } + } +} + +#-> sub CPAN::all_objects ; +sub all_objects { + my($mgr,$class) = @_; + CPAN::HandleConfig->load unless $CPAN::Config_loaded++; + CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG; + CPAN::Index->reload; + values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok +} + +# Called by shell, not in batch mode. In batch mode I see no risk in +# having many processes updating something as installations are +# continually checked at runtime. In shell mode I suspect it is +# unintentional to open more than one shell at a time + +#-> sub CPAN::checklock ; +sub checklock { + my($self) = @_; + my $lockfile = File::Spec->catfile($CPAN::Config->{cpan_home},".lock"); + if (-f $lockfile && -M _ > 0) { + my $fh = FileHandle->new($lockfile) or + $CPAN::Frontend->mydie("Could not open lockfile '$lockfile': $!"); + my $otherpid = <$fh>; + my $otherhost = <$fh>; + $fh->close; + if (defined $otherpid && $otherpid) { + chomp $otherpid; + } + if (defined $otherhost && $otherhost) { + chomp $otherhost; + } + my $thishost = hostname(); + if (defined $otherhost && defined $thishost && + $otherhost ne '' && $thishost ne '' && + $otherhost ne $thishost) { + $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile '$lockfile'\n". + "reports other host $otherhost and other ". + "process $otherpid.\n". + "Cannot proceed.\n")); + } elsif ($RUN_DEGRADED) { + $CPAN::Frontend->mywarn("Running in downgraded mode (experimental)\n"); + } elsif (defined $otherpid && $otherpid) { + return if $$ == $otherpid; # should never happen + $CPAN::Frontend->mywarn( + qq{ +There seems to be running another CPAN process (pid $otherpid). Contacting... +}); + if (kill 0, $otherpid or $!{EPERM}) { + $CPAN::Frontend->mywarn(qq{Other job is running.\n}); + my($ans) = + CPAN::Shell::colorable_makemaker_prompt + (qq{Shall I try to run in downgraded }. + qq{mode? (Y/n)},"y"); + if ($ans =~ /^y/i) { + $CPAN::Frontend->mywarn("Running in downgraded mode (experimental). +Please report if something unexpected happens\n"); + $RUN_DEGRADED = 1; + for ($CPAN::Config) { + # XXX + # $_->{build_dir_reuse} = 0; # 2006-11-17 akoenig Why was that? + $_->{commandnumber_in_prompt} = 0; # visibility + $_->{histfile} = ""; # who should win otherwise? + $_->{cache_metadata} = 0; # better would be a lock? + $_->{use_sqlite} = 0; # better would be a write lock! + $_->{auto_commit} = 0; # we are violent, do not persist + $_->{test_report} = 0; # Oliver Paukstadt had sent wrong reports in degraded mode + } + } else { + $CPAN::Frontend->mydie(" +You may want to kill the other job and delete the lockfile. On UNIX try: + kill $otherpid + rm $lockfile +"); + } + } elsif (-w $lockfile) { + my($ans) = + CPAN::Shell::colorable_makemaker_prompt + (qq{Other job not responding. Shall I overwrite }. + qq{the lockfile '$lockfile'? (Y/n)},"y"); + $CPAN::Frontend->myexit("Ok, bye\n") + unless $ans =~ /^y/i; + } else { + Carp::croak( + qq{Lockfile '$lockfile' not writable by you. }. + qq{Cannot proceed.\n}. + qq{ On UNIX try:\n}. + qq{ rm '$lockfile'\n}. + qq{ and then rerun us.\n} + ); + } + } else { + $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Found invalid lockfile ". + "'$lockfile', please remove. Cannot proceed.\n")); + } + } + my $dotcpan = $CPAN::Config->{cpan_home}; + eval { File::Path::mkpath($dotcpan);}; + if ($@) { + # A special case at least for Jarkko. + my $firsterror = $@; + my $seconderror; + my $symlinkcpan; + if (-l $dotcpan) { + $symlinkcpan = readlink $dotcpan; + die "readlink $dotcpan failed: $!" unless defined $symlinkcpan; + eval { File::Path::mkpath($symlinkcpan); }; + if ($@) { + $seconderror = $@; + } else { + $CPAN::Frontend->mywarn(qq{ +Working directory $symlinkcpan created. +}); + } + } + unless (-d $dotcpan) { + my $mess = qq{ +Your configuration suggests "$dotcpan" as your +CPAN.pm working directory. I could not create this directory due +to this error: $firsterror\n}; + $mess .= qq{ +As "$dotcpan" is a symlink to "$symlinkcpan", +I tried to create that, but I failed with this error: $seconderror +} if $seconderror; + $mess .= qq{ +Please make sure the directory exists and is writable. +}; + $CPAN::Frontend->mywarn($mess); + return suggest_myconfig; + } + } # $@ after eval mkpath $dotcpan + if (0) { # to test what happens when a race condition occurs + for (reverse 1..10) { + print $_, "\n"; + sleep 1; + } + } + # locking + if (!$RUN_DEGRADED && !$self->{LOCKFH}) { + my $fh; + unless ($fh = FileHandle->new("+>>$lockfile")) { + if ($! =~ /Permission/) { + $CPAN::Frontend->mywarn(qq{ + +Your configuration suggests that CPAN.pm should use a working +directory of + $CPAN::Config->{cpan_home} +Unfortunately we could not create the lock file + $lockfile +due to permission problems. + +Please make sure that the configuration variable + \$CPAN::Config->{cpan_home} +points to a directory where you can write a .lock file. You can set +this variable in either a CPAN/MyConfig.pm or a CPAN/Config.pm in your +\@INC path; +}); + return suggest_myconfig; + } + } + my $sleep = 1; + while (!CPAN::_flock($fh, LOCK_EX|LOCK_NB)) { + if ($sleep>10) { + $CPAN::Frontend->mydie("Giving up\n"); + } + $CPAN::Frontend->mysleep($sleep++); + $CPAN::Frontend->mywarn("Could not lock lockfile with flock: $!; retrying\n"); + } + + seek $fh, 0, 0; + truncate $fh, 0; + $fh->autoflush(1); + $fh->print($$, "\n"); + $fh->print(hostname(), "\n"); + $self->{LOCK} = $lockfile; + $self->{LOCKFH} = $fh; + } + $SIG{TERM} = sub { + my $sig = shift; + &cleanup; + $CPAN::Frontend->mydie("Got SIG$sig, leaving"); + }; + $SIG{INT} = sub { + # no blocks!!! + my $sig = shift; + &cleanup if $Signal; + die "Got yet another signal" if $Signal > 1; + $CPAN::Frontend->mydie("Got another SIG$sig") if $Signal; + $CPAN::Frontend->mywarn("Caught SIG$sig, trying to continue\n"); + $Signal++; + }; + +# From: Larry Wall <larry@wall.org> +# Subject: Re: deprecating SIGDIE +# To: perl5-porters@perl.org +# Date: Thu, 30 Sep 1999 14:58:40 -0700 (PDT) +# +# The original intent of __DIE__ was only to allow you to substitute one +# kind of death for another on an application-wide basis without respect +# to whether you were in an eval or not. As a global backstop, it should +# not be used any more lightly (or any more heavily :-) than class +# UNIVERSAL. Any attempt to build a general exception model on it should +# be politely squashed. Any bug that causes every eval {} to have to be +# modified should be not so politely squashed. +# +# Those are my current opinions. It is also my optinion that polite +# arguments degenerate to personal arguments far too frequently, and that +# when they do, it's because both people wanted it to, or at least didn't +# sufficiently want it not to. +# +# Larry + + # global backstop to cleanup if we should really die + $SIG{__DIE__} = \&cleanup; + $self->debug("Signal handler set.") if $CPAN::DEBUG; +} + +#-> sub CPAN::DESTROY ; +sub DESTROY { + &cleanup; # need an eval? +} + +#-> sub CPAN::anycwd ; +sub anycwd () { + my $getcwd; + $getcwd = $CPAN::Config->{'getcwd'} || 'cwd'; + CPAN->$getcwd(); +} + +#-> sub CPAN::cwd ; +sub cwd {Cwd::cwd();} + +#-> sub CPAN::getcwd ; +sub getcwd {Cwd::getcwd();} + +#-> sub CPAN::fastcwd ; +sub fastcwd {Cwd::fastcwd();} + +#-> sub CPAN::backtickcwd ; +sub backtickcwd {my $cwd = `cwd`; chomp $cwd; $cwd} + +#-> sub CPAN::find_perl ; +sub find_perl () { + my($perl) = File::Spec->file_name_is_absolute($^X) ? $^X : ""; + unless ($perl) { + my $candidate = File::Spec->catfile($CPAN::iCwd,$^X); + $^X = $perl = $candidate if MM->maybe_command($candidate); + } + unless ($perl) { + my ($component,$perl_name); + DIST_PERLNAME: foreach $perl_name ($^X, 'perl', 'perl5', "perl$]") { + PATH_COMPONENT: foreach $component (File::Spec->path(), + $Config::Config{'binexp'}) { + next unless defined($component) && $component; + my($abs) = File::Spec->catfile($component,$perl_name); + if (MM->maybe_command($abs)) { + $^X = $perl = $abs; + last DIST_PERLNAME; + } + } + } + } + return $perl; +} + + +#-> sub CPAN::exists ; +sub exists { + my($mgr,$class,$id) = @_; + CPAN::HandleConfig->load unless $CPAN::Config_loaded++; + CPAN::Index->reload; + ### Carp::croak "exists called without class argument" unless $class; + $id ||= ""; + $id =~ s/:+/::/g if $class eq "CPAN::Module"; + my $exists; + if (CPAN::_sqlite_running) { + $exists = (exists $META->{readonly}{$class}{$id} or + $CPAN::SQLite->set($class, $id)); + } else { + $exists = exists $META->{readonly}{$class}{$id}; + } + $exists ||= exists $META->{readwrite}{$class}{$id}; # unsafe meta access, ok +} + +#-> sub CPAN::delete ; +sub delete { + my($mgr,$class,$id) = @_; + delete $META->{readonly}{$class}{$id}; # unsafe meta access, ok + delete $META->{readwrite}{$class}{$id}; # unsafe meta access, ok +} + +#-> sub CPAN::has_usable +# has_inst is sometimes too optimistic, we should replace it with this +# has_usable whenever a case is given +sub has_usable { + my($self,$mod,$message) = @_; + return 1 if $HAS_USABLE->{$mod}; + my $has_inst = $self->has_inst($mod,$message); + return unless $has_inst; + my $usable; + $usable = { + + # + # these subroutines die if they believe the installed version is unusable; + # + + LWP => [ # we frequently had "Can't locate object + # method "new" via package "LWP::UserAgent" at + # (eval 69) line 2006 + sub {require LWP}, + sub {require LWP::UserAgent}, + sub {require HTTP::Request}, + sub {require URI::URL; + unless (CPAN::Version->vge(URI::URL::->VERSION,0.08)) { + for ("Will not use URI::URL, need 0.08\n") { + $CPAN::Frontend->mywarn($_); + die $_; + } + } + }, + ], + 'Net::FTP' => [ + sub {require Net::FTP}, + sub {require Net::Config}, + ], + 'File::HomeDir' => [ + sub {require File::HomeDir; + unless (CPAN::Version->vge(File::HomeDir::->VERSION, 0.52)) { + for ("Will not use File::HomeDir, need 0.52\n") { + $CPAN::Frontend->mywarn($_); + die $_; + } + } + }, + ], + 'Archive::Tar' => [ + sub {require Archive::Tar; + my $demand = "1.50"; + unless (CPAN::Version->vge(Archive::Tar::->VERSION, $demand)) { + my $atv = Archive::Tar->VERSION; + for ("You have Archive::Tar $atv, but $demand or later is recommended. Please upgrade.\n") { + $CPAN::Frontend->mywarn($_); + # don't die, because we may need + # Archive::Tar to upgrade + } + + } + }, + ], + 'File::Temp' => [ + # XXX we should probably delete from + # %INC too so we can load after we + # installed a new enough version -- + # I'm not sure. + sub {require File::Temp; + unless (CPAN::Version->vge(File::Temp::->VERSION,0.16)) { + for ("Will not use File::Temp, need 0.16\n") { + $CPAN::Frontend->mywarn($_); + die $_; + } + } + }, + ] + }; + if ($usable->{$mod}) { + for my $c (0..$#{$usable->{$mod}}) { + my $code = $usable->{$mod}[$c]; + my $ret = eval { &$code() }; + $ret = "" unless defined $ret; + if ($@) { + # warn "DEBUG: c[$c]\$\@[$@]ret[$ret]"; + return; + } + } + } + return $HAS_USABLE->{$mod} = 1; +} + +#-> sub CPAN::has_inst +sub has_inst { + my($self,$mod,$message) = @_; + Carp::croak("CPAN->has_inst() called without an argument") + unless defined $mod; + my %dont = map { $_ => 1 } keys %{$CPAN::META->{dontload_hash}||{}}, + keys %{$CPAN::Config->{dontload_hash}||{}}, + @{$CPAN::Config->{dontload_list}||[]}; + if (defined $message && $message eq "no" # afair only used by Nox + || + $dont{$mod} + ) { + $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok + return 0; + } + my $file = $mod; + my $obj; + $file =~ s|::|/|g; + $file .= ".pm"; + if ($INC{$file}) { + # checking %INC is wrong, because $INC{LWP} may be true + # although $INC{"URI/URL.pm"} may have failed. But as + # I really want to say "bla loaded OK", I have to somehow + # cache results. + ### warn "$file in %INC"; #debug + return 1; + } elsif (eval { require $file }) { + # eval is good: if we haven't yet read the database it's + # perfect and if we have installed the module in the meantime, + # it tries again. The second require is only a NOOP returning + # 1 if we had success, otherwise it's retrying + + my $mtime = (stat $INC{$file})[9]; + # privileged files loaded by has_inst; Note: we use $mtime + # as a proxy for a checksum. + $CPAN::Shell::reload->{$file} = $mtime; + my $v = eval "\$$mod\::VERSION"; + $v = $v ? " (v$v)" : ""; + CPAN::Shell->optprint("load_module","CPAN: $mod loaded ok$v\n"); + if ($mod eq "CPAN::WAIT") { + push @CPAN::Shell::ISA, 'CPAN::WAIT'; + } + return 1; + } elsif ($mod eq "Net::FTP") { + $CPAN::Frontend->mywarn(qq{ + Please, install Net::FTP as soon as possible. CPAN.pm installs it for you + if you just type + install Bundle::libnet + +}) unless $Have_warned->{"Net::FTP"}++; + $CPAN::Frontend->mysleep(3); + } elsif ($mod eq "Digest::SHA") { + if ($Have_warned->{"Digest::SHA"}++) { + $CPAN::Frontend->mywarn(qq{CPAN: checksum security checks disabled }. + qq{because Digest::SHA not installed.\n}); + } else { + $CPAN::Frontend->mywarn(qq{ + CPAN: checksum security checks disabled because Digest::SHA not installed. + Please consider installing the Digest::SHA module. + +}); + $CPAN::Frontend->mysleep(2); + } + } elsif ($mod eq "Module::Signature") { + # NOT prefs_lookup, we are not a distro + my $check_sigs = $CPAN::Config->{check_sigs}; + if (not $check_sigs) { + # they do not want us:-( + } elsif (not $Have_warned->{"Module::Signature"}++) { + # No point in complaining unless the user can + # reasonably install and use it. + if (eval { require Crypt::OpenPGP; 1 } || + ( + defined $CPAN::Config->{'gpg'} + && + $CPAN::Config->{'gpg'} =~ /\S/ + ) + ) { + $CPAN::Frontend->mywarn(qq{ + CPAN: Module::Signature security checks disabled because Module::Signature + not installed. Please consider installing the Module::Signature module. + You may also need to be able to connect over the Internet to the public + keyservers like pgp.mit.edu (port 11371). + +}); + $CPAN::Frontend->mysleep(2); + } + } + } else { + delete $INC{$file}; # if it inc'd LWP but failed during, say, URI + } + return 0; +} + +#-> sub CPAN::instance ; +sub instance { + my($mgr,$class,$id) = @_; + CPAN::Index->reload; + $id ||= ""; + # unsafe meta access, ok? + return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id}; + $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id); +} + +#-> sub CPAN::new ; +sub new { + bless {}, shift; +} + +#-> sub CPAN::cleanup ; +sub cleanup { + # warn "cleanup called with arg[@_] End[$CPAN::End] Signal[$Signal]"; + local $SIG{__DIE__} = ''; + my($message) = @_; + my $i = 0; + my $ineval = 0; + my($subroutine); + while ((undef,undef,undef,$subroutine) = caller(++$i)) { + $ineval = 1, last if + $subroutine eq '(eval)'; + } + return if $ineval && !$CPAN::End; + return unless defined $META->{LOCK}; + return unless -f $META->{LOCK}; + $META->savehist; + close $META->{LOCKFH}; + unlink $META->{LOCK}; + # require Carp; + # Carp::cluck("DEBUGGING"); + if ( $CPAN::CONFIG_DIRTY ) { + $CPAN::Frontend->mywarn("Warning: Configuration not saved.\n"); + } + $CPAN::Frontend->myprint("Lockfile removed.\n"); +} + +#-> sub CPAN::readhist +sub readhist { + my($self,$term,$histfile) = @_; + my $histsize = $CPAN::Config->{'histsize'} || 100; + $term->Attribs->{'MaxHistorySize'} = $histsize if (defined($term->Attribs->{'MaxHistorySize'})); + my($fh) = FileHandle->new; + open $fh, "<$histfile" or return; + local $/ = "\n"; + while (<$fh>) { + chomp; + $term->AddHistory($_); + } + close $fh; +} + +#-> sub CPAN::savehist +sub savehist { + my($self) = @_; + my($histfile,$histsize); + unless ($histfile = $CPAN::Config->{'histfile'}) { + $CPAN::Frontend->mywarn("No history written (no histfile specified).\n"); + return; + } + $histsize = $CPAN::Config->{'histsize'} || 100; + if ($CPAN::term) { + unless ($CPAN::term->can("GetHistory")) { + $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n"); + return; + } + } else { + return; + } + my @h = $CPAN::term->GetHistory; + splice @h, 0, @h-$histsize if @h>$histsize; + my($fh) = FileHandle->new; + open $fh, ">$histfile" or $CPAN::Frontend->mydie("Couldn't open >$histfile: $!"); + local $\ = local $, = "\n"; + print $fh @h; + close $fh; +} + +#-> sub CPAN::is_tested +sub is_tested { + my($self,$what,$when) = @_; + unless ($what) { + Carp::cluck("DEBUG: empty what"); + return; + } + $self->{is_tested}{$what} = $when; +} + +#-> sub CPAN::reset_tested +# forget all distributions tested -- resets what gets included in PERL5LIB +sub reset_tested { + my ($self) = @_; + $self->{is_tested} = {}; +} + +#-> sub CPAN::is_installed +# unsets the is_tested flag: as soon as the thing is installed, it is +# not needed in set_perl5lib anymore +sub is_installed { + my($self,$what) = @_; + delete $self->{is_tested}{$what}; +} + +sub _list_sorted_descending_is_tested { + my($self) = @_; + sort + { ($self->{is_tested}{$b}||0) <=> ($self->{is_tested}{$a}||0) } + keys %{$self->{is_tested}} +} + +#-> sub CPAN::set_perl5lib +# Notes on max environment variable length: +# - Win32 : XP or later, 8191; Win2000 or NT4, 2047 +{ +my $fh; +sub set_perl5lib { + my($self,$for) = @_; + unless ($for) { + (undef,undef,undef,$for) = caller(1); + $for =~ s/.*://; + } + $self->{is_tested} ||= {}; + return unless %{$self->{is_tested}}; + my $env = $ENV{PERL5LIB}; + $env = $ENV{PERLLIB} unless defined $env; + my @env; + push @env, split /\Q$Config::Config{path_sep}\E/, $env if defined $env and length $env; + #my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}}; + #$CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n"); + + my @dirs = map {("$_/blib/arch", "$_/blib/lib")} $self->_list_sorted_descending_is_tested; + return if !@dirs; + + if (@dirs < 12) { + $CPAN::Frontend->optprint('perl5lib', "Prepending @dirs to PERL5LIB for '$for'\n"); + $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; + } elsif (@dirs < 24 ) { + my @d = map {my $cp = $_; + $cp =~ s/^\Q$CPAN::Config->{build_dir}\E/%BUILDDIR%/; + $cp + } @dirs; + $CPAN::Frontend->optprint('perl5lib', "Prepending @d to PERL5LIB; ". + "%BUILDDIR%=$CPAN::Config->{build_dir} ". + "for '$for'\n" + ); + $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; + } else { + my $cnt = keys %{$self->{is_tested}}; + $CPAN::Frontend->optprint('perl5lib', "Prepending blib/arch and blib/lib of ". + "$cnt build dirs to PERL5LIB; ". + "for '$for'\n" + ); + $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env; + } +}} + + +1; + + +__END__ + +=head1 NAME + +CPAN - query, download and build perl modules from CPAN sites + +=head1 SYNOPSIS + +Interactive mode: + + perl -MCPAN -e shell + +--or-- + + cpan + +Basic commands: + + # Modules: + + cpan> install Acme::Meta # in the shell + + CPAN::Shell->install("Acme::Meta"); # in perl + + # Distributions: + + cpan> install NWCLARK/Acme-Meta-0.02.tar.gz # in the shell + + CPAN::Shell-> + install("NWCLARK/Acme-Meta-0.02.tar.gz"); # in perl + + # module objects: + + $mo = CPAN::Shell->expandany($mod); + $mo = CPAN::Shell->expand("Module",$mod); # same thing + + # distribution objects: + + $do = CPAN::Shell->expand("Module",$mod)->distribution; + $do = CPAN::Shell->expandany($distro); # same thing + $do = CPAN::Shell->expand("Distribution", + $distro); # same thing + +=head1 DESCRIPTION + +The CPAN module automates or at least simplifies the make and install +of perl modules and extensions. It includes some primitive searching +capabilities and knows how to use Net::FTP, LWP, and certain external +download clients to fetch distributions from the net. + +These are fetched from one or more mirrored CPAN (Comprehensive +Perl Archive Network) sites and unpacked in a dedicated directory. + +The CPAN module also supports named and versioned +I<bundles> of modules. Bundles simplify handling of sets of +related modules. See Bundles below. + +The package contains a session manager and a cache manager. The +session manager keeps track of what has been fetched, built, and +installed in the current session. The cache manager keeps track of the +disk space occupied by the make processes and deletes excess space +using a simple FIFO mechanism. + +All methods provided are accessible in a programmer style and in an +interactive shell style. + +=head2 CPAN::shell([$prompt, $command]) Starting Interactive Mode + +Enter interactive mode by running + + perl -MCPAN -e shell + +or + + cpan + +which puts you into a readline interface. If C<Term::ReadKey> and +either of C<Term::ReadLine::Perl> or C<Term::ReadLine::Gnu> are installed, +history and command completion are supported. + +Once at the command line, type C<h> for one-page help +screen; the rest should be self-explanatory. + +The function call C<shell> takes two optional arguments: one the +prompt, the second the default initial command line (the latter +only works if a real ReadLine interface module is installed). + +The most common uses of the interactive modes are + +=over 2 + +=item Searching for authors, bundles, distribution files and modules + +There are corresponding one-letter commands C<a>, C<b>, C<d>, and C<m> +for each of the four categories and another, C<i> for any of the +mentioned four. Each of the four entities is implemented as a class +with slightly differing methods for displaying an object. + +Arguments to these commands are either strings exactly matching +the identification string of an object, or regular expressions +matched case-insensitively against various attributes of the +objects. The parser only recognizes a regular expression when you +enclose it with slashes. + +The principle is that the number of objects found influences how an +item is displayed. If the search finds one item, the result is +displayed with the rather verbose method C<as_string>, but if +more than one is found, each object is displayed with the terse method +C<as_glimpse>. + +Examples: + + cpan> m Acme::MetaSyntactic + Module id = Acme::MetaSyntactic + CPAN_USERID BOOK (Philippe Bruhat (BooK) <[...]>) + CPAN_VERSION 0.99 + CPAN_FILE B/BO/BOOK/Acme-MetaSyntactic-0.99.tar.gz + UPLOAD_DATE 2006-11-06 + MANPAGE Acme::MetaSyntactic - Themed metasyntactic variables names + INST_FILE /usr/local/lib/perl/5.10.0/Acme/MetaSyntactic.pm + INST_VERSION 0.99 + cpan> a BOOK + Author id = BOOK + EMAIL [...] + FULLNAME Philippe Bruhat (BooK) + cpan> d BOOK/Acme-MetaSyntactic-0.99.tar.gz + Distribution id = B/BO/BOOK/Acme-MetaSyntactic-0.99.tar.gz + CPAN_USERID BOOK (Philippe Bruhat (BooK) <[...]>) + CONTAINSMODS Acme::MetaSyntactic Acme::MetaSyntactic::Alias [...] + UPLOAD_DATE 2006-11-06 + cpan> m /lorem/ + Module = Acme::MetaSyntactic::loremipsum (BOOK/Acme-MetaSyntactic-0.99.tar.gz) + Module Text::Lorem (ADEOLA/Text-Lorem-0.3.tar.gz) + Module Text::Lorem::More (RKRIMEN/Text-Lorem-More-0.12.tar.gz) + Module Text::Lorem::More::Source (RKRIMEN/Text-Lorem-More-0.12.tar.gz) + cpan> i /berlin/ + Distribution BEATNIK/Filter-NumberLines-0.02.tar.gz + Module = DateTime::TimeZone::Europe::Berlin (DROLSKY/DateTime-TimeZone-0.7904.tar.gz) + Module Filter::NumberLines (BEATNIK/Filter-NumberLines-0.02.tar.gz) + Author [...] + +The examples illustrate several aspects: the first three queries +target modules, authors, or distros directly and yield exactly one +result. The last two use regular expressions and yield several +results. The last one targets all of bundles, modules, authors, and +distros simultaneously. When more than one result is available, they +are printed in one-line format. + +=item C<get>, C<make>, C<test>, C<install>, C<clean> modules or distributions + +These commands take any number of arguments and investigate what is +necessary to perform the action. Argument processing is as follows: + + known module name in format Foo/Bar.pm module + other embedded slash distribution + - with trailing slash dot directory + enclosing slashes regexp + known module name in format Foo::Bar module + +If the argument is a distribution file name (recognized by embedded +slashes), it is processed. If it is a module, CPAN determines the +distribution file in which this module is included and processes that, +following any dependencies named in the module's META.yml or +Makefile.PL (this behavior is controlled by the configuration +parameter C<prerequisites_policy>). If an argument is enclosed in +slashes it is treated as a regular expression: it is expanded and if +the result is a single object (distribution, bundle or module), this +object is processed. + +Example: + + install Dummy::Perl # installs the module + install AUXXX/Dummy-Perl-3.14.tar.gz # installs that distribution + install /Dummy-Perl-3.14/ # same if the regexp is unambiguous + +C<get> downloads a distribution file and untars or unzips it, C<make> +builds it, C<test> runs the test suite, and C<install> installs it. + +Any C<make> or C<test> is run unconditionally. An + + install <distribution_file> + +is also run unconditionally. But for + + install <module> + +CPAN checks whether an install is needed and prints +I<module up to date> if the distribution file containing +the module doesn't need updating. + +CPAN also keeps track of what it has done within the current session +and doesn't try to build a package a second time regardless of whether it +succeeded or not. It does not repeat a test run if the test +has been run successfully before. Same for install runs. + +The C<force> pragma may precede another command (currently: C<get>, +C<make>, C<test>, or C<install>) to execute the command from scratch +and attempt to continue past certain errors. See the section below on +the C<force> and the C<fforce> pragma. + +The C<notest> pragma skips the test part in the build +process. + +Example: + + cpan> notest install Tk + +A C<clean> command results in a + + make clean + +being executed within the distribution file's working directory. + +=item C<readme>, C<perldoc>, C<look> module or distribution + +C<readme> displays the README file of the associated distribution. +C<Look> gets and untars (if not yet done) the distribution file, +changes to the appropriate directory and opens a subshell process in +that directory. C<perldoc> displays the module's pod documentation +in html or plain text format. + +=item C<ls> author + +=item C<ls> globbing_expression + +The first form lists all distribution files in and below an author's +CPAN directory as stored in the CHECKUMS files distributed on +CPAN. The listing recurses into subdirectories. + +The second form limits or expands the output with shell +globbing as in the following examples: + + ls JV/make* + ls GSAR/*make* + ls */*make* + +The last example is very slow and outputs extra progress indicators +that break the alignment of the result. + +Note that globbing only lists directories explicitly asked for, for +example FOO/* will not list FOO/bar/Acme-Sthg-n.nn.tar.gz. This may be +regarded as a bug that may be changed in some future version. + +=item C<failed> + +The C<failed> command reports all distributions that failed on one of +C<make>, C<test> or C<install> for some reason in the currently +running shell session. + +=item Persistence between sessions + +If the C<YAML> or the C<YAML::Syck> module is installed a record of +the internal state of all modules is written to disk after each step. +The files contain a signature of the currently running perl version +for later perusal. + +If the configurations variable C<build_dir_reuse> is set to a true +value, then CPAN.pm reads the collected YAML files. If the stored +signature matches the currently running perl, the stored state is +loaded into memory such that persistence between sessions +is effectively established. + +=item The C<force> and the C<fforce> pragma + +To speed things up in complex installation scenarios, CPAN.pm keeps +track of what it has already done and refuses to do some things a +second time. A C<get>, a C<make>, and an C<install> are not repeated. +A C<test> is repeated only if the previous test was unsuccessful. The +diagnostic message when CPAN.pm refuses to do something a second time +is one of I<Has already been >C<unwrapped|made|tested successfully> or +something similar. Another situation where CPAN refuses to act is an +C<install> if the corresponding C<test> was not successful. + +In all these cases, the user can override this stubborn behaviour by +prepending the command with the word force, for example: + + cpan> force get Foo + cpan> force make AUTHOR/Bar-3.14.tar.gz + cpan> force test Baz + cpan> force install Acme::Meta + +Each I<forced> command is executed with the corresponding part of its +memory erased. + +The C<fforce> pragma is a variant that emulates a C<force get> which +erases the entire memory followed by the action specified, effectively +restarting the whole get/make/test/install procedure from scratch. + +=item Lockfile + +Interactive sessions maintain a lockfile, by default C<~/.cpan/.lock>. +Batch jobs can run without a lockfile and not disturb each other. + +The shell offers to run in I<downgraded mode> when another process is +holding the lockfile. This is an experimental feature that is not yet +tested very well. This second shell then does not write the history +file, does not use the metadata file, and has a different prompt. + +=item Signals + +CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are +in the cpan-shell, it is intended that you can press C<^C> anytime and +return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell +to clean up and leave the shell loop. You can emulate the effect of a +SIGTERM by sending two consecutive SIGINTs, which usually means by +pressing C<^C> twice. + +CPAN.pm ignores SIGPIPE. If the user sets C<inactivity_timeout>, a +SIGALRM is used during the run of the C<perl Makefile.PL> or C<perl +Build.PL> subprocess. A SIGALRM is also used during module version +parsing, and is controlled by C<version_timeout>. + +=back + +=head2 CPAN::Shell + +The commands available in the shell interface are methods in +the package CPAN::Shell. If you enter the shell command, your +input is split by the Text::ParseWords::shellwords() routine, which +acts like most shells do. The first word is interpreted as the +method to be invoked, and the rest of the words are treated as the method's arguments. +Continuation lines are supported by ending a line with a +literal backslash. + +=head2 autobundle + +C<autobundle> writes a bundle file into the +C<$CPAN::Config-E<gt>{cpan_home}/Bundle> directory. The file contains +a list of all modules that are both available from CPAN and currently +installed within @INC. The name of the bundle file is based on the +current date and a counter. + +=head2 hosts + +Note: this feature is still in alpha state and may change in future +versions of CPAN.pm + +This commands provides a statistical overview over recent download +activities. The data for this is collected in the YAML file +C<FTPstats.yml> in your C<cpan_home> directory. If no YAML module is +configured or YAML not installed, no stats are provided. + +=head2 mkmyconfig + +mkmyconfig() writes your own CPAN::MyConfig file into your C<~/.cpan/> +directory so that you can save your own preferences instead of the +system-wide ones. + +=head2 recent ***EXPERIMENTAL COMMAND*** + +The C<recent> command downloads a list of recent uploads to CPAN and +displays them I<slowly>. While the command is running, a $SIG{INT} +exits the loop after displaying the current item. + +B<Note>: This command requires XML::LibXML installed. + +B<Note>: This whole command currently is just a hack and will +probably change in future versions of CPAN.pm, but the general +approach will likely remain. + +B<Note>: See also L<smoke> + +=head2 recompile + +recompile() is a special command that takes no argument and +runs the make/test/install cycle with brute force over all installed +dynamically loadable extensions (aka XS modules) with 'force' in +effect. The primary purpose of this command is to finish a network +installation. Imagine you have a common source tree for two different +architectures. You decide to do a completely independent fresh +installation. You start on one architecture with the help of a Bundle +file produced earlier. CPAN installs the whole Bundle for you, but +when you try to repeat the job on the second architecture, CPAN +responds with a C<"Foo up to date"> message for all modules. So you +invoke CPAN's recompile on the second architecture and you're done. + +Another popular use for C<recompile> is to act as a rescue in case your +perl breaks binary compatibility. If one of the modules that CPAN uses +is in turn depending on binary compatibility (so you cannot run CPAN +commands), then you should try the CPAN::Nox module for recovery. + +=head2 report Bundle|Distribution|Module + +The C<report> command temporarily turns on the C<test_report> config +variable, then runs the C<force test> command with the given +arguments. The C<force> pragma reruns the tests and repeats +every step that might have failed before. + +=head2 smoke ***EXPERIMENTAL COMMAND*** + +B<*** WARNING: this command downloads and executes software from CPAN to +your computer of completely unknown status. You should never do +this with your normal account and better have a dedicated well +separated and secured machine to do this. ***> + +The C<smoke> command takes the list of recent uploads to CPAN as +provided by the C<recent> command and tests them all. While the +command is running $SIG{INT} is defined to mean that the current item +shall be skipped. + +B<Note>: This whole command currently is just a hack and will +probably change in future versions of CPAN.pm, but the general +approach will likely remain. + +B<Note>: See also L<recent> + +=head2 upgrade [Module|/Regex/]... + +The C<upgrade> command first runs an C<r> command with the given +arguments and then installs the newest versions of all modules that +were listed by that. + +=head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution + +Although it may be considered internal, the class hierarchy does matter +for both users and programmer. CPAN.pm deals with the four +classes mentioned above, and those classes all share a set of methods. Classical +single polymorphism is in effect. A metaclass object registers all +objects of all kinds and indexes them with a string. The strings +referencing objects have a separated namespace (well, not completely +separated): + + Namespace Class + + words containing a "/" (slash) Distribution + words starting with Bundle:: Bundle + everything else Module or Author + +Modules know their associated Distribution objects. They always refer +to the most recent official release. Developers may mark their releases +as unstable development versions (by inserting an underbar into the +module version number which will also be reflected in the distribution +name when you run 'make dist'), so the really hottest and newest +distribution is not always the default. If a module Foo circulates +on CPAN in both version 1.23 and 1.23_90, CPAN.pm offers a convenient +way to install version 1.23 by saying + + install Foo + +This would install the complete distribution file (say +BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would +like to install version 1.23_90, you need to know where the +distribution file resides on CPAN relative to the authors/id/ +directory. If the author is BAR, this might be BAR/Foo-1.23_90.tar.gz; +so you would have to say + + install BAR/Foo-1.23_90.tar.gz + +The first example will be driven by an object of the class +CPAN::Module, the second by an object of class CPAN::Distribution. + +=head2 Integrating local directories + +Note: this feature is still in alpha state and may change in future +versions of CPAN.pm + +Distribution objects are normally distributions from the CPAN, but +there is a slightly degenerate case for Distribution objects, too, of +projects held on the local disk. These distribution objects have the +same name as the local directory and end with a dot. A dot by itself +is also allowed for the current directory at the time CPAN.pm was +used. All actions such as C<make>, C<test>, and C<install> are applied +directly to that directory. This gives the command C<cpan .> an +interesting touch: while the normal mantra of installing a CPAN module +without CPAN.pm is one of + + perl Makefile.PL perl Build.PL + ( go and get prerequisites ) + make ./Build + make test ./Build test + make install ./Build install + +the command C<cpan .> does all of this at once. It figures out which +of the two mantras is appropriate, fetches and installs all +prerequisites, takes care of them recursively, and finally finishes the +installation of the module in the current directory, be it a CPAN +module or not. + +The typical usage case is for private modules or working copies of +projects from remote repositories on the local disk. + +=head2 Redirection + +The usual shell redirection symbols C< | > and C<< > >> are recognized +by the cpan shell B<only when surrounded by whitespace>. So piping to +pager or redirecting output into a file works somewhat as in a normal +shell, with the stipulation that you must type extra spaces. + +=head1 CONFIGURATION + +When the CPAN module is used for the first time, a configuration +dialogue tries to determine a couple of site specific options. The +result of the dialog is stored in a hash reference C< $CPAN::Config > +in a file CPAN/Config.pm. + +Default values defined in the CPAN/Config.pm file can be +overridden in a user specific file: CPAN/MyConfig.pm. Such a file is +best placed in C<$HOME/.cpan/CPAN/MyConfig.pm>, because C<$HOME/.cpan> is +added to the search path of the CPAN module before the use() or +require() statements. The mkmyconfig command writes this file for you. + +The C<o conf> command has various bells and whistles: + +=over + +=item completion support + +If you have a ReadLine module installed, you can hit TAB at any point +of the commandline and C<o conf> will offer you completion for the +built-in subcommands and/or config variable names. + +=item displaying some help: o conf help + +Displays a short help + +=item displaying current values: o conf [KEY] + +Displays the current value(s) for this config variable. Without KEY, +displays all subcommands and config variables. + +Example: + + o conf shell + +If KEY starts and ends with a slash, the string in between is +treated as a regular expression and only keys matching this regex +are displayed + +Example: + + o conf /color/ + +=item changing of scalar values: o conf KEY VALUE + +Sets the config variable KEY to VALUE. The empty string can be +specified as usual in shells, with C<''> or C<""> + +Example: + + o conf wget /usr/bin/wget + +=item changing of list values: o conf KEY SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST + +If a config variable name ends with C<list>, it is a list. C<o conf +KEY shift> removes the first element of the list, C<o conf KEY pop> +removes the last element of the list. C<o conf KEYS unshift LIST> +prepends a list of values to the list, C<o conf KEYS push LIST> +appends a list of valued to the list. + +Likewise, C<o conf KEY splice LIST> passes the LIST to the corresponding +splice command. + +Finally, any other list of arguments is taken as a new list value for +the KEY variable discarding the previous value. + +Examples: + + o conf urllist unshift http://cpan.dev.local/CPAN + o conf urllist splice 3 1 + o conf urllist http://cpan1.local http://cpan2.local ftp://ftp.perl.org + +=item reverting to saved: o conf defaults + +Reverts all config variables to the state in the saved config file. + +=item saving the config: o conf commit + +Saves all config variables to the current config file (CPAN/Config.pm +or CPAN/MyConfig.pm that was loaded at start). + +=back + +The configuration dialog can be started any time later again by +issuing the command C< o conf init > in the CPAN shell. A subset of +the configuration dialog can be run by issuing C<o conf init WORD> +where WORD is any valid config variable or a regular expression. + +=head2 Config Variables + +The following keys in the hash reference $CPAN::Config are +currently defined: + + applypatch path to external prg + auto_commit commit all changes to config variables to disk + build_cache size of cache for directories to build modules + build_dir locally accessible directory to build modules + build_dir_reuse boolean if distros in build_dir are persistent + build_requires_install_policy + to install or not to install when a module is + only needed for building. yes|no|ask/yes|ask/no + bzip2 path to external prg + cache_metadata use serializer to cache metadata + check_sigs if signatures should be verified + colorize_debug Term::ANSIColor attributes for debugging output + colorize_output boolean if Term::ANSIColor should colorize output + colorize_print Term::ANSIColor attributes for normal output + colorize_warn Term::ANSIColor attributes for warnings + commandnumber_in_prompt + boolean if you want to see current command number + commands_quote preferred character to use for quoting external + commands when running them. Defaults to double + quote on Windows, single tick everywhere else; + can be set to space to disable quoting + connect_to_internet_ok + whether to ask if opening a connection is ok before + urllist is specified + cpan_home local directory reserved for this package + curl path to external prg + dontload_hash DEPRECATED + dontload_list arrayref: modules in the list will not be + loaded by the CPAN::has_inst() routine + ftp path to external prg + ftp_passive if set, the envariable FTP_PASSIVE is set for downloads + ftp_proxy proxy host for ftp requests + ftpstats_period max number of days to keep download statistics + ftpstats_size max number of items to keep in the download statistics + getcwd see below + gpg path to external prg + gzip location of external program gzip + halt_on_failure stop processing after the first failure of queued + items or dependencies + histfile file to maintain history between sessions + histsize maximum number of lines to keep in histfile + http_proxy proxy host for http requests + inactivity_timeout breaks interactive Makefile.PLs or Build.PLs + after this many seconds inactivity. Set to 0 to + disable timeouts. + index_expire refetch index files after this many days + inhibit_startup_message + if true, suppress the startup message + keep_source_where directory in which to keep the source (if we do) + load_module_verbosity + report loading of optional modules used by CPAN.pm + lynx path to external prg + make location of external make program + make_arg arguments that should always be passed to 'make' + make_install_make_command + the make command for running 'make install', for + example 'sudo make' + make_install_arg same as make_arg for 'make install' + makepl_arg arguments passed to 'perl Makefile.PL' + mbuild_arg arguments passed to './Build' + mbuild_install_arg arguments passed to './Build install' + mbuild_install_build_command + command to use instead of './Build' when we are + in the install stage, for example 'sudo ./Build' + mbuildpl_arg arguments passed to 'perl Build.PL' + ncftp path to external prg + ncftpget path to external prg + no_proxy don't proxy to these hosts/domains (comma separated list) + pager location of external program more (or any pager) + password your password if you CPAN server wants one + patch path to external prg + patches_dir local directory containing patch files + perl5lib_verbosity verbosity level for PERL5LIB additions + prefer_installer legal values are MB and EUMM: if a module comes + with both a Makefile.PL and a Build.PL, use the + former (EUMM) or the latter (MB); if the module + comes with only one of the two, that one will be + used no matter the setting + prerequisites_policy + what to do if you are missing module prerequisites + ('follow' automatically, 'ask' me, or 'ignore') + For 'follow', also sets PERL_AUTOINSTALL and + PERL_EXTUTILS_AUTOINSTALL for "--defaultdeps" if + not already set + prefs_dir local directory to store per-distro build options + proxy_user username for accessing an authenticating proxy + proxy_pass password for accessing an authenticating proxy + randomize_urllist add some randomness to the sequence of the urllist + scan_cache controls scanning of cache ('atstart' or 'never') + shell your favorite shell + show_unparsable_versions + boolean if r command tells which modules are versionless + show_upload_date boolean if commands should try to determine upload date + show_zero_versions boolean if r command tells for which modules $version==0 + tar location of external program tar + tar_verbosity verbosity level for the tar command + term_is_latin deprecated: if true Unicode is translated to ISO-8859-1 + (and nonsense for characters outside latin range) + term_ornaments boolean to turn ReadLine ornamenting on/off + test_report email test reports (if CPAN::Reporter is installed) + trust_test_report_history + skip testing when previously tested ok (according to + CPAN::Reporter history) + unzip location of external program unzip + urllist arrayref to nearby CPAN sites (or equivalent locations) + use_sqlite use CPAN::SQLite for metadata storage (fast and lean) + username your username if you CPAN server wants one + version_timeout stops version parsing after this many seconds. + Default is 15 secs. Set to 0 to disable. + wait_list arrayref to a wait server to try (See CPAN::WAIT) + wget path to external prg + yaml_load_code enable YAML code deserialisation via CPAN::DeferredCode + yaml_module which module to use to read/write YAML files + +You can set and query each of these options interactively in the cpan +shell with the C<o conf> or the C<o conf init> command as specified below. + +=over 2 + +=item C<o conf E<lt>scalar optionE<gt>> + +prints the current value of the I<scalar option> + +=item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>> + +Sets the value of the I<scalar option> to I<value> + +=item C<o conf E<lt>list optionE<gt>> + +prints the current value of the I<list option> in MakeMaker's +neatvalue format. + +=item C<o conf E<lt>list optionE<gt> [shift|pop]> + +shifts or pops the array in the I<list option> variable + +=item C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>> + +works like the corresponding perl commands. + +=item interactive editing: o conf init [MATCH|LIST] + +Runs an interactive configuration dialog for matching variables. +Without argument runs the dialog over all supported config variables. +To specify a MATCH the argument must be enclosed by slashes. + +Examples: + + o conf init ftp_passive ftp_proxy + o conf init /color/ + +Note: this method of setting config variables often provides more +explanation about the functioning of a variable than the manpage. + +=back + +=head2 CPAN::anycwd($path): Note on config variable getcwd + +CPAN.pm changes the current working directory often and needs to +determine its own current working directory. By default it uses +Cwd::cwd, but if for some reason this doesn't work on your system, +configure alternatives according to the following table: + +=over 4 + +=item cwd + +Calls Cwd::cwd + +=item getcwd + +Calls Cwd::getcwd + +=item fastcwd + +Calls Cwd::fastcwd + +=item backtickcwd + +Calls the external command cwd. + +=back + +=head2 Note on the format of the urllist parameter + +urllist parameters are URLs according to RFC 1738. We do a little +guessing if your URL is not compliant, but if you have problems with +C<file> URLs, please try the correct format. Either: + + file://localhost/whatever/ftp/pub/CPAN/ + +or + + file:///home/ftp/pub/CPAN/ + +=head2 The urllist parameter has CD-ROM support + +The C<urllist> parameter of the configuration table contains a list of +URLs used for downloading. If the list contains any +C<file> URLs, CPAN always tries there first. This +feature is disabled for index files. So the recommendation for the +owner of a CD-ROM with CPAN contents is: include your local, possibly +outdated CD-ROM as a C<file> URL at the end of urllist, e.g. + + o conf urllist push file://localhost/CDROM/CPAN + +CPAN.pm will then fetch the index files from one of the CPAN sites +that come at the beginning of urllist. It will later check for each +module to see whether there is a local copy of the most recent version. + +Another peculiarity of urllist is that the site that we could +successfully fetch the last file from automatically gets a preference +token and is tried as the first site for the next request. So if you +add a new site at runtime it may happen that the previously preferred +site will be tried another time. This means that if you want to disallow +a site for the next transfer, it must be explicitly removed from +urllist. + +=head2 Maintaining the urllist parameter + +If you have YAML.pm (or some other YAML module configured in +C<yaml_module>) installed, CPAN.pm collects a few statistical data +about recent downloads. You can view the statistics with the C<hosts> +command or inspect them directly by looking into the C<FTPstats.yml> +file in your C<cpan_home> directory. + +To get some interesting statistics, it is recommended that +C<randomize_urllist> be set; this introduces some amount of +randomness into the URL selection. + +=head2 The C<requires> and C<build_requires> dependency declarations + +Since CPAN.pm version 1.88_51 modules declared as C<build_requires> by +a distribution are treated differently depending on the config +variable C<build_requires_install_policy>. By setting +C<build_requires_install_policy> to C<no>, such a module is not +installed. It is only built and tested, and then kept in the list of +tested but uninstalled modules. As such, it is available during the +build of the dependent module by integrating the path to the +C<blib/arch> and C<blib/lib> directories in the environment variable +PERL5LIB. If C<build_requires_install_policy> is set ti C<yes>, then +both modules declared as C<requires> and those declared as +C<build_requires> are treated alike. By setting to C<ask/yes> or +C<ask/no>, CPAN.pm asks the user and sets the default accordingly. + +=head2 Configuration for individual distributions (I<Distroprefs>) + +(B<Note:> This feature has been introduced in CPAN.pm 1.8854 and is +still considered beta quality) + +Distributions on CPAN usually behave according to what we call the +CPAN mantra. Or since the advent of Module::Build we should talk about +two mantras: + + perl Makefile.PL perl Build.PL + make ./Build + make test ./Build test + make install ./Build install + +But some modules cannot be built with this mantra. They try to get +some extra data from the user via the environment, extra arguments, or +interactively--thus disturbing the installation of large bundles like +Phalanx100 or modules with many dependencies like Plagger. + +The distroprefs system of C<CPAN.pm> addresses this problem by +allowing the user to specify extra informations and recipes in YAML +files to either + +=over + +=item + +pass additional arguments to one of the four commands, + +=item + +set environment variables + +=item + +instantiate an Expect object that reads from the console, waits for +some regular expressions and enters some answers + +=item + +temporarily override assorted C<CPAN.pm> configuration variables + +=item + +specify dependencies the original maintainer forgot + +=item + +disable the installation of an object altogether + +=back + +See the YAML and Data::Dumper files that come with the C<CPAN.pm> +distribution in the C<distroprefs/> directory for examples. + +=head2 Filenames + +The YAML files themselves must have the C<.yml> extension; all other +files are ignored (for two exceptions see I<Fallback Data::Dumper and +Storable> below). The containing directory can be specified in +C<CPAN.pm> in the C<prefs_dir> config variable. Try C<o conf init +prefs_dir> in the CPAN shell to set and activate the distroprefs +system. + +Every YAML file may contain arbitrary documents according to the YAML +specification, and every document is treated as an entity that +can specify the treatment of a single distribution. + +Filenames can be picked arbitrarily; C<CPAN.pm> always reads +all files (in alphabetical order) and takes the key C<match> (see +below in I<Language Specs>) as a hashref containing match criteria +that determine if the current distribution matches the YAML document +or not. + +=head2 Fallback Data::Dumper and Storable + +If neither your configured C<yaml_module> nor YAML.pm is installed, +CPAN.pm falls back to using Data::Dumper and Storable and looks for +files with the extensions C<.dd> or C<.st> in the C<prefs_dir> +directory. These files are expected to contain one or more hashrefs. +For Data::Dumper generated files, this is expected to be done with by +defining C<$VAR1>, C<$VAR2>, etc. The YAML shell would produce these +with the command + + ysh < somefile.yml > somefile.dd + +For Storable files the rule is that they must be constructed such that +C<Storable::retrieve(file)> returns an array reference and the array +elements represent one distropref object each. The conversion from +YAML would look like so: + + perl -MYAML=LoadFile -MStorable=nstore -e ' + @y=LoadFile(shift); + nstore(\@y, shift)' somefile.yml somefile.st + +In bootstrapping situations it is usually sufficient to translate only +a few YAML files to Data::Dumper for crucial modules like +C<YAML::Syck>, C<YAML.pm> and C<Expect.pm>. If you prefer Storable +over Data::Dumper, remember to pull out a Storable version that writes +an older format than all the other Storable versions that will need to +read them. + +=head2 Blueprint + +The following example contains all supported keywords and structures +with the exception of C<eexpect> which can be used instead of +C<expect>. + + --- + comment: "Demo" + match: + module: "Dancing::Queen" + distribution: "^CHACHACHA/Dancing-" + not_distribution: "\.zip$" + perl: "/usr/local/cariba-perl/bin/perl" + perlconfig: + archname: "freebsd" + not_cc: "gcc" + env: + DANCING_FLOOR: "Shubiduh" + disabled: 1 + cpanconfig: + make: gmake + pl: + args: + - "--somearg=specialcase" + + env: {} + + expect: + - "Which is your favorite fruit" + - "apple\n" + + make: + args: + - all + - extra-all + + env: {} + + expect: [] + + commandline: "echo SKIPPING make" + + test: + args: [] + + env: {} + + expect: [] + + install: + args: [] + + env: + WANT_TO_INSTALL: YES + + expect: + - "Do you really want to install" + - "y\n" + + patches: + - "ABCDE/Fedcba-3.14-ABCDE-01.patch" + + depends: + configure_requires: + LWP: 5.8 + build_requires: + Test::Exception: 0.25 + requires: + Spiffy: 0.30 + + +=head2 Language Specs + +Every YAML document represents a single hash reference. The valid keys +in this hash are as follows: + +=over + +=item comment [scalar] + +A comment + +=item cpanconfig [hash] + +Temporarily override assorted C<CPAN.pm> configuration variables. + +Supported are: C<build_requires_install_policy>, C<check_sigs>, +C<make>, C<make_install_make_command>, C<prefer_installer>, +C<test_report>. Please report as a bug when you need another one +supported. + +=item depends [hash] *** EXPERIMENTAL FEATURE *** + +All three types, namely C<configure_requires>, C<build_requires>, and +C<requires> are supported in the way specified in the META.yml +specification. The current implementation I<merges> the specified +dependencies with those declared by the package maintainer. In a +future implementation this may be changed to override the original +declaration. + +=item disabled [boolean] + +Specifies that this distribution shall not be processed at all. + +=item features [array] *** EXPERIMENTAL FEATURE *** + +Experimental implementation to deal with optional_features from +META.yml. Still needs coordination with installer software and +currently works only for META.yml declaring C<dynamic_config=0>. Use +with caution. + +=item goto [string] + +The canonical name of a delegate distribution to install +instead. Useful when a new version, although it tests OK itself, +breaks something else or a developer release or a fork is already +uploaded that is better than the last released version. + +=item install [hash] + +Processing instructions for the C<make install> or C<./Build install> +phase of the CPAN mantra. See below under I<Processing Instructions>. + +=item make [hash] + +Processing instructions for the C<make> or C<./Build> phase of the +CPAN mantra. See below under I<Processing Instructions>. + +=item match [hash] + +A hashref with one or more of the keys C<distribution>, C<modules>, +C<perl>, C<perlconfig>, and C<env> that specify whether a document is +targeted at a specific CPAN distribution or installation. +Keys prefixed with C<not_> negates the corresponding match. + +The corresponding values are interpreted as regular expressions. The +C<distribution> related one will be matched against the canonical +distribution name, e.g. "AUTHOR/Foo-Bar-3.14.tar.gz". + +The C<module> related one will be matched against I<all> modules +contained in the distribution until one module matches. + +The C<perl> related one will be matched against C<$^X> (but with the +absolute path). + +The value associated with C<perlconfig> is itself a hashref that is +matched against corresponding values in the C<%Config::Config> hash +living in the C<Config.pm> module. +Keys prefixed with C<not_> negates the corresponding match. + +The value associated with C<env> is itself a hashref that is +matched against corresponding values in the C<%ENV> hash. +Keys prefixed with C<not_> negates the corresponding match. + +If more than one restriction of C<module>, C<distribution>, etc. is +specified, the results of the separately computed match values must +all match. If so, the hashref represented by the +YAML document is returned as the preference structure for the current +distribution. + +=item patches [array] + +An array of patches on CPAN or on the local disk to be applied in +order via an external patch program. If the value for the C<-p> +parameter is C<0> or C<1> is determined by reading the patch +beforehand. The path to each patch is either an absolute path on the +local filesystem or relative to a patch directory specified in the +C<patches_dir> configuration variable or in the format of a canonical +distroname. For examples please consult the distroprefs/ directory in +the CPAN.pm distribution (these examples are not installed by +default). + +Note: if the C<applypatch> program is installed and C<CPAN::Config> +knows about it B<and> a patch is written by the C<makepatch> program, +then C<CPAN.pm> lets C<applypatch> apply the patch. Both C<makepatch> +and C<applypatch> are available from CPAN in the C<JV/makepatch-*> +distribution. + +=item pl [hash] + +Processing instructions for the C<perl Makefile.PL> or C<perl +Build.PL> phase of the CPAN mantra. See below under I<Processing +Instructions>. + +=item test [hash] + +Processing instructions for the C<make test> or C<./Build test> phase +of the CPAN mantra. See below under I<Processing Instructions>. + +=back + +=head2 Processing Instructions + +=over + +=item args [array] + +Arguments to be added to the command line + +=item commandline + +A full commandline to run via C<system()>. +During execution, the environment variable PERL is set +to $^X (but with an absolute path). If C<commandline> is specified, +C<args> is not used. + +=item eexpect [hash] + +Extended C<expect>. This is a hash reference with four allowed keys, +C<mode>, C<timeout>, C<reuse>, and C<talk>. + +You must install the C<Expect> module to use C<eexpect>. CPAN.pm +does not install it for you. + +C<mode> may have the values C<deterministic> for the case where all +questions come in the order written down and C<anyorder> for the case +where the questions may come in any order. The default mode is +C<deterministic>. + +C<timeout> denotes a timeout in seconds. Floating-point timeouts are +OK. With C<mode=deterministic>, the timeout denotes the +timeout per question; with C<mode=anyorder> it denotes the +timeout per byte received from the stream or questions. + +C<talk> is a reference to an array that contains alternating questions +and answers. Questions are regular expressions and answers are literal +strings. The Expect module watches the stream from the +execution of the external program (C<perl Makefile.PL>, C<perl +Build.PL>, C<make>, etc.). + +For C<mode=deterministic>, the CPAN.pm injects the +corresponding answer as soon as the stream matches the regular expression. + +For C<mode=anyorder> CPAN.pm answers a question as soon +as the timeout is reached for the next byte in the input stream. In +this mode you can use the C<reuse> parameter to decide what will +happen with a question-answer pair after it has been used. In the +default case (reuse=0) it is removed from the array, avoiding being +used again accidentally. If you want to answer the +question C<Do you really want to do that> several times, then it must +be included in the array at least as often as you want this answer to +be given. Setting the parameter C<reuse> to 1 makes this repetition +unnecessary. + +=item env [hash] + +Environment variables to be set during the command + +=item expect [array] + +You must install the C<Expect> module to use C<expect>. CPAN.pm +does not install it for you. + +C<< expect: <array> >> is a short notation for this C<eexpect>: + + eexpect: + mode: deterministic + timeout: 15 + talk: <array> + +=back + +=head2 Schema verification with C<Kwalify> + +If you have the C<Kwalify> module installed (which is part of the +Bundle::CPANxxl), then all your distroprefs files are checked for +syntactic correctness. + +=head2 Example Distroprefs Files + +C<CPAN.pm> comes with a collection of example YAML files. Note that these +are really just examples and should not be used without care because +they cannot fit everybody's purpose. After all, the authors of the +packages that ask questions had a need to ask, so you should watch +their questions and adjust the examples to your environment and your +needs. You have been warned:-) + +=head1 PROGRAMMER'S INTERFACE + +If you do not enter the shell, shell commands are +available both as methods (C<CPAN::Shell-E<gt>install(...)>) and as +functions in the calling package (C<install(...)>). Before calling low-level +commands, it makes sense to initialize components of CPAN you need, e.g.: + + CPAN::HandleConfig->load; + CPAN::Shell::setup_output; + CPAN::Index->reload; + +High-level commands do such initializations automatically. + +There's currently only one class that has a stable interface - +CPAN::Shell. All commands that are available in the CPAN shell are +methods of the class CPAN::Shell. Each of the commands that produce +listings of modules (C<r>, C<autobundle>, C<u>) also return a list of +the IDs of all modules within the list. + +=over 2 + +=item expand($type,@things) + +The IDs of all objects available within a program are strings that can +be expanded to the corresponding real objects with the +C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a +list of CPAN::Module objects according to the C<@things> arguments +given. In scalar context, it returns only the first element of the +list. + +=item expandany(@things) + +Like expand, but returns objects of the appropriate type, i.e. +CPAN::Bundle objects for bundles, CPAN::Module objects for modules, and +CPAN::Distribution objects for distributions. Note: it does not expand +to CPAN::Author objects. + +=item Programming Examples + +This enables the programmer to do operations that combine +functionalities that are available in the shell. + + # install everything that is outdated on my disk: + perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)' + + # install my favorite programs if necessary: + for $mod (qw(Net::FTP Digest::SHA Data::Dumper)) { + CPAN::Shell->install($mod); + } + + # list all modules on my disk that have no VERSION number + for $mod (CPAN::Shell->expand("Module","/./")) { + next unless $mod->inst_file; + # MakeMaker convention for undefined $VERSION: + next unless $mod->inst_version eq "undef"; + print "No VERSION in ", $mod->id, "\n"; + } + + # find out which distribution on CPAN contains a module: + print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file + +Or if you want to schedule a I<cron> job to watch CPAN, you could list +all modules that need updating. First a quick and dirty way: + + perl -e 'use CPAN; CPAN::Shell->r;' + +If you don't want any output should all modules be +up to date, parse the output of above command for the regular +expression C</modules are up to date/> and decide to mail the output +only if it doesn't match. + +If you prefer to do it more in a programmerish style in one single +process, something like this may better suit you: + + # list all modules on my disk that have newer versions on CPAN + for $mod (CPAN::Shell->expand("Module","/./")) { + next unless $mod->inst_file; + next if $mod->uptodate; + printf "Module %s is installed as %s, could be updated to %s from CPAN\n", + $mod->id, $mod->inst_version, $mod->cpan_version; + } + +If that gives too much output every day, you may want to +watch only for three modules. You can write + + for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")) { + +as the first line instead. Or you can combine some of the above +tricks: + + # watch only for a new mod_perl module + $mod = CPAN::Shell->expand("Module","mod_perl"); + exit if $mod->uptodate; + # new mod_perl arrived, let me know all update recommendations + CPAN::Shell->r; + +=back + +=head2 Methods in the other Classes + +=over 4 + +=item CPAN::Author::as_glimpse() + +Returns a one-line description of the author + +=item CPAN::Author::as_string() + +Returns a multi-line description of the author + +=item CPAN::Author::email() + +Returns the author's email address + +=item CPAN::Author::fullname() + +Returns the author's name + +=item CPAN::Author::name() + +An alias for fullname + +=item CPAN::Bundle::as_glimpse() + +Returns a one-line description of the bundle + +=item CPAN::Bundle::as_string() + +Returns a multi-line description of the bundle + +=item CPAN::Bundle::clean() + +Recursively runs the C<clean> method on all items contained in the bundle. + +=item CPAN::Bundle::contains() + +Returns a list of objects' IDs contained in a bundle. The associated +objects may be bundles, modules or distributions. + +=item CPAN::Bundle::force($method,@args) + +Forces CPAN to perform a task that it normally would have refused to +do. Force takes as arguments a method name to be called and any number +of additional arguments that should be passed to the called method. +The internals of the object get the needed changes so that CPAN.pm +does not refuse to take the action. The C<force> is passed recursively +to all contained objects. See also the section above on the C<force> +and the C<fforce> pragma. + +=item CPAN::Bundle::get() + +Recursively runs the C<get> method on all items contained in the bundle + +=item CPAN::Bundle::inst_file() + +Returns the highest installed version of the bundle in either @INC or +C<< $CPAN::Config->{cpan_home} >>. Note that this is different from +CPAN::Module::inst_file. + +=item CPAN::Bundle::inst_version() + +Like CPAN::Bundle::inst_file, but returns the $VERSION + +=item CPAN::Bundle::uptodate() + +Returns 1 if the bundle itself and all its members are uptodate. + +=item CPAN::Bundle::install() + +Recursively runs the C<install> method on all items contained in the bundle + +=item CPAN::Bundle::make() + +Recursively runs the C<make> method on all items contained in the bundle + +=item CPAN::Bundle::readme() + +Recursively runs the C<readme> method on all items contained in the bundle + +=item CPAN::Bundle::test() + +Recursively runs the C<test> method on all items contained in the bundle + +=item CPAN::Distribution::as_glimpse() + +Returns a one-line description of the distribution + +=item CPAN::Distribution::as_string() + +Returns a multi-line description of the distribution + +=item CPAN::Distribution::author + +Returns the CPAN::Author object of the maintainer who uploaded this +distribution + +=item CPAN::Distribution::pretty_id() + +Returns a string of the form "AUTHORID/TARBALL", where AUTHORID is the +author's PAUSE ID and TARBALL is the distribution filename. + +=item CPAN::Distribution::base_id() + +Returns the distribution filename without any archive suffix. E.g +"Foo-Bar-0.01" + +=item CPAN::Distribution::clean() + +Changes to the directory where the distribution has been unpacked and +runs C<make clean> there. + +=item CPAN::Distribution::containsmods() + +Returns a list of IDs of modules contained in a distribution file. +Works only for distributions listed in the 02packages.details.txt.gz +file. This typically means that just most recent version of a +distribution is covered. + +=item CPAN::Distribution::cvs_import() + +Changes to the directory where the distribution has been unpacked and +runs something like + + cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version + +there. + +=item CPAN::Distribution::dir() + +Returns the directory into which this distribution has been unpacked. + +=item CPAN::Distribution::force($method,@args) + +Forces CPAN to perform a task that it normally would have refused to +do. Force takes as arguments a method name to be called and any number +of additional arguments that should be passed to the called method. +The internals of the object get the needed changes so that CPAN.pm +does not refuse to take the action. See also the section above on the +C<force> and the C<fforce> pragma. + +=item CPAN::Distribution::get() + +Downloads the distribution from CPAN and unpacks it. Does nothing if +the distribution has already been downloaded and unpacked within the +current session. + +=item CPAN::Distribution::install() + +Changes to the directory where the distribution has been unpacked and +runs the external command C<make install> there. If C<make> has not +yet been run, it will be run first. A C<make test> is issued in +any case and if this fails, the install is cancelled. The +cancellation can be avoided by letting C<force> run the C<install> for +you. + +This install method only has the power to install the distribution if +there are no dependencies in the way. To install an object along with all +its dependencies, use CPAN::Shell->install. + +Note that install() gives no meaningful return value. See uptodate(). + +=item CPAN::Distribution::install_tested() + +Install all distributions that have tested sucessfully but +not yet installed. See also C<is_tested>. + +=item CPAN::Distribution::isa_perl() + +Returns 1 if this distribution file seems to be a perl distribution. +Normally this is derived from the file name only, but the index from +CPAN can contain a hint to achieve a return value of true for other +filenames too. + +=item CPAN::Distribution::look() + +Changes to the directory where the distribution has been unpacked and +opens a subshell there. Exiting the subshell returns. + +=item CPAN::Distribution::make() + +First runs the C<get> method to make sure the distribution is +downloaded and unpacked. Changes to the directory where the +distribution has been unpacked and runs the external commands C<perl +Makefile.PL> or C<perl Build.PL> and C<make> there. + +=item CPAN::Distribution::perldoc() + +Downloads the pod documentation of the file associated with a +distribution (in HTML format) and runs it through the external +command I<lynx> specified in C<< $CPAN::Config->{lynx} >>. If I<lynx> +isn't available, it converts it to plain text with the external +command I<html2text> and runs it through the pager specified +in C<< $CPAN::Config->{pager} >>. + +=item CPAN::Distribution::prefs() + +Returns the hash reference from the first matching YAML file that the +user has deposited in the C<prefs_dir/> directory. The first +succeeding match wins. The files in the C<prefs_dir/> are processed +alphabetically, and the canonical distroname (e.g. +AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions +stored in the $root->{match}{distribution} attribute value. +Additionally all module names contained in a distribution are matched +against the regular expressions in the $root->{match}{module} attribute +value. The two match values are ANDed together. Each of the two +attributes are optional. + +=item CPAN::Distribution::prereq_pm() + +Returns the hash reference that has been announced by a distribution +as the C<requires> and C<build_requires> elements. These can be +declared either by the C<META.yml> (if authoritative) or can be +deposited after the run of C<Build.PL> in the file C<./_build/prereqs> +or after the run of C<Makfile.PL> written as the C<PREREQ_PM> hash in +a comment in the produced C<Makefile>. I<Note>: this method only works +after an attempt has been made to C<make> the distribution. Returns +undef otherwise. + +=item CPAN::Distribution::readme() + +Downloads the README file associated with a distribution and runs it +through the pager specified in C<< $CPAN::Config->{pager} >>. + +=item CPAN::Distribution::reports() + +Downloads report data for this distribution from www.cpantesters.org +and displays a subset of them. + +=item CPAN::Distribution::read_yaml() + +Returns the content of the META.yml of this distro as a hashref. Note: +works only after an attempt has been made to C<make> the distribution. +Returns undef otherwise. Also returns undef if the content of META.yml +is not authoritative. (The rules about what exactly makes the content +authoritative are still in flux.) + +=item CPAN::Distribution::test() + +Changes to the directory where the distribution has been unpacked and +runs C<make test> there. + +=item CPAN::Distribution::uptodate() + +Returns 1 if all the modules contained in the distribution are +uptodate. Relies on containsmods. + +=item CPAN::Index::force_reload() + +Forces a reload of all indices. + +=item CPAN::Index::reload() + +Reloads all indices if they have not been read for more than +C<< $CPAN::Config->{index_expire} >> days. + +=item CPAN::InfoObj::dump() + +CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution +inherit this method. It prints the data structure associated with an +object. Useful for debugging. Note: the data structure is considered +internal and thus subject to change without notice. + +=item CPAN::Module::as_glimpse() + +Returns a one-line description of the module in four columns: The +first column contains the word C<Module>, the second column consists +of one character: an equals sign if this module is already installed +and uptodate, a less-than sign if this module is installed but can be +upgraded, and a space if the module is not installed. The third column +is the name of the module and the fourth column gives maintainer or +distribution information. + +=item CPAN::Module::as_string() + +Returns a multi-line description of the module + +=item CPAN::Module::clean() + +Runs a clean on the distribution associated with this module. + +=item CPAN::Module::cpan_file() + +Returns the filename on CPAN that is associated with the module. + +=item CPAN::Module::cpan_version() + +Returns the latest version of this module available on CPAN. + +=item CPAN::Module::cvs_import() + +Runs a cvs_import on the distribution associated with this module. + +=item CPAN::Module::description() + +Returns a 44 character description of this module. Only available for +modules listed in The Module List (CPAN/modules/00modlist.long.html +or 00modlist.long.txt.gz) + +=item CPAN::Module::distribution() + +Returns the CPAN::Distribution object that contains the current +version of this module. + +=item CPAN::Module::dslip_status() + +Returns a hash reference. The keys of the hash are the letters C<D>, +C<S>, C<L>, C<I>, and <P>, for development status, support level, +language, interface and public licence respectively. The data for the +DSLIP status are collected by pause.perl.org when authors register +their namespaces. The values of the 5 hash elements are one-character +words whose meaning is described in the table below. There are also 5 +hash elements C<DV>, C<SV>, C<LV>, C<IV>, and <PV> that carry a more +verbose value of the 5 status variables. + +Where the 'DSLIP' characters have the following meanings: + + D - Development Stage (Note: *NO IMPLIED TIMESCALES*): + i - Idea, listed to gain consensus or as a placeholder + c - under construction but pre-alpha (not yet released) + a/b - Alpha/Beta testing + R - Released + M - Mature (no rigorous definition) + S - Standard, supplied with Perl 5 + + S - Support Level: + m - Mailing-list + d - Developer + u - Usenet newsgroup comp.lang.perl.modules + n - None known, try comp.lang.perl.modules + a - abandoned; volunteers welcome to take over maintainance + + L - Language Used: + p - Perl-only, no compiler needed, should be platform independent + c - C and perl, a C compiler will be needed + h - Hybrid, written in perl with optional C code, no compiler needed + + - C++ and perl, a C++ compiler will be needed + o - perl and another language other than C or C++ + + I - Interface Style + f - plain Functions, no references used + h - hybrid, object and function interfaces available + n - no interface at all (huh?) + r - some use of unblessed References or ties + O - Object oriented using blessed references and/or inheritance + + P - Public License + p - Standard-Perl: user may choose between GPL and Artistic + g - GPL: GNU General Public License + l - LGPL: "GNU Lesser General Public License" (previously known as + "GNU Library General Public License") + b - BSD: The BSD License + a - Artistic license alone + 2 - Artistic license 2.0 or later + o - open source: appoved by www.opensource.org + d - allows distribution without restrictions + r - restricted distribtion + n - no license at all + +=item CPAN::Module::force($method,@args) + +Forces CPAN to perform a task it would normally refuse to +do. Force takes as arguments a method name to be invoked and any number +of additional arguments to pass that method. +The internals of the object get the needed changes so that CPAN.pm +does not refuse to take the action. See also the section above on the +C<force> and the C<fforce> pragma. + +=item CPAN::Module::get() + +Runs a get on the distribution associated with this module. + +=item CPAN::Module::inst_file() + +Returns the filename of the module found in @INC. The first file found +is reported, just as perl itself stops searching @INC once it finds a +module. + +=item CPAN::Module::available_file() + +Returns the filename of the module found in PERL5LIB or @INC. The +first file found is reported. The advantage of this method over +C<inst_file> is that modules that have been tested but not yet +installed are included because PERL5LIB keeps track of tested modules. + +=item CPAN::Module::inst_version() + +Returns the version number of the installed module in readable format. + +=item CPAN::Module::available_version() + +Returns the version number of the available module in readable format. + +=item CPAN::Module::install() + +Runs an C<install> on the distribution associated with this module. + +=item CPAN::Module::look() + +Changes to the directory where the distribution associated with this +module has been unpacked and opens a subshell there. Exiting the +subshell returns. + +=item CPAN::Module::make() + +Runs a C<make> on the distribution associated with this module. + +=item CPAN::Module::manpage_headline() + +If module is installed, peeks into the module's manpage, reads the +headline, and returns it. Moreover, if the module has been downloaded +within this session, does the equivalent on the downloaded module even +if it hasn't been installed yet. + +=item CPAN::Module::perldoc() + +Runs a C<perldoc> on this module. + +=item CPAN::Module::readme() + +Runs a C<readme> on the distribution associated with this module. + +=item CPAN::Module::reports() + +Calls the reports() method on the associated distribution object. + +=item CPAN::Module::test() + +Runs a C<test> on the distribution associated with this module. + +=item CPAN::Module::uptodate() + +Returns 1 if the module is installed and up-to-date. + +=item CPAN::Module::userid() + +Returns the author's ID of the module. + +=back + +=head2 Cache Manager + +Currently the cache manager only keeps track of the build directory +($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that +deletes complete directories below C<build_dir> as soon as the size of +all directories there gets bigger than $CPAN::Config->{build_cache} +(in MB). The contents of this cache may be used for later +re-installations that you intend to do manually, but will never be +trusted by CPAN itself. This is due to the fact that the user might +use these directories for building modules on different architectures. + +There is another directory ($CPAN::Config->{keep_source_where}) where +the original distribution files are kept. This directory is not +covered by the cache manager and must be controlled by the user. If +you choose to have the same directory as build_dir and as +keep_source_where directory, then your sources will be deleted with +the same fifo mechanism. + +=head2 Bundles + +A bundle is just a perl module in the namespace Bundle:: that does not +define any functions or methods. It usually only contains documentation. + +It starts like a perl module with a package declaration and a $VERSION +variable. After that the pod section looks like any other pod with the +only difference being that I<one special pod section> exists starting with +(verbatim): + + =head1 CONTENTS + +In this pod section each line obeys the format + + Module_Name [Version_String] [- optional text] + +The only required part is the first field, the name of a module +(e.g. Foo::Bar, ie. I<not> the name of the distribution file). The rest +of the line is optional. The comment part is delimited by a dash just +as in the man page header. + +The distribution of a bundle should follow the same convention as +other distributions. + +Bundles are treated specially in the CPAN package. If you say 'install +Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all +the modules in the CONTENTS section of the pod. You can install your +own Bundles locally by placing a conformant Bundle file somewhere into +your @INC path. The autobundle() command which is available in the +shell interface does that for you by including all currently installed +modules in a snapshot bundle file. + +=head1 PREREQUISITES + +The CPAN program is trying to depend on as little as possible so the +user can use it in hostile enviroment. It works better the more goodies +the environment provides. For example if you try in the CPAN shell + + install Bundle::CPAN + +or + + install Bundle::CPANxxl + +you will find the shell more convenient than the bare shell before. + +If you have a local mirror of CPAN and can access all files with +"file:" URLs, then you only need a perl later than perl5.003 to run +this module. Otherwise Net::FTP is strongly recommended. LWP may be +required for non-UNIX systems, or if your nearest CPAN site is +associated with a URL that is not C<ftp:>. + +If you have neither Net::FTP nor LWP, there is a fallback mechanism +implemented for an external ftp command or for an external lynx +command. + +=head1 UTILITIES + +=head2 Finding packages and VERSION + +This module presumes that all packages on CPAN + +=over 2 + +=item * + +declare their $VERSION variable in an easy to parse manner. This +prerequisite can hardly be relaxed because it consumes far too much +memory to load all packages into the running program just to determine +the $VERSION variable. Currently all programs that are dealing with +version use something like this + + perl -MExtUtils::MakeMaker -le \ + 'print MM->parse_version(shift)' filename + +If you are author of a package and wonder if your $VERSION can be +parsed, please try the above method. + +=item * + +come as compressed or gzipped tarfiles or as zip files and contain a +C<Makefile.PL> or C<Build.PL> (well, we try to handle a bit more, but +with little enthusiasm). + +=back + +=head2 Debugging + +Debugging this module is more than a bit complex due to interference from +the software producing the indices on CPAN, the mirroring process on CPAN, +packaging, configuration, synchronicity, and even (gasp!) due to bugs +within the CPAN.pm module itself. + +For debugging the code of CPAN.pm itself in interactive mode, some +debugging aid can be turned on for most packages within +CPAN.pm with one of + +=over 2 + +=item o debug package... + +sets debug mode for packages. + +=item o debug -package... + +unsets debug mode for packages. + +=item o debug all + +turns debugging on for all packages. + +=item o debug number + +=back + +which sets the debugging packages directly. Note that C<o debug 0> +turns debugging off. + +What seems a successful strategy is the combination of C<reload +cpan> and the debugging switches. Add a new debug statement while +running in the shell and then issue a C<reload cpan> and see the new +debugging messages immediately without losing the current context. + +C<o debug> without an argument lists the valid package names and the +current set of packages in debugging mode. C<o debug> has built-in +completion support. + +For debugging of CPAN data there is the C<dump> command which takes +the same arguments as make/test/install and outputs each object's +Data::Dumper dump. If an argument looks like a perl variable and +contains one of C<$>, C<@> or C<%>, it is eval()ed and fed to +Data::Dumper directly. + +=head2 Floppy, Zip, Offline Mode + +CPAN.pm works nicely without network access, too. If you maintain machines +that are not networked at all, you should consider working with C<file:> +URLs. You'll have to collect your modules somewhere first. So +you might use CPAN.pm to put together all you need on a networked +machine. Then copy the $CPAN::Config->{keep_source_where} (but not +$CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind +of a personal CPAN. CPAN.pm on the non-networked machines works nicely +with this floppy. See also below the paragraph about CD-ROM support. + +=head2 Basic Utilities for Programmers + +=over 2 + +=item has_inst($module) + +Returns true if the module is installed. Used to load all modules into +the running CPAN.pm that are considered optional. The config variable +C<dontload_list> intercepts the C<has_inst()> call such +that an optional module is not loaded despite being available. For +example, the following command will prevent C<YAML.pm> from being +loaded: + + cpan> o conf dontload_list push YAML + +See the source for details. + +=item has_usable($module) + +Returns true if the module is installed and in a usable state. Only +useful for a handful of modules that are used internally. See the +source for details. + +=item instance($module) + +The constructor for all the singletons used to represent modules, +distributions, authors, and bundles. If the object already exists, this +method returns the object; otherwise, it calls the constructor. + +=back + +=head1 SECURITY + +There's no strong security layer in CPAN.pm. CPAN.pm helps you to +install foreign, unmasked, unsigned code on your machine. We compare +to a checksum that comes from the net just as the distribution file +itself. But we try to make it easy to add security on demand: + +=head2 Cryptographically signed modules + +Since release 1.77, CPAN.pm has been able to verify cryptographically +signed module distributions using Module::Signature. The CPAN modules +can be signed by their authors, thus giving more security. The simple +unsigned MD5 checksums that were used before by CPAN protect mainly +against accidental file corruption. + +You will need to have Module::Signature installed, which in turn +requires that you have at least one of Crypt::OpenPGP module or the +command-line F<gpg> tool installed. + +You will also need to be able to connect over the Internet to the public +keyservers, like pgp.mit.edu, and their port 11731 (the HKP protocol). + +The configuration parameter check_sigs is there to turn signature +checking on or off. + +=head1 EXPORT + +Most functions in package CPAN are exported by default. The reason +for this is that the primary use is intended for the cpan shell or for +one-liners. + +=head1 ENVIRONMENT + +When the CPAN shell enters a subshell via the look command, it sets +the environment CPAN_SHELL_LEVEL to 1, or increments that variable if it is +already set. + +When CPAN runs, it sets the environment variable PERL5_CPAN_IS_RUNNING +to the ID of the running process. It also sets +PERL5_CPANPLUS_IS_RUNNING to prevent runaway processes which could +happen with older versions of Module::Install. + +When running C<perl Makefile.PL>, the environment variable +C<PERL5_CPAN_IS_EXECUTING> is set to the full path of the +C<Makefile.PL> that is being executed. This prevents runaway processes +with newer versions of Module::Install. + +When the config variable ftp_passive is set, all downloads will be run +with the environment variable FTP_PASSIVE set to this value. This is +in general a good idea as it influences both Net::FTP and LWP based +connections. The same effect can be achieved by starting the cpan +shell with this environment variable set. For Net::FTP alone, one can +also always set passive mode by running libnetcfg. + +=head1 POPULATE AN INSTALLATION WITH LOTS OF MODULES + +Populating a freshly installed perl with one's favorite modules is pretty +easy if you maintain a private bundle definition file. To get a useful +blueprint of a bundle definition file, the command autobundle can be used +on the CPAN shell command line. This command writes a bundle definition +file for all modules installed for the current perl +interpreter. It's recommended to run this command once only, and from then +on maintain the file manually under a private name, say +Bundle/my_bundle.pm. With a clever bundle file you can then simply say + + cpan> install Bundle::my_bundle + +then answer a few questions and go out for coffee (possibly +even in a different city). + +Maintaining a bundle definition file means keeping track of two +things: dependencies and interactivity. CPAN.pm sometimes fails on +calculating dependencies because not all modules define all MakeMaker +attributes correctly, so a bundle definition file should specify +prerequisites as early as possible. On the other hand, it's +annoying that so many distributions need some interactive configuring. So +what you can try to accomplish in your private bundle file is to have the +packages that need to be configured early in the file and the gentle +ones later, so you can go out for cofeee after a few minutes and leave CPAN.pm +to churn away untended. + +=head1 WORKING WITH CPAN.pm BEHIND FIREWALLS + +Thanks to Graham Barr for contributing the following paragraphs about +the interaction between perl, and various firewall configurations. For +further information on firewalls, it is recommended to consult the +documentation that comes with the I<ncftp> program. If you are unable to +go through the firewall with a simple Perl setup, it is likely +that you can configure I<ncftp> so that it works through your firewall. + +=head2 Three basic types of firewalls + +Firewalls can be categorized into three basic types. + +=over 4 + +=item http firewall + +This is when the firewall machine runs a web server, and to access the +outside world, you must do so via that web server. If you set environment +variables like http_proxy or ftp_proxy to values beginning with http://, +or in your web browser you've proxy information set, then you know +you are running behind an http firewall. + +To access servers outside these types of firewalls with perl (even for +ftp), you need LWP. + +=item ftp firewall + +This where the firewall machine runs an ftp server. This kind of +firewall will only let you access ftp servers outside the firewall. +This is usually done by connecting to the firewall with ftp, then +entering a username like "user@outside.host.com". + +To access servers outside these type of firewalls with perl, you +need Net::FTP. + +=item One-way visibility + +One-way visibility means these firewalls try to make themselves +invisible to users inside the firewall. An FTP data connection is +normally created by sending your IP address to the remote server and then +listening for the return connection. But the remote server will not be able to +connect to you because of the firewall. For these types of firewall, +FTP connections need to be done in a passive mode. + +There are two that I can think off. + +=over 4 + +=item SOCKS + +If you are using a SOCKS firewall, you will need to compile perl and link +it with the SOCKS library. This is what is normally called a 'socksified' +perl. With this executable you will be able to connect to servers outside +the firewall as if it were not there. + +=item IP Masquerade + +This is when the firewall implemented in the kernel (via NAT, or networking +address translation), it allows you to hide a complete network behind one +IP address. With this firewall no special compiling is needed as you can +access hosts directly. + +For accessing ftp servers behind such firewalls you usually need to +set the environment variable C<FTP_PASSIVE> or the config variable +ftp_passive to a true value. + +=back + +=back + +=head2 Configuring lynx or ncftp for going through a firewall + +If you can go through your firewall with e.g. lynx, presumably with a +command such as + + /usr/local/bin/lynx -pscott:tiger + +then you would configure CPAN.pm with the command + + o conf lynx "/usr/local/bin/lynx -pscott:tiger" + +That's all. Similarly for ncftp or ftp, you would configure something +like + + o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg" + +Your mileage may vary... + +=head1 FAQ + +=over 4 + +=item 1) + +I installed a new version of module X but CPAN keeps saying, +I have the old version installed + +Probably you B<do> have the old version installed. This can +happen if a module installs itself into a different directory in the +@INC path than it was previously installed. This is not really a +CPAN.pm problem, you would have the same problem when installing the +module manually. The easiest way to prevent this behaviour is to add +the argument C<UNINST=1> to the C<make install> call, and that is why +many people add this argument permanently by configuring + + o conf make_install_arg UNINST=1 + +=item 2) + +So why is UNINST=1 not the default? + +Because there are people who have their precise expectations about who +may install where in the @INC path and who uses which @INC array. In +fine tuned environments C<UNINST=1> can cause damage. + +=item 3) + +I want to clean up my mess, and install a new perl along with +all modules I have. How do I go about it? + +Run the autobundle command for your old perl and optionally rename the +resulting bundle file (e.g. Bundle/mybundle.pm), install the new perl +with the Configure option prefix, e.g. + + ./Configure -Dprefix=/usr/local/perl-5.6.78.9 + +Install the bundle file you produced in the first step with something like + + cpan> install Bundle::mybundle + +and you're done. + +=item 4) + +When I install bundles or multiple modules with one command +there is too much output to keep track of. + +You may want to configure something like + + o conf make_arg "| tee -ai /root/.cpan/logs/make.out" + o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out" + +so that STDOUT is captured in a file for later inspection. + + +=item 5) + +I am not root, how can I install a module in a personal directory? + +First of all, you will want to use your own configuration, not the one +that your root user installed. If you do not have permission to write +in the cpan directory that root has configured, you will be asked if +you want to create your own config. Answering "yes" will bring you into +CPAN's configuration stage, using the system config for all defaults except +things that have to do with CPAN's work directory, saving your choices to +your MyConfig.pm file. + +You can also manually initiate this process with the following command: + + % perl -MCPAN -e 'mkmyconfig' + +or by running + + mkmyconfig + +from the CPAN shell. + +You will most probably also want to configure something like this: + + o conf makepl_arg "LIB=~/myperl/lib \ + INSTALLMAN1DIR=~/myperl/man/man1 \ + INSTALLMAN3DIR=~/myperl/man/man3 \ + INSTALLSCRIPT=~/myperl/bin \ + INSTALLBIN=~/myperl/bin" + +and then the equivalent command for Module::Build, which is + + o conf mbuildpl_arg "--lib=~/myperl/lib \ + --installman1dir=~/myperl/man/man1 \ + --installman3dir=~/myperl/man/man3 \ + --installscript=~/myperl/bin \ + --installbin=~/myperl/bin" + +You can make this setting permanent like all C<o conf> settings with +C<o conf commit> or by setting C<auto_commit> beforehand. + +You will have to add ~/myperl/man to the MANPATH environment variable +and also tell your perl programs to look into ~/myperl/lib, e.g. by +including + + use lib "$ENV{HOME}/myperl/lib"; + +or setting the PERL5LIB environment variable. + +While we're speaking about $ENV{HOME}, it might be worth mentioning, +that for Windows we use the File::HomeDir module that provides an +equivalent to the concept of the home directory on Unix. + +Another thing you should bear in mind is that the UNINST parameter can +be dangerous when you are installing into a private area because you +might accidentally remove modules that other people depend on that are +not using the private area. + +=item 6) + +How to get a package, unwrap it, and make a change before building it? + +Have a look at the C<look> (!) command. + +=item 7) + +I installed a Bundle and had a couple of fails. When I +retried, everything resolved nicely. Can this be fixed to work +on first try? + +The reason for this is that CPAN does not know the dependencies of all +modules when it starts out. To decide about the additional items to +install, it just uses data found in the META.yml file or the generated +Makefile. An undetected missing piece breaks the process. But it may +well be that your Bundle installs some prerequisite later than some +depending item and thus your second try is able to resolve everything. +Please note, CPAN.pm does not know the dependency tree in advance and +cannot sort the queue of things to install in a topologically correct +order. It resolves perfectly well B<if> all modules declare the +prerequisites correctly with the PREREQ_PM attribute to MakeMaker or +the C<requires> stanza of Module::Build. For bundles which fail and +you need to install often, it is recommended to sort the Bundle +definition file manually. + +=item 8) + +In our intranet, we have many modules for internal use. How +can I integrate these modules with CPAN.pm but without uploading +the modules to CPAN? + +Have a look at the CPAN::Site module. + +=item 9) + +When I run CPAN's shell, I get an error message about things in my +C</etc/inputrc> (or C<~/.inputrc>) file. + +These are readline issues and can only be fixed by studying readline +configuration on your architecture and adjusting the referenced file +accordingly. Please make a backup of the C</etc/inputrc> or C<~/.inputrc> +and edit them. Quite often harmless changes like uppercasing or +lowercasing some arguments solves the problem. + +=item 10) + +Some authors have strange characters in their names. + +Internally CPAN.pm uses the UTF-8 charset. If your terminal is +expecting ISO-8859-1 charset, a converter can be activated by setting +term_is_latin to a true value in your config file. One way of doing so +would be + + cpan> o conf term_is_latin 1 + +If other charset support is needed, please file a bugreport against +CPAN.pm at rt.cpan.org and describe your needs. Maybe we can extend +the support or maybe UTF-8 terminals become widely available. + +Note: this config variable is deprecated and will be removed in a +future version of CPAN.pm. It will be replaced with the conventions +around the family of $LANG and $LC_* environment variables. + +=item 11) + +When an install fails for some reason and then I correct the error +condition and retry, CPAN.pm refuses to install the module, saying +C<Already tried without success>. + +Use the force pragma like so + + force install Foo::Bar + +Or you can use + + look Foo::Bar + +and then C<make install> directly in the subshell. + +=item 12) + +How do I install a "DEVELOPER RELEASE" of a module? + +By default, CPAN will install the latest non-developer release of a +module. If you want to install a dev release, you have to specify the +partial path starting with the author id to the tarball you wish to +install, like so: + + cpan> install KWILLIAMS/Module-Build-0.27_07.tar.gz + +Note that you can use the C<ls> command to get this path listed. + +=item 13) + +How do I install a module and all its dependencies from the commandline, +without being prompted for anything, despite my CPAN configuration +(or lack thereof)? + +CPAN uses ExtUtils::MakeMaker's prompt() function to ask its questions, so +if you set the PERL_MM_USE_DEFAULT environment variable, you shouldn't be +asked any questions at all (assuming the modules you are installing are +nice about obeying that variable as well): + + % PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'install My::Module' + +=item 14) + +How do I create a Module::Build based Build.PL derived from an +ExtUtils::MakeMaker focused Makefile.PL? + +http://search.cpan.org/dist/Module-Build-Convert/ + +=item 15) + +I'm frequently irritated with the CPAN shell's inability to help me +select a good mirror. + +The urllist config parameter is yours. You can add and remove sites at +will. You should find out which sites have the best uptodateness, +bandwidth, reliability, etc. and are topologically close to you. Some +people prefer fast downloads, others uptodateness, others reliability. +You decide which to try in which order. + +Henk P. Penning maintains a site that collects data about CPAN sites: + + http://www.cs.uu.nl/people/henkp/mirmon/cpan.html + +Also, feel free to play with experimental features. Run + + o conf init randomize_urllist ftpstats_period ftpstats_size + +and choose your favorite parameters. After a few downloads running the +C<hosts> command will probably assist you in choosing the best mirror +sites. + +=item 16) + +Why do I get asked the same questions every time I start the shell? + +You can make your configuration changes permanent by calling the +command C<o conf commit>. Alternatively set the C<auto_commit> +variable to true by running C<o conf init auto_commit> and answering +the following question with yes. + +=item 17) + +Older versions of CPAN.pm had the original root directory of all +tarballs in the build directory. Now there are always random +characters appended to these directory names. Why was this done? + +The random characters are provided by File::Temp and ensure that each +module's individual build directory is unique. This makes running +CPAN.pm in concurrent processes simultaneously safe. + +=item 18) + +Speaking of the build directory. Do I have to clean it up myself? + +You have the choice to set the config variable C<scan_cache> to +C<never>. Then you must clean it up yourself. The other possible +value, C<atstart> only cleans up the build directory when you start +the CPAN shell. If you never start up the CPAN shell, you probably +also have to clean up the build directory yourself. + +=back + +=head1 COMPATIBILITY + +=head2 OLD PERL VERSIONS + +CPAN.pm is regularly tested to run under 5.004, 5.005, and assorted +newer versions. It is getting more and more difficult to get the +minimal prerequisites working on older perls. It is close to +impossible to get the whole Bundle::CPAN working there. If you're in +the position to have only these old versions, be advised that CPAN is +designed to work fine without the Bundle::CPAN installed. + +To get things going, note that GBARR/Scalar-List-Utils-1.18.tar.gz is +compatible with ancient perls and that File::Temp is listed as a +prerequisite but CPAN has reasonable workarounds if it is missing. + +=head2 CPANPLUS + +This module and its competitor, the CPANPLUS module, are both much +cooler than the other. CPAN.pm is older. CPANPLUS was designed to be +more modular, but it was never intended to be compatible with CPAN.pm. + +=head1 SECURITY ADVICE + +This software enables you to upgrade software on your computer and so +is inherently dangerous because the newly installed software may +contain bugs and may alter the way your computer works or even make it +unusable. Please consider backing up your data before every upgrade. + +=head1 BUGS + +Please report bugs via L<http://rt.cpan.org/> + +Before submitting a bug, please make sure that the traditional method +of building a Perl module package from a shell by following the +installation instructions of that package still works in your +environment. + +=head1 AUTHOR + +Andreas Koenig C<< <andk@cpan.org> >> + +=head1 LICENSE + +This program is free software; you can redistribute it and/or +modify it under the same terms as Perl itself. + +See L<http://www.perl.com/perl/misc/Artistic.html> + +=head1 TRANSLATIONS + +Kawai,Takanori provides a Japanese translation of a very old version +of this manpage at +L<http://homepage3.nifty.com/hippo2000/perltips/CPAN.htm> + +=head1 SEE ALSO + +Many people enter the CPAN shell by running the L<cpan> utility +program which is installed in the same directory as perl itself. So if +you have this directory in your PATH variable (or some equivalent in +your operating system) then typing C<cpan> in a console window will +work for you as well. Above that the utility provides several +commandline shortcuts. + +=cut |