| # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- |
| # vim: ts=4 sts=4 sw=4: |
| use strict; |
| package CPAN; |
| $CPAN::VERSION = '1.9800'; |
| $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 CPAN::Exception::yaml_process_error; |
| |
| 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)) { |
| # temporarily 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")) { |
| $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 '$!'. |
| |
| 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} |
| |
| # Adapted from Probe::Perl |
| #-> sub CPAN::_perl_is_same |
| sub _perl_is_same { |
| my ($perl) = @_; |
| return MM->maybe_command($perl) |
| && `$perl -MConfig=myconfig -e print -e myconfig` eq Config->myconfig; |
| } |
| |
| # Adapted in part from Probe::Perl |
| #-> sub CPAN::find_perl ; |
| sub find_perl () { |
| if ( File::Spec->file_name_is_absolute($^X) ) { |
| return $^X; |
| } |
| else { |
| my $exe = $Config::Config{exe_ext}; |
| my @candidates = ( |
| File::Spec->catfile($CPAN::iCwd,$^X), |
| $Config::Config{'perlpath'}, |
| ); |
| for my $perl_name ($^X, 'perl', 'perl5', "perl$]") { |
| for my $path (File::Spec->path(), $Config::Config{'binexp'}) { |
| if ( defined($path) && length $path && -d $path ) { |
| my $perl = File::Spec->catfile($path,$perl_name); |
| push @candidates, $perl; |
| # try with extension if not provided already |
| if ($^O eq 'VMS') { |
| # VMS might have a file version at the end |
| push @candidates, $perl . $exe |
| unless $perl =~ m/$exe(;\d+)?$/i; |
| } elsif (defined $exe && length $exe) { |
| push @candidates, $perl . $exe |
| unless $perl =~ m/$exe$/i; |
| } |
| } |
| } |
| } |
| for my $perl ( @candidates ) { |
| if (MM->maybe_command($perl) && _perl_is_same($perl)) { |
| $^X = $perl; |
| return $perl; |
| } |
| } |
| } |
| return $^X; # default fall back |
| } |
| |
| #-> 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; |
| # |
| 'CPAN::Meta' => [ |
| sub { |
| require CPAN::Meta; |
| unless (CPAN::Version->vge(CPAN::Meta->VERSION, 2.110350)) { |
| for ("Will not use CPAN::Meta, need version 2.110350\n") { |
| $CPAN::Frontend->mywarn($_); |
| die $_; |
| } |
| } |
| }, |
| ], |
| |
| 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}, |
| ], |
| 'HTTP::Tiny' => [ |
| sub { |
| require HTTP::Tiny; |
| unless (CPAN::Version->vge(HTTP::Tiny->VERSION, 0.005)) { |
| for ("Will not use HTTP::Tiny, need version 0.005\n") { |
| $CPAN::Frontend->mywarn($_); |
| die $_; |
| } |
| } |
| }, |
| ], |
| '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 |
| key servers like pool.sks-keyservers.net or pgp.mit.edu. |
| |
| }); |
| $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::_exit_messages ; |
| sub _exit_messages { |
| my ($self) = @_; |
| $self->{exit_messages} ||= []; |
| } |
| |
| #-> 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; |
| $META->{cachemgr} ||= CPAN::CacheMgr->new('atexit'); |
| 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"); |
| for my $msg ( @{ $META->_exit_messages } ) { |
| $CPAN::Frontend->myprint($msg); |
| } |
| } |
| |
| #-> 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 LWP, HTTP::Tiny, Net::FTP 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. Duplicates of each distribution are suppressed. |
| The name of the bundle file is based on the current date and a |
| counter. |
| |
| Return value: path to the written file. |
| |
| =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 r [Module|/Regexp/]... |
| |
| scans current perl installation for modules that have a newer version |
| available on CPAN and provides a list of them. If called without |
| argument, all potential upgrades are listed; if called with arguments |
| the list is filtered to the modules and regexps given as arguments. |
| |
| The listing looks something like this: |
| |
| Package namespace installed latest in CPAN file |
| CPAN 1.94_64 1.9600 ANDK/CPAN-1.9600.tar.gz |
| CPAN::Reporter 1.1801 1.1902 DAGOLDEN/CPAN-Reporter-1.1902.tar.gz |
| YAML 0.70 0.73 INGY/YAML-0.73.tar.gz |
| YAML::Syck 1.14 1.17 AVAR/YAML-Syck-1.17.tar.gz |
| YAML::Tiny 1.44 1.50 ADAMK/YAML-Tiny-1.50.tar.gz |
| CGI 3.43 3.55 MARKSTOS/CGI.pm-3.55.tar.gz |
| Module::Build::YAML 1.40 1.41 DAGOLDEN/Module-Build-0.3800.tar.gz |
| TAP::Parser::Result::YAML 3.22 3.23 ANDYA/Test-Harness-3.23.tar.gz |
| YAML::XS 0.34 0.35 INGY/YAML-LibYAML-0.35.tar.gz |
| |
| It suppresses duplicates in the column C<in CPAN file> such that |
| distributions with many upgradeable modules are listed only once. |
| |
| Note that the list is not sorted. |
| |
| =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 (a.k.a. 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|/Regexp/]... |
| |
| 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 regexp |
| 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 environment variable 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_external_tar |
| per default all untar operations are done with |
| Archive::Tar; by setting this variable to true |
| the external tar command is used if available |
| 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', 'atexit' 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 |
| distro name. 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. The arguments on the commandline are |
| passed as arguments to the method. |
| |
| So if you take for example the shell command |
| |
| notest install A B C |
| |
| the actually executed command is |
| |
| CPAN::Shell->notest("install","A","B","C"); |
| |
| 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 up-to-date. |
| |
| =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 successfully 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 distro name (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 |
| up-to-date. 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 up-to-date, 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 maintenance |
| |
| 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: approved by www.opensource.org |
| d - allows distribution without restrictions |
| r - restricted distribution |
| 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, i.e. 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 environment. 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 |
| key servers, 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 coffee 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 or HTTP::Tiny. |
| |
| =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? |
| |
| As of CPAN 1.9463, if you do not have permission to write the default perl |
| library directories, CPAN's configuration process will ask you whether |
| you want to bootstrap <local::lib>, which makes keeping a personal |
| perl library directory easy. |
| |
| 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 bug report 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. |
| |
| CPAN can now help you select a "good" mirror, based on which ones have the |
| lowest 'ping' round-trip times. From the shell, use the command 'o conf init |
| urllist' and allow CPAN to automatically select mirrors for you. |
| |
| Beyond that help, the urllist config parameter is yours. You can add and remove |
| sites at will. You should find out which sites have the best up-to-dateness, |
| bandwidth, reliability, etc. and are topologically close to you. Some people |
| prefer fast downloads, others up-to-dateness, 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 |
| values, C<atstart> and C<atexit> clean up the build directory when you |
| start or exit the CPAN shell, respectively. 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. |
| |
| =head2 CPANMINUS |
| |
| In the year 2010 App::cpanminus was launched as a new approach to a |
| cpan shell with a considerably smaller footprint. Very cool stuff. |
| |
| =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 |