From: Steve Peters Date: Tue, 13 Feb 2007 15:23:00 +0000 (+0000) Subject: Upgrade to CPAN-1.88_72 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=f20de9f042d39c1d62d00a7c9da4cca3665ec21d;p=p5sagit%2Fp5-mst-13.2.git Upgrade to CPAN-1.88_72 p4raw-id: //depot/perl@30256 --- diff --git a/lib/CPAN.pm b/lib/CPAN.pm index 434fc16..2221a5f 100644 --- a/lib/CPAN.pm +++ b/lib/CPAN.pm @@ -1,7 +1,7 @@ # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- use strict; package CPAN; -$CPAN::VERSION = '1.88_69'; +$CPAN::VERSION = '1.88_73'; $CPAN::VERSION = eval $CPAN::VERSION; use CPAN::HandleConfig; @@ -64,13 +64,13 @@ use vars qw( $AUTOLOAD $Be_Silent $CONFIG_DIRTY - $DEBUG $Defaultdocs $Defaultrecent $Frontend $GOTOSHELL $HAS_USABLE $Have_warned + $MAX_RECURSION $META $RUN_DEGRADED $Signal @@ -83,6 +83,8 @@ use vars qw( @EXPORT ); +$MAX_RECURSION = 32; + @CPAN::ISA = qw(CPAN::Debug Exporter); # note that these functions live in CPAN::Shell and get executed via @@ -98,6 +100,7 @@ use vars qw( get install install_tested + is_tested make mkmyconfig notest @@ -179,14 +182,7 @@ sub shell { $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n"); last; } - my($fh) = FileHandle->new; - open $fh, "<$histfile" or last; - local $/ = "\n"; - while (<$fh>) { - chomp; - $term->AddHistory($_); - } - close $fh; + $META->readhist($term,$histfile); }} for ($CPAN::Config->{term_ornaments}) { # alias local $Term::ReadLine::termcap_nowarn = 1; @@ -374,14 +370,28 @@ sub _yaml_loadfile { return +[] unless -s $local_file; my $yaml_module = _yaml_module; if ($CPAN::META->has_inst($yaml_module)) { - my $code = UNIVERSAL::can($yaml_module, "LoadFile"); - my @yaml; - 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",$@); + my $code; + if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) { + my @yaml; + 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",$@); + } + return \@yaml; + } elsif ($code = UNIVERSAL::can($yaml_module, "Load")) { + local *FH; + open FH, $local_file or die "Could not open '$local_file': $!"; + local $/; + my $ystream = ; + my @yaml; + 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",$@); + } + return \@yaml; } - return \@yaml; } else { # this shall not be done by the frontend die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "parse"); @@ -394,12 +404,16 @@ 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")) { - my $code = UNIVERSAL::can($yaml_module, "Dump"); + $code = UNIVERSAL::can($yaml_module, "Dump"); eval { print $local_file $code->(@what) }; - } else { - my $code = UNIVERSAL::can($yaml_module, "DumpFile"); + } 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",$@); @@ -466,11 +480,13 @@ use strict; clean cvs_import dump + failed force fforce hosts install install_tested + is_tested look ls make @@ -520,6 +536,10 @@ package CPAN::Exception::RecursiveDependency; use strict; use overload '""' => "as_string"; +# a module sees its distribution (no version) +# a distribution sees its prereqs (which are module names) (usually with versions) +# a bundle sees its module names and/or its distributions (no version) + sub new { my($class) = shift; my($deps) = shift; @@ -709,10 +729,11 @@ sub _perl_fingerprint { if (defined $dll) { $mtime_dll = (-f $dll ? (stat(_))[9] : '-1'); } + my $mtime_perl = (-f $^X ? (stat(_))[9] : '-1'); my $this_fingerprint = { '$^X' => $^X, sitearchexp => $Config::Config{sitearchexp}, - 'mtime_$^X' => (stat $^X)[9], + 'mtime_$^X' => $mtime_perl, 'mtime_dll' => $mtime_dll, }; if ($other_fingerprint) { @@ -1064,6 +1085,16 @@ sub has_usable { } }, ], + 'Archive::Tar' => [ + sub {require Archive::Tar; + unless (Archive::Tar::->VERSION >= 1.00) { + for ("Will not use Archive::Tar, need 1.00\n") { + $CPAN::Frontend->mywarn($_); + die $_; + } + } + }, + ], }; if ($usable->{$mod}) { for my $c (0..$#{$usable->{$mod}}) { @@ -1128,7 +1159,7 @@ sub has_inst { $CPAN::Frontend->mysleep(3); } elsif ($mod eq "Digest::SHA"){ if ($Have_warned->{"Digest::SHA"}++) { - $CPAN::Frontend->myprint(qq{CPAN: checksum security checks disabled}. + $CPAN::Frontend->myprint(qq{CPAN: checksum security checks disabled }. qq{because Digest::SHA not installed.\n}); } else { $CPAN::Frontend->mywarn(qq{ @@ -1210,6 +1241,19 @@ sub cleanup { $CPAN::Frontend->myprint("Lockfile removed.\n"); } +#-> sub CPAN::readhist +sub readhist { + my($self,$term,$histfile) = @_; + my($fh) = FileHandle->new; + open $fh, "<$histfile" or last; + local $/ = "\n"; + while (<$fh>) { + chomp; + $term->AddHistory($_); + } + close $fh; +} + #-> sub CPAN::savehist sub savehist { my($self) = @_; @@ -1327,8 +1371,11 @@ sub tidyup { my($toremove) = shift @{$self->{FIFO}}; unless ($toremove =~ /\.yml$/) { $CPAN::Frontend->myprint(sprintf( - "DEL: $toremove (%.1f>%.1f MB)\n", - $self->{DU}, $self->{'MAX'}) + "DEL(%.1f>%.1fMB): %s \n", + $self->{DU}, + $self->{MAX}, + $toremove, + ) ); } return if $CPAN::Signal; @@ -1436,7 +1483,22 @@ sub _clean_cache { $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}") if $CPAN::DEBUG; File::Path::rmtree($dir); - unlink "$dir.yml"; # may fail + my $id_deleted = 0; + if ($dir !~ /\.yml$/ && -f "$dir.yml") { + my $yaml_module = CPAN::_yaml_module; + if ($CPAN::META->has_inst($yaml_module)) { + my($peek_yaml) = CPAN->_yaml_loadfile("$dir.yml"); + if (my $id = $peek_yaml->[0]{distribution}{ID}) { + $CPAN::META->delete("CPAN::Distribution", $id); + # $CPAN::Frontend->mywarn (" +++\n"); + $id_deleted++; + } + } + unlink "$dir.yml"; # may fail + unless ($id_deleted) { + CPAN->debug("no distro found associated with '$dir'"); + } + } $self->{DU} -= $self->{SIZE}{$dir}; delete $self->{SIZE}{$dir}; } @@ -1470,6 +1532,7 @@ sub scan_cache { return if $self->{SCAN} eq 'never'; $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}") unless $self->{SCAN} eq 'atstart'; + return unless $CPAN::META->{LOCK}; $CPAN::Frontend->myprint( sprintf("Scanning cache %s for sizes\n", $self->{ID})); @@ -1724,7 +1787,7 @@ sub o { CPAN::HandleConfig->prettyprint($k); } $CPAN::Frontend->myprint("\n"); - } else { + } else { if (CPAN::HandleConfig->edit(@o_what)) { } else { $CPAN::Frontend->myprint(qq{Type 'o conf' to view all configuration }. @@ -1841,7 +1904,7 @@ sub hosts { $S{end} ||= $last->{end}; my $dltime = $last->{end} - $start; my $dlsize = $last->{filesize} || 0; - my $url = $last->{thesiteurl}->text; + my $url = ref $last->{thesiteurl} ? $last->{thesiteurl}->text : $last->{thesiteurl}; my $s = $S{ok}{$url} ||= {}; $s->{n}++; $s->{dlsize} ||= 0; @@ -1904,6 +1967,7 @@ sub reload { "CPAN/Kwalify.pm", "CPAN/Queue.pm", "CPAN/Reporter.pm", + "CPAN/SQLite.pm", "CPAN/Tarzip.pm", "CPAN/Version.pm", ); @@ -2127,7 +2191,7 @@ sub report { # re-run (as documented) } -# experimental (compare with _is_tested) +# compare with is_tested #-> sub CPAN::Shell::install_tested sub install_tested { my($self,@some) = @_; @@ -2141,8 +2205,8 @@ sub install_tested { $CPAN::Frontend->mywarn("No YAML file for $b available, skipping\n"); next; } - my $yaml_content = CPAN::_yaml_loadfile($yaml); - my $id = $yaml_content->[0]{ID}; + my $yaml_content = CPAN->_yaml_loadfile($yaml); + my $id = $yaml_content->[0]{distribution}{ID}; unless ($id){ $CPAN::Frontend->mywarn("No ID found in '$yaml', skipping\n"); next; @@ -2442,11 +2506,11 @@ sub status { } } -# experimental (must run after failed or similar [I think]) -# intended as a preparation ot install_tested +# compare with install_tested #-> sub CPAN::Shell::is_tested -sub _is_tested { +sub is_tested { my($self) = @_; + CPAN::Index->reload; for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) { my $time; if ($CPAN::META->{is_tested}{$b}) { @@ -2727,7 +2791,7 @@ sub print_ornamented { my $color_on = eval { Term::ANSIColor::color($ornament) } || ""; if ($@) { print "Term::ANSIColor rejects color[$ornament]: $@\n -Please choose a different color (Hint: try 'o conf init color.*')\n"; +Please choose a different color (Hint: try 'o conf init /color/')\n"; } print $color_on, $swhat, @@ -2819,6 +2883,7 @@ sub unrecoverable_error { #-> sub CPAN::Shell::mysleep ; sub mysleep { my($self, $sleep) = @_; + use Time::HiRes qw(sleep); sleep $sleep; } @@ -2861,6 +2926,8 @@ sub rematein { # enter the queue but not its copy. How do they get a sensible # test_count? + my $needs_recursion_protection = "make|test|install"; + # construct the queue my($s,@s,@qcopy); STHING: foreach $s (@some) { @@ -2887,7 +2954,10 @@ sub rematein { } if (0) { } elsif (ref $obj) { - $obj->color_cmd_tmps(0,1); + if ($meth =~ /^($needs_recursion_protection)$/) { + # silly for look or dump + $obj->color_cmd_tmps(0,1); + } CPAN::Queue->new(qmod => $obj->id, reqtype => "c"); push @qcopy, $obj; } elsif ($CPAN::META->exists('CPAN::Author',uc($s))) { @@ -2927,6 +2997,15 @@ to find objects with matching identifiers. my $s = $q->as_string; my $reqtype = $q->reqtype || ""; $obj = CPAN::Shell->expandany($s); + unless ($obj) { + # don't know how this can happen, maybe we should panic, + # but maybe we get a solution from the first user who hits + # this unfortunate exception? + $CPAN::Frontend->mywarn("Warning: Could not expand string '$s' ". + "to an object. Skipping."); + $CPAN::Frontend->mysleep(5); + next; + } $obj->{reqtype} ||= ""; { # force debugging because CPAN::SQLite somehow delivers us @@ -3002,8 +3081,10 @@ to find objects with matching identifiers. } CPAN::Queue->delete_first($s); } - for my $obj (@qcopy) { - $obj->color_cmd_tmps(0,0); + if ($meth =~ /^($needs_recursion_protection)$/) { + for my $obj (@qcopy) { + $obj->color_cmd_tmps(0,0); + } } } @@ -3233,6 +3314,7 @@ sub _new_stats { sub _add_to_statistics { my($self,$stats) = @_; my $yaml_module = CPAN::_yaml_module; + $self->debug("yaml_module[$yaml_module]") if $CPAN::DEBUG; if ($CPAN::META->has_inst($yaml_module)) { $stats->{thesiteurl} = $ThesiteURL; if (CPAN->has_inst("Time::HiRes")) { @@ -3254,7 +3336,7 @@ sub _add_to_statistics { # arbitrary hardcoded constants until somebody demands to have # them settable while ( - @{$fullstats->{history}} > 9999 + @{$fullstats->{history}} > 999 || $time - $fullstats->{history}[0]{start} > 30*86400 # one month ) { shift @{$fullstats->{history}} @@ -3563,7 +3645,9 @@ sub localize { if ($ret) { $stats->{filesize} = -s $ret; } + $self->debug("before _add_to_statistics") if $CPAN::DEBUG; $self->_add_to_statistics($stats); + $self->debug("after _add_to_statistics") if $CPAN::DEBUG; if ($ret) { unlink "$aslocal.bak$$"; return $ret; @@ -4202,7 +4286,7 @@ sub cpl { $pos ||= 0; CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG; $line =~ s/^\s*//; - if ($line =~ s/^(force\s*)//) { + if ($line =~ s/^((?:notest|f?force)\s*)//) { $pos -= length($1); } my @return; @@ -5372,7 +5456,11 @@ sub pretty_id { substr($id,5); } -# mark as dirty/clean +# mark as dirty/clean for the sake of recursion detection. $color=1 +# means "in use", $color=0 means "not in use anymore". $color=2 means +# we have determined prereqs now and thus insist on passing this +# through (at least) once again. + #-> sub CPAN::Distribution::color_cmd_tmps ; sub color_cmd_tmps { my($self) = shift; @@ -5382,8 +5470,9 @@ sub color_cmd_tmps { # a distribution needs to recurse into its prereq_pms return if exists $self->{incommandcolor} + && $color==1 && $self->{incommandcolor}==$color; - if ($depth>=100){ + if ($depth>=$CPAN::MAX_RECURSION){ $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors)); } # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; @@ -5407,7 +5496,7 @@ sub color_cmd_tmps { # as we are at the end of a command, we'll give up this # reminder of a broken test. Other commands may test this guy # again. Maybe 'badtestcnt' should be renamed to - # 'makte_test_failed_within_command'? + # 'make_test_failed_within_command'? delete $self->{badtestcnt}; } $self->{incommandcolor} = $color; @@ -5745,8 +5834,10 @@ EOF my $prefer_installer = "eumm"; # eumm|mb if (-f File::Spec->catfile($packagedir,"Build.PL")) { if ($mpl_exists) { # they *can* choose - $prefer_installer = CPAN::HandleConfig->prefs_lookup($self, - q{prefer_installer}); + if ($CPAN::META->has_inst("Module::Build")) { + $prefer_installer = CPAN::HandleConfig->prefs_lookup($self, + q{prefer_installer}); + } } else { $prefer_installer = "mb"; } @@ -7190,6 +7281,13 @@ sub _find_prefs { # CPAN::Distribution::prefs sub prefs { my($self) = @_; + if (exists $self->{negative_prefs_cache} + && + $self->{negative_prefs_cache} != $CPAN::CurrentCommandId + ) { + delete $self->{negative_prefs_cache}; + delete $self->{prefs}; + } if (exists $self->{prefs}) { return $self->{prefs}; # XXX comment out during debugging } @@ -7219,7 +7317,8 @@ $filler2 $bs $filler2 return $self->{prefs}; } } - return +{}; + $self->{negative_prefs_cache} = $CPAN::CurrentCommandId; + return $self->{prefs} = +{}; } # CPAN::Distribution::make_x_arg @@ -7280,6 +7379,7 @@ sub follow_prereqs { c => "commandline", ); my($filler1,$filler2,$filler3,$filler4); + # $DB::single=1; my $unsat = "Unsatisfied dependencies detected during"; my $w = length($unsat) > length($pretty_id) ? length($unsat) : length($pretty_id); { @@ -7319,7 +7419,7 @@ of modules we are processing right now?", "yes"); # warn "calling color_cmd_tmps(0,1)"; my $any = CPAN::Shell->expandany($p); if ($any) { - $any->color_cmd_tmps(0,1); + $any->color_cmd_tmps(0,2); } else { $CPAN::Frontend->mywarn("Warning (maybe a bug): Cannot expand prereq '$p'\n"); $CPAN::Frontend->mysleep(2); @@ -7341,19 +7441,21 @@ sub unsat_prereq { my $prereq_pm = $self->prereq_pm or return; my(@need); my %merged = (%{$prereq_pm->{requires}||{}},%{$prereq_pm->{build_requires}||{}}); + my @merged = %merged; + CPAN->debug("all merged_prereqs[@merged]") if $CPAN::DEBUG; NEED: while (my($need_module, $need_version) = each %merged) { - my($available_version,$available_file); + my($available_version,$available_file,$nmo); if ($need_module eq "perl") { $available_version = $]; $available_file = $^X; } else { - my $nmo = $CPAN::META->instance("CPAN::Module",$need_module); + $nmo = $CPAN::META->instance("CPAN::Module",$need_module); next if $nmo->uptodate; $available_file = $nmo->available_file; # if they have not specified a version, we accept any installed one if (not defined $need_version or - $need_version eq "0" or + $need_version == 0 or $need_version eq "undef") { next if defined $available_file; } @@ -7410,13 +7512,71 @@ sub unsat_prereq { } if ($self->{sponsored_mods}{$need_module}++){ # We have already sponsored it and for some reason it's still - # not available. So we do nothing. Or what should we do? + # not available. So we do ... what?? + # if we push it again, we have a potential infinite loop - next; + + # The following "next" was a very problematic construct. + # It helped a lot but broke some day and must be replaced. + + # We must be able to deal with modules that come again and + # again as a prereq and have themselves prereqs and the + # queue becomes long but finally we would find the correct + # order. The RecursiveDependency check should trigger a + # die when it's becoming too weird. Unfortunately removing + # this next breaks many other things. + + # The bug that brought this up is described in Todo under + # "5.8.9 cannot install Compress::Zlib" + + # next; # this is the next that must go away + + # The following "next NEED" are fine and the error message + # explains well what is going on. For example when the DBI + # fails and consequently DBD::SQLite fails and now we are + # processing CPAN::SQLite. Then we must have a "next" for + # DBD::SQLite. How can we get it and how can we identify + # all other cases we must identify? + + my $do = $nmo->distribution; + next NEED unless $do; # not on CPAN + NOSAYER: for my $nosayer ( + "unwrapped", + "writemakefile", + "signature_verify", + "make", + "make_test", + "install", + "make_clean", + ) { + if ( + $do->{$nosayer} + &&(UNIVERSAL::can($do->{$nosayer},"failed") ? + $do->{$nosayer}->failed : + $do->{$nosayer} =~ /^NO/) + ) { + if ($nosayer eq "make_test" + && + $do->{make_test}{COMMANDID} != $CPAN::CurrentCommandId + ) { + next NOSAYER; + } + $CPAN::Frontend->mywarn("Warning: Prerequisite ". + "'$need_module => $need_version' ". + "for '$self->{ID}' failed when ". + "processing '$do->{ID}' with ". + "'$nosayer => $do->{$nosayer}'. Continuing, ". + "but chances to succeed are limited.\n" + ); + next NEED; + } + } } my $needed_as = exists $prereq_pm->{requires}{$need_module} ? "r" : "b"; push @need, [$need_module,$needed_as]; } + my @unfolded = map { "[".join(",",@$_)."]" } @need; + CPAN->debug("returning from unsat_prereq[@unfolded]") if $CPAN::DEBUG; @need; } @@ -7437,6 +7597,7 @@ sub read_yaml { # cannot read YAML's own # META.yml } + # not "authoritative" if (not exists $self->{yaml_content}{dynamic_config} or $self->{yaml_content}{dynamic_config} ) { @@ -7451,7 +7612,7 @@ sub read_yaml { sub prereq_pm { my($self) = @_; $self->{prereq_pm_detected} ||= 0; - CPAN->debug("prereq_pm_detected[$self->{prereq_pm_detected}]") if $CPAN::DEBUG; + CPAN->debug("ID[$self->{ID}]prereq_pm_detected[$self->{prereq_pm_detected}]") if $CPAN::DEBUG; return $self->{prereq_pm} if $self->{prereq_pm_detected}; return unless $self->{writemakefile} # no need to have succeeded # but we must have run it @@ -7516,13 +7677,17 @@ sub prereq_pm { # Regexp modified by A.Speer to remember actual version of file # PREREQ_PM hash key wants, then add to - while ( $p =~ m/(?:\s)([\w\:]+)=>q\[(.*?)\],?/g ){ + while ( $p =~ m/(?:\s)([\w\:]+)=>(q\[.*?\]|undef),?/g ){ # In case a prereq is mentioned twice, complain. if ( defined $req->{$1} ) { warn "Warning: PREREQ_PM mentions $1 more than once, ". "last mention wins"; } - $req->{$1} = $2; + my($m,$n) = ($1,$2); + if ($n =~ /^q\[(.*?)\]$/) { + $n = $1; + } + $req->{$m} = $n; } last; } @@ -7597,11 +7762,17 @@ sub test { local $ENV{MAKEFLAGS}; # protect us from outer make calls $CPAN::Frontend->myprint("Running $make test\n"); - if (my @prereq = $self->unsat_prereq){ - unless ($prereq[0][0] eq "perl") { - return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner - } - } + +# if (my @prereq = $self->unsat_prereq){ +# if ( $CPAN::DEBUG ) { +# require Data::Dumper; +# CPAN->debug(sprintf "unsat_prereq[%s]", Data::Dumper::Dumper(\@prereq)); +# } +# unless ($prereq[0][0] eq "perl") { +# return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner +# } +# } + EXCUSE: { my @e; unless (exists $self->{make} or exists $self->{later}) { @@ -7617,8 +7788,11 @@ sub test { ) and push @e, "Can't test without successful make"; $self->{badtestcnt} ||= 0; - $self->{badtestcnt} > 0 and + if ($self->{badtestcnt} > 0) { + require Data::Dumper; + CPAN->debug(sprintf "NOREPEAT[%s]", Data::Dumper::Dumper($self)) if $CPAN::DEBUG; push @e, "Won't repeat unsuccessful test during this command"; + } exists $self->{later} and length($self->{later}) and push @e, $self->{later}; @@ -7672,6 +7846,11 @@ sub test { } else { $system = join " ", $self->_make_command(), "test"; } + my $make_test_arg = $self->make_x_arg("test"); + $system = sprintf("%s%s", + $system, + $make_test_arg ? " $make_test_arg" : "", + ); my($tests_ok); my %env; while (my($k,$v) = each %ENV) { @@ -7750,7 +7929,7 @@ sub test { # local $CPAN::DEBUG = 16; # Distribution for my $m (keys %{$self->{sponsored_mods}}) { - my $m_obj = CPAN::Shell->expand("Module",$m); + my $m_obj = CPAN::Shell->expand("Module",$m) or next; # XXX we need available_version which reflects # $ENV{PERL5LIB} so that already tested but not yet # installed modules are counted. @@ -7917,7 +8096,10 @@ sub install { if (my $goto = $self->prefs->{goto}) { return $self->goto($goto); } - $self->test; + $DB::single=1; + unless ($self->{badtestcnt}) { + $self->test; + } if ($CPAN::Signal){ delete $self->{force_update}; return; @@ -8333,8 +8515,9 @@ sub color_cmd_tmps { # to recurse into its prereq_pms, a bundle needs to recurse into its modules return if exists $self->{incommandcolor} + && $color==1 && $self->{incommandcolor}==$color; - if ($depth>=100){ + if ($depth>=$CPAN::MAX_RECURSION){ $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors)); } # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; @@ -8522,62 +8705,6 @@ Going to $meth that. my $obj = $CPAN::META->instance($type,$s); $obj->{reqtype} = $self->{reqtype}; $obj->$meth(); - if ($obj->isa('CPAN::Bundle') - && - exists $obj->{install_failed} - && - ref($obj->{install_failed}) eq "HASH" - ) { - for (keys %{$obj->{install_failed}}) { - $self->{install_failed}{$_} = undef; # propagate faiure up - # to me in a - # recursive call - $fail{$s} = 1; # the bundle itself may have succeeded but - # not all children - } - } else { - my $success; - $success = $obj->can("uptodate") ? $obj->uptodate : 0; - $success ||= $obj->{install} && $obj->{install} eq "YES"; - if ($success) { - delete $self->{install_failed}{$s}; - } else { - $fail{$s} = 1; - } - } - } - - # recap with less noise - if ( $meth eq "install" ) { - if (%fail) { - require Text::Wrap; - my $raw = sprintf(qq{Bundle summary: -The following items in bundle %s had installation problems:}, - $self->id - ); - $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw)); - $CPAN::Frontend->myprint("\n"); - my $paragraph = ""; - my %reported; - for $s ($self->contains) { - if ($fail{$s}){ - $paragraph .= "$s "; - $self->{install_failed}{$s} = undef; - $reported{$s} = undef; - } - } - my $report_propagated; - for $s (sort keys %{$self->{install_failed}}) { - next if exists $reported{$s}; - $paragraph .= "and the following items had problems -during recursive bundle calls: " unless $report_propagated++; - $paragraph .= "$s "; - } - $CPAN::Frontend->myprint(Text::Wrap::fill(" "," ",$paragraph)); - $CPAN::Frontend->myprint("\n"); - } else { - $self->{install} = 'YES'; - } } } @@ -8675,9 +8802,41 @@ sub color_cmd_tmps { # a module needs to recurse to its cpan_file return if exists $self->{incommandcolor} + && $color==1 && $self->{incommandcolor}==$color; - return if $depth>=1 && $self->uptodate; - if ($depth>=100){ + return if $color==0 && !$self->{incommandcolor}; + if ($color>=1) { + if ( $self->uptodate ) { + $self->{incommandcolor} = $color; + return; + } elsif (my $have_version = $self->available_version) { + # maybe what we have is good enough + if (@$ancestors) { + my $who_asked_for_me = $ancestors->[-1]; + my $obj = CPAN::Shell->expandany($who_asked_for_me); + if (0) { + } elsif ($obj->isa("CPAN::Bundle")) { + # bundles cannot specify a minimum version + return; + } elsif ($obj->isa("CPAN::Distribution")) { + if (my $prereq_pm = $obj->prereq_pm) { + for my $k (keys %$prereq_pm) { + if (my $want_version = $prereq_pm->{$k}{$self->id}) { + if (CPAN::Version->vcmp($have_version,$want_version) >= 0) { + $self->{incommandcolor} = $color; + return; + } + } + } + } + } + } + } + } else { + $self->{incommandcolor} = $color; # set me before recursion, + # so we can break it + } + if ($depth>=$CPAN::MAX_RECURSION){ $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors)); } # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1; @@ -8735,17 +8894,22 @@ sub as_glimpse { sub dslip_status { my($self) = @_; my($stat); + # development status @{$stat->{D}}{qw,i c a b R M S,} = qw,idea pre-alpha alpha beta released mature standard,; + # support level @{$stat->{S}}{qw,m d u n a,} = qw,mailing-list developer comp.lang.perl.* none abandoned,; + # language @{$stat->{L}}{qw,p c + o h,} = qw,perl C C++ other hybrid,; + # interface @{$stat->{I}}{qw,f r O p h n,} = qw,functions references+ties object-oriented pragma hybrid none,; + # public licence @{$stat->{P}}{qw,p g l b a o d r n,} = qw,Standard-Perl GPL LGPL BSD Artistic @@ -9213,11 +9377,13 @@ CPAN - query, download and build perl modules from CPAN sites Interactive mode: - perl -MCPAN -e shell; + perl -MCPAN -e shell -Batch mode: +--or-- - use CPAN; + cpan + +Basic commands: # Modules: @@ -9246,14 +9412,13 @@ Batch mode: =head1 DESCRIPTION -The CPAN module is designed to automate the make and install of perl -modules and extensions. It includes some primitive searching -capabilities and knows how to use Net::FTP or LWP (or some external -download clients) to fetch the raw data from the net. +The CPAN module automates or at least simplifies the make and install +of perl modules and extensions. It includes some primitive searching +capabilities and knows how to use Net::FTP or LWP or some external +download clients to fetch the distributions from the net. -Distributions are fetched from one or more of the mirrored CPAN -(Comprehensive Perl Archive Network) sites and unpacked in a dedicated -directory. +These are fetched from one or more of the mirrored CPAN (Comprehensive +Perl Archive Network) sites and unpacked in a dedicated directory. The CPAN module also supports the concept of named and versioned I of modules. Bundles simplify the handling of sets of @@ -9274,11 +9439,15 @@ The interactive mode is entered by running perl -MCPAN -e shell -which puts you into a readline interface. If Term::ReadKey and either -Term::ReadLine::Perl or Term::ReadLine::Gnu are installed it supports -both history and command completion. +or + + cpan + +which puts you into a readline interface. If C and +either C or C are installed +it supports both history and command completion. -Once you are on the command line, type 'h' to get a one page help +Once you are on the command line, type C to get a one page help screen and the rest should be self-explanatory. The function call C takes two optional arguments, one is the @@ -9308,7 +9477,7 @@ displayed with the rather verbose method C, but if we find more than one, we display each object with the terse method C. -=item get, make, test, install, clean modules or distributions +=item C, C, C, C, C modules or distributions These commands take any number of arguments and investigate what is necessary to perform the action. If the argument is a distribution @@ -9341,7 +9510,7 @@ has been run successfully before. Same for install runs. The C pragma may precede another command (currently: C, C, C, or C) and executes the command from scratch and tries to continue in case of some errors. See the section below on -The C and the C pragma. +the C and the C pragma. The C pragma may be used to skip the test part in the build process. @@ -9356,7 +9525,7 @@ A C command results in a being executed within the distribution file's working directory. -=item readme, perldoc, look module or distribution +=item C, C, C module or distribution C displays the README file of the associated distribution. C gets and untars (if not yet done) the distribution file, @@ -9364,9 +9533,9 @@ changes to the appropriate directory and opens a subshell process in that directory. C displays the pod documentation of the module in html or plain text format. -=item ls author +=item C author -=item ls globbing_expression +=item C globbing_expression The first form lists all distribution files in and below an author's CPAN directory as they are stored in the CHECKUMS files distributed on @@ -9386,7 +9555,7 @@ 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 and may be changed in future versions. -=item failed +=item C The C command reports all distributions that failed on one of C, C or C for some reason in the currently @@ -9585,1016 +9754,1335 @@ module or not. The typical usage case is for private modules or working copies of projects from remote repositories on the local disk. -=head1 PROGRAMMER'S INTERFACE - -If you do not enter the shell, the available shell commands are both -available as methods (Cinstall(...)>) and as -functions in the calling package (C). Before calling low-level -commands it makes sense to initialize components of CPAN you need, e.g.: - - CPAN::HandleConfig->load; - CPAN::Shell::setup_output; - CPAN::Index->reload; - -High-level commands do such initializations automatically. - -There's currently only one class that has a stable interface - -CPAN::Shell. All commands that are available in the CPAN shell are -methods of the class CPAN::Shell. Each of the commands that produce -listings of modules (C, C, C) 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 -Cexpand("Module",@things)> method. Expand returns a -list of CPAN::Module objects according to the C<@things> arguments -given. In scalar context it only returns 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"; - } +=head1 CONFIGURATION - # find out which distribution on CPAN contains a module: - print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file +When the CPAN module is used for the first time, a configuration +dialog 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. -Or if you want to write a cronjob to watch The CPAN, you could list -all modules that need updating. First a quick and dirty way: +The 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 $HOME/.cpan/CPAN/MyConfig.pm, because $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. - perl -e 'use CPAN; CPAN::Shell->r;' +The C command has various bells and whistles: -If you don't want to get any output in the case that all modules are -up to date, you can parse the output of above command for the regular -expression //modules are up to date// and decide to mail the output -only if it doesn't match. Ick? +=over -If you prefer to do it more in a programmer style in one single -process, maybe something like this suits you better: +=item completion support - # 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 you have a ReadLine module installed, you can hit TAB at any point +of the commandline and C will offer you completion for the +built-in subcommands and/or config variable names. -If that gives you too much output every day, you maybe only want to -watch for three modules. You can write +=item displaying some help: o conf help - for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")){ +Displays a short help -as the first line instead. Or you can combine some of the above -tricks: +=item displaying current values: o conf [KEY] - # 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; +Displays the current value(s) for this config variable. Without KEY +displays all subcommands and config variables. -=back +Example: -=head2 Methods in the other Classes + o conf shell -=over 4 +=item changing of scalar values: o conf KEY VALUE -=item CPAN::Author::as_glimpse() +Sets the config variable KEY to VALUE. The empty string can be +specified as usual in shells, with C<''> or C<""> -Returns a one-line description of the author +Example: -=item CPAN::Author::as_string() + o conf wget /usr/bin/wget -Returns a multi-line description of the author +=item changing of list values: o conf KEY SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST -=item CPAN::Author::email() +If a config variable name ends with C, it is a list. C removes the first element of the list, C +removes the last element of the list. C +prepends a list of values to the list, C +appends a list of valued to the list. -Returns the author's email address +Likewise, C passes the LIST to the according +splice command. -=item CPAN::Author::fullname() +Finally, any other list of arguments is taken as a new list value for +the KEY variable discarding the previous value. -Returns the author's name +Examples: -=item CPAN::Author::name() + 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 -An alias for fullname +=item reverting to saved: o conf defaults -=item CPAN::Bundle::as_glimpse() +Reverts all config variables to the state in the saved config file. -Returns a one-line description of the bundle +=item saving the config: o conf commit -=item CPAN::Bundle::as_string() +Saves all config variables to the current config file (CPAN/Config.pm +or CPAN/MyConfig.pm that was loaded at start). -Returns a multi-line description of the bundle +=back -=item CPAN::Bundle::clean() +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 +where WORD is any valid config variable or a regular expression. -Recursively runs the C method on all items contained in the bundle. +=head2 Config Variables -=item CPAN::Bundle::contains() +Currently the following keys in the hash reference $CPAN::Config are +defined: -Returns a list of objects' IDs contained in a bundle. The associated -objects may be bundles, modules or distributions. + 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 + commands_quote prefered 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 + 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 + cpan_home local directory reserved for this package + curl path to external prg + dontload_hash DEPRECATED + dontload_list arrayref: modules in the list will not be + loaded by the CPAN::has_inst() routine + ftp path to external prg + ftp_passive if set, the envariable FTP_PASSIVE is set for downloads + ftp_proxy proxy host for ftp requests + getcwd see below + gpg path to external prg + gzip location of external program gzip + 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 + never break. + index_expire after this many days refetch index files + inhibit_startup_message + if true, does not print the startup message + keep_source_where directory in which to keep the source (if we do) + 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 + 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 in any case + prerequisites_policy + what to do if you are missing module prerequisites + ('follow' automatically, 'ask' me, or 'ignore') + prefs_dir local directory to store per-distro build options + proxy_user username for accessing an authenticating proxy + proxy_pass password for accessing an authenticating proxy + randomize_urllist add some randomness to the sequence of the urllist + scan_cache controls scanning of cache ('atstart' or 'never') + shell your favorite shell + show_upload_date boolean if commands should try to determine upload date + tar location of external program tar + term_is_latin if true internal UTF-8 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) + 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 + wait_list arrayref to a wait server to try (See CPAN::WAIT) + wget path to external prg + yaml_module which module to use to read/write YAML files -=item CPAN::Bundle::force($method,@args) +You can set and query each of these options interactively in the cpan +shell with the C or the C command as specified below. -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 is passed recursively -to all contained objects. See also the section above on the C -and the C pragma. +=over 2 -=item CPAN::Bundle::get() +=item Cscalar optionE> -Recursively runs the C method on all items contained in the bundle +prints the current value of the I -=item CPAN::Bundle::inst_file() +=item Cscalar optionE EvalueE> -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. +Sets the value of the I to I -=item CPAN::Bundle::inst_version() +=item Clist optionE> -Like CPAN::Bundle::inst_file, but returns the $VERSION +prints the current value of the I in MakeMaker's +neatvalue format. -=item CPAN::Bundle::uptodate() +=item Clist optionE [shift|pop]> -Returns 1 if the bundle itself and all its members are uptodate. +shifts or pops the array in the I variable -=item CPAN::Bundle::install() +=item Clist optionE [unshift|push|splice] ElistE> -Recursively runs the C method on all items contained in the bundle +works like the corresponding perl commands. -=item CPAN::Bundle::make() +=item interactive editing: o conf init [MATCH|LIST] -Recursively runs the C method on all items contained in the bundle +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. -=item CPAN::Bundle::readme() +Examples: -Recursively runs the C method on all items contained in the bundle + o conf init ftp_passive ftp_proxy + o conf init /color/ -=item CPAN::Bundle::test() +Note: this method of setting config variables often provides more +explanation about the functioning of a variable than the manpage. -Recursively runs the C method on all items contained in the bundle +=back -=item CPAN::Distribution::as_glimpse() +=head2 CPAN::anycwd($path): Note on config variable getcwd -Returns a one-line description of the distribution +CPAN.pm changes the current working directory often and needs to +determine its own current working directory. Per default it uses +Cwd::cwd but if this doesn't work on your system for some reason, +alternatives can be configured according to the following table: -=item CPAN::Distribution::as_string() +=over 4 -Returns a multi-line description of the distribution +=item cwd -=item CPAN::Distribution::author +Calls Cwd::cwd -Returns the CPAN::Author object of the maintainer who uploaded this -distribution +=item getcwd -=item CPAN::Distribution::clean() +Calls Cwd::getcwd -Changes to the directory where the distribution has been unpacked and -runs C there. +=item fastcwd -=item CPAN::Distribution::containsmods() +Calls Cwd::fastcwd -Returns a list of IDs of modules contained in a distribution file. -Only works for distributions listed in the 02packages.details.txt.gz -file. This typically means that only the most recent version of a -distribution is covered. +=item backtickcwd -=item CPAN::Distribution::cvs_import() +Calls the external command cwd. -Changes to the directory where the distribution has been unpacked and -runs something like +=back - cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version +=head2 Note on the format of the urllist parameter -there. +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 URLs, please try the correct format. Either: -=item CPAN::Distribution::dir() + file://localhost/whatever/ftp/pub/CPAN/ -Returns the directory into which this distribution has been unpacked. +or -=item CPAN::Distribution::force($method,@args) + file:///home/ftp/pub/CPAN/ -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 and the C pragma. +=head2 The urllist parameter has CD-ROM support -=item CPAN::Distribution::get() +The C parameter of the configuration table contains a list of +URLs that are to be used for downloading. If the list contains any +C URLs, CPAN always tries to get files from 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 URL at the end of urllist, e.g. -Downloads the distribution from CPAN and unpacks it. Does nothing if -the distribution has already been downloaded and unpacked within the -current session. + o conf urllist push file://localhost/CDROM/CPAN -=item CPAN::Distribution::install() +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 if there is a local copy of the most recent version. -Changes to the directory where the distribution has been unpacked and -runs the external command C there. If C has not -yet been run, it will be run first. A C will be issued in -any case and if this fails, the install will be canceled. The -cancellation can be avoided by letting C run the C for -you. +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. -This install method has only the power to install the distribution if -there are no dependencies in the way. To install an object and all of -its dependencies, use CPAN::Shell->install. +=head2 Maintaining the urllist parameter -Note that install() gives no meaningful return value. See uptodate(). +If you have YAML.pm (or some other YAML module configured in +C) installed, CPAN.pm collects a few statistical data +about recent downloads. You can view the statistics with the C +command or inspect them directly by looking into the C +file in your C directory. -=item CPAN::Distribution::isa_perl() +To get some interesting statistics it is recommended to set the +C parameter that introduces some amount of +randomness into the URL selection. -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. +=head2 The C and C dependency declarations -=item CPAN::Distribution::look() +Since CPAN.pm version 1.88_51 modules declared as C by +a distribution are treated differently depending on the config +variable C. By setting +C to C such a module is not being +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 and C directories in the environment variable +PERL5LIB. If C is set ti C, then +both modules declared as C and those declared as +C are treated alike. By setting to C or +C, CPAN.pm asks the user and sets the default accordingly. -Changes to the directory where the distribution has been unpacked and -opens a subshell there. Exiting the subshell returns. +=head2 Configuration for individual distributions (I) -=item CPAN::Distribution::make() +(B This feature has been introduced in CPAN.pm 1.8854 and is +still considered beta quality) -First runs the C 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 or C and C there. +Distributions on the CPAN usually behave according to what we call the +CPAN mantra. Or since the event of Module::Build we should talk about +two mantras: -=item CPAN::Distribution::perldoc() + perl Makefile.PL perl Build.PL + make ./Build + make test ./Build test + make install ./Build install -Downloads the pod documentation of the file associated with a -distribution (in html format) and runs it through the external -command lynx specified in C<$CPAN::Config->{lynx}>. If lynx -isn't available, it converts it to plain text with external -command html2text and runs it through the pager specified -in C<$CPAN::Config->{pager}> +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. -=item CPAN::Distribution::prefs() +The distroprefs system of C addresses this problem by +allowing the user to specify extra informations and recipes in YAML +files to either -Returns the hash reference from the first matching YAML file that the -user has deposited in the C directory. The first -succeeding match wins. The files in the C are processed -alphabetically and the canonical distroname (e.g. -AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions -stored in the $root->{match}{distribution} attribute value. -Additionally all module names contained in a distribution are matched -agains 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 merge of the C element and the C -element of the META.yml or the C hash in the -C. Note: works only after an attempt has been made to -C the distribution. Returns undef otherwise. +=over -=item CPAN::Distribution::readme() +=item -Downloads the README file associated with a distribution and runs it -through the pager specified in C<$CPAN::Config->{pager}>. +pass additional arguments to one of the four commands, -=item CPAN::Distribution::read_yaml() +=item -Returns the content of the META.yml of this distro as a hashref. Note: -works only after an attempt has been made to C the distribution. -Returns undef otherwise. Also returns undef if the content of META.yml -is dynamic. +set environment variables -=item CPAN::Distribution::test() +=item -Changes to the directory where the distribution has been unpacked and -runs C there. +instantiate an Expect object that reads from the console, waits for +some regular expressions and enters some answers -=item CPAN::Distribution::uptodate() +=item -Returns 1 if all the modules contained in the distribution are -uptodate. Relies on containsmods. +temporarily override assorted C configuration variables -=item CPAN::Index::force_reload() +=item -Forces a reload of all indices. +disable the installation of an object altogether -=item CPAN::Index::reload() +=back -Reloads all indices if they have not been read for more than -C<$CPAN::Config->{index_expire}> days. +See the YAML and Data::Dumper files that come with the C +distribution in the C directory for examples. -=item CPAN::InfoObj::dump() +=head2 Filenames -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. +The YAML files themselves must have the C<.yml> extension, all other +files are ignored (for two exceptions see I below). The containing directory can be specified in +C in the C config variable. Try C in the CPAN shell to set and activate the distroprefs +system. -=item CPAN::Module::as_glimpse() +Every YAML file may contain arbitrary documents according to the YAML +specification and every single document is treated as an entity that +can specify the treatment of a single distribution. -Returns a one-line description of the module in four columns: The -first column contains the word C, the second column consists -of one character: an equals sign if this module is already installed -and uptodate, a less-than sign if this module is installed but can be -upgraded, and a space if the module is not installed. The third column -is the name of the module and the fourth column gives maintainer or -distribution information. +The names of the files can be picked freely, C always reads +all files (in alphabetical order) and takes the key C (see +below in I) as a hashref containing match criteria +that determine if the current distribution matches the YAML document +or not. -=item CPAN::Module::as_string() +=head2 Fallback Data::Dumper and Storable -Returns a multi-line description of the module +If neither your configured C 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 +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 -=item CPAN::Module::clean() + ysh < somefile.yml > somefile.dd -Runs a clean on the distribution associated with this module. +For Storable files the rule is that they must be constructed such that +C returns an array reference and the array +elements represent one distropref object each. The conversion from +YAML would look like so: -=item CPAN::Module::cpan_file() + perl -MYAML=LoadFile -MStorable=nstore -e ' + @y=LoadFile(shift); + nstore(\@y, shift)' somefile.yml somefile.st -Returns the filename on CPAN that is associated with the module. +In bootstrapping situations it is usually sufficient to translate only +a few YAML files to Data::Dumper for the crucial modules like +C, C and C. 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. -=item CPAN::Module::cpan_version() +=head2 Blueprint -Returns the latest version of this module available on CPAN. +The following example contains all supported keywords and structures +with the exception of C which can be used instead of +C. -=item CPAN::Module::cvs_import() + --- + comment: "Demo" + match: + module: "Dancing::Queen" + distribution: "^CHACHACHA/Dancing-" + perl: "/usr/local/cariba-perl/bin/perl" + disabled: 1 + cpanconfig: + make: gmake + pl: + args: + - "--somearg=specialcase" -Runs a cvs_import on the distribution associated with this module. + env: {} -=item CPAN::Module::description() + expect: + - "Which is your favorite fruit" + - "apple\n" -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) + make: + args: + - all + - extra-all -=item CPAN::Module::distribution() + env: {} -Returns the CPAN::Distribution object that contains the current -version of this module. + expect: [] -=item CPAN::Module::dslip_status() + commendline: "echo SKIPPING make" -Returns a hash reference. The keys of the hash are the letters C, -C, C, C, and

, 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, C, C, C, and that carry a more -verbose value of the 5 status variables. + test: + args: [] -Where the 'DSLIP' characters have the following meanings: + env: {} - 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 + expect: [] - S - Support Level: - m - Mailing-list - d - Developer - u - Usenet newsgroup comp.lang.perl.modules - n - None known, try comp.lang.perl.modules - a - abandoned; volunteers welcome to take over maintainance + install: + args: [] - 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++ + env: + WANT_TO_INSTALL: YES - 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 + expect: + - "Do you really want to install" + - "y\n" - 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 - o - open source: appoved by www.opensource.org - d - allows distribution without restrictions - r - restricted distribtion - n - no license at all + patches: + - "ABCDE/Fedcba-3.14-ABCDE-01.patch" -=item CPAN::Module::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 and the C pragma. +=head2 Language Specs -=item CPAN::Module::get() +Every YAML document represents a single hash reference. The valid keys +in this hash are as follows: -Runs a get on the distribution associated with this module. +=over -=item CPAN::Module::inst_file() +=item comment [scalar] -Returns the filename of the module found in @INC. The first file found -is reported just like perl itself stops searching @INC when it finds a -module. +A comment -=item CPAN::Module::available_file() +=item cpanconfig [hash] -Returns the filename of the module found in PERL5LIB or @INC. The -first file found is reported. The advantage of this method over -C is that modules that have been tested but not yet -installed are included because PERL5LIB keeps track of tested modules. +Temporarily override assorted C configuration variables. -=item CPAN::Module::inst_version() +Supported are: C, C, +C, C, C, +C. Please report as a bug when you need another one +supported. -Returns the version number of the installed module in readable format. +=item disabled [boolean] -=item CPAN::Module::available_version() +Specifies that this distribution shall not be processed at all. -Returns the version number of the available module in readable format. +=item goto [string] -=item CPAN::Module::install() +The canonical name of a delegate distribution that shall be installed +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. -Runs an C on the distribution associated with this module. +=item install [hash] -=item CPAN::Module::look() +Processing instructions for the C or C<./Build install> +phase of the CPAN mantra. See below under I. -Changes to the directory where the distribution associated with this -module has been unpacked and opens a subshell there. Exiting the -subshell returns. +=item make [hash] -=item CPAN::Module::make() +Processing instructions for the C or C<./Build> phase of the +CPAN mantra. See below under I. -Runs a C on the distribution associated with this module. +=item match [hash] -=item CPAN::Module::manpage_headline() +A hashref with one or more of the keys C, C, or +C that specify if a document is targeted at a specific CPAN +distribution. -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 is not installed. +The corresponding values are interpreted as regular expressions. The +C related one will be matched against the canonical +distribution name, e.g. "AUTHOR/Foo-Bar-3.14.tar.gz". -=item CPAN::Module::perldoc() +The C related one will be matched against I modules +contained in the distribution until one module matches. -Runs a C on this module. +The C related one will be matched against C<$^X>. -=item CPAN::Module::readme() +If more than one restriction of C, C, and +C is specified, the results of the separately computed match +values must all match. If this is the case then the hashref +represented by the YAML document is returned as the preference +structure for the current distribution. -Runs a C on the distribution associated with this module. +=item patches [array] -=item CPAN::Module::test() +An array of patches on CPAN or on the local disk to be applied in +order via the external patch program. If the value for the C<-p> +parameter is C<0> or C<1> is determined by reading the patch +beforehand. -Runs a C on the distribution associated with this module. +Note: if the C program is installed and C +knows about it B a patch is written by the C program, +then C lets C apply the patch. Both C +and C are available from CPAN in the C +distribution. -=item CPAN::Module::uptodate() +=item pl [hash] -Returns 1 if the module is installed and up-to-date. +Processing instructions for the C or C phase of the CPAN mantra. See below under I. -=item CPAN::Module::userid() +=item test [hash] -Returns the author's ID of the module. +Processing instructions for the C or C<./Build test> phase +of the CPAN mantra. See below under I. =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 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 Processing Instructions -=head2 Bundles +=over -A bundle is just a perl module in the namespace Bundle:: that does not -define any functions or methods. It usually only contains documentation. +=item args [array] -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 exists starting with -(verbatim): +Arguments to be added to the command line - =head1 CONTENTS +=item commandline -In this pod section each line obeys the format +A full commandline that will be executed as it stands by a system +call. During the execution the environment variable PERL will is set +to $^X. If C is specified, the content of C is not +used. - Module_Name [Version_String] [- optional text] +=item eexpect [hash] -The only required part is the first field, the name of a module -(e.g. Foo::Bar, ie. I 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. +Extended C. This is a hash reference with three allowed keys, +C, C, and C. -The distribution of a bundle should follow the same convention as -other distributions. +C may have the values C for the case where all +questions come in the order written down and C for the case +where the questions may come in any order. The default mode is +C. -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. +C denotes a timeout in seconds. Floating point timeouts are +OK. In the case of a C the timeout denotes the +timeout per question, in the case of C it denotes the +timeout per byte received from the stream or questions. -=head1 PREREQUISITES +C is a reference to an array that contains alternating questions +and answers. Questions are regular expressions and answers are literal +strings. The Expect module will then watch the stream coming from the +execution of the external program (C, C, C, etc.). -If you have a local mirror of CPAN and can access all files with -"file:" URLs, then you only need a perl better 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. +In the case of C the CPAN.pm will inject the +according answer as soon as the stream matches the regular expression. +In the case of C the CPAN.pm will answer a question as +soon as the timeout is reached for the next byte in the input stream. +In the latter case it removes the according question/answer pair from +the array, so if you want to answer the question C several times, then it must be included in the array at +least as often as you want this answer to be given. -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. +=item env [hash] -=head1 UTILITIES +Environment variables to be set during the command -=head2 Finding packages and VERSION +=item expect [array] -This module presumes that all packages on CPAN +C<< expect: >> is a short notation for -=over 2 + eexpect: + mode: deterministic + timeout: 15 + talk: -=item * +=back -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 +=head2 Schema verification with C - perl -MExtUtils::MakeMaker -le \ - 'print MM->parse_version(shift)' filename +If you have the C module installed (which is part of the +Bundle::CPANxxl), then all your distroprefs files are checked for +syntactical correctness. -If you are author of a package and wonder if your $VERSION can be -parsed, please try the above method. +=head2 Example Distroprefs Files -=item * +C 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 beend warned:-) -come as compressed or gzipped tarfiles or as zip files and contain a -C or C (well, we try to handle a bit more, but -without much enthusiasm). +=head1 PROGRAMMER'S INTERFACE -=back +If you do not enter the shell, the available shell commands are both +available as methods (Cinstall(...)>) and as +functions in the calling package (C). Before calling low-level +commands it makes sense to initialize components of CPAN you need, e.g.: -=head2 Debugging + CPAN::HandleConfig->load; + CPAN::Shell::setup_output; + CPAN::Index->reload; -The debugging of this module is a bit complex, because we have -interferences of the software producing the indices on CPAN, of the -mirroring process on CPAN, of packaging, of configuration, of -synchronicity, and of bugs within CPAN.pm. +High-level commands do such initializations automatically. -For debugging the code of CPAN.pm itself in interactive mode some more -or less useful debugging aid can be turned on for most packages within -CPAN.pm with one of +There's currently only one class that has a stable interface - +CPAN::Shell. All commands that are available in the CPAN shell are +methods of the class CPAN::Shell. Each of the commands that produce +listings of modules (C, C, C) also return a list of +the IDs of all modules within the list. =over 2 -=item o debug package... - -sets debug mode for packages. - -=item o debug -package... +=item expand($type,@things) -unsets debug mode for packages. +The IDs of all objects available within a program are strings that can +be expanded to the corresponding real objects with the +Cexpand("Module",@things)> method. Expand returns a +list of CPAN::Module objects according to the C<@things> arguments +given. In scalar context it only returns the first element of the +list. -=item o debug all +=item expandany(@things) -turns debugging on for all packages. +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 o debug number +=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 write a cronjob to watch The 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 to get any output in the case that all modules are +up to date, you can parse the output of above command for the regular +expression //modules are up to date// and decide to mail the output +only if it doesn't match. Ick? + +If you prefer to do it more in a programmer style in one single +process, maybe something like this suits you better: + + # 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 you too much output every day, you maybe only want to +watch 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 -which sets the debugging packages directly. Note that C -turns debugging off. +=head2 Methods in the other Classes -What seems quite a successful strategy is the combination of C and the debugging switches. Add a new debug statement while -running in the shell and then issue a C and see the new -debugging messages immediately without losing the current context. +=over 4 -C without an argument lists the valid package names and the -current set of packages in debugging mode. C has built-in -completion support. +=item CPAN::Author::as_glimpse() -For debugging of CPAN data there is the C 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. +Returns a one-line description of the author -=head2 Floppy, Zip, Offline Mode +=item CPAN::Author::as_string() -CPAN.pm works nicely without network too. If you maintain machines -that are not networked at all, you should consider working with file: -URLs. Of course, you 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. +Returns a multi-line description of the author -=head2 Basic Utilities for Programmers +=item CPAN::Author::email() -=over 2 +Returns the author's email address -=item has_inst($module) +=item CPAN::Author::fullname() -Returns true if the module is installed. Used to load all modules into -the running CPAN.pm which are considered optional. The config variable -C can be used to intercept the C call such -that an optional module is not loaded despite being available. For -example the following command will prevent that C is being -loaded: +Returns the author's name - cpan> o conf dontload_list push YAML +=item CPAN::Author::name() -See the source for details. +An alias for fullname -=item has_usable($module) +=item CPAN::Bundle::as_glimpse() -Returns true if the module is installed and is in a usable state. Only -useful for a handful of modules that are used internally. See the -source for details. +Returns a one-line description of the bundle -=item instance($module) +=item CPAN::Bundle::as_string() -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. +Returns a multi-line description of the bundle -=back +=item CPAN::Bundle::clean() -=head1 CONFIGURATION +Recursively runs the C method on all items contained in the bundle. -When the CPAN module is used for the first time, a configuration -dialog 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. +=item CPAN::Bundle::contains() -The 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 $HOME/.cpan/CPAN/MyConfig.pm, because $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. +Returns a list of objects' IDs contained in a bundle. The associated +objects may be bundles, modules or distributions. -The C command has various bells and whistles: +=item CPAN::Bundle::force($method,@args) -=over +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 is passed recursively +to all contained objects. See also the section above on the C +and the C pragma. -=item completion support +=item CPAN::Bundle::get() -If you have a ReadLine module installed, you can hit TAB at any point -of the commandline and C will offer you completion for the -built-in subcommands and/or config variable names. +Recursively runs the C method on all items contained in the bundle -=item displaying some help: o conf help +=item CPAN::Bundle::inst_file() -Displays a short help +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 displaying current values: o conf [KEY] +=item CPAN::Bundle::inst_version() -Displays the current value(s) for this config variable. Without KEY -displays all subcommands and config variables. +Like CPAN::Bundle::inst_file, but returns the $VERSION -Example: +=item CPAN::Bundle::uptodate() - o conf shell +Returns 1 if the bundle itself and all its members are uptodate. -=item changing of scalar values: o conf KEY VALUE +=item CPAN::Bundle::install() -Sets the config variable KEY to VALUE. The empty string can be -specified as usual in shells, with C<''> or C<""> +Recursively runs the C method on all items contained in the bundle -Example: +=item CPAN::Bundle::make() - o conf wget /usr/bin/wget +Recursively runs the C method on all items contained in the bundle -=item changing of list values: o conf KEY SHIFT|UNSHIFT|PUSH|POP|SPLICE|LIST +=item CPAN::Bundle::readme() -If a config variable name ends with C, it is a list. C removes the first element of the list, C -removes the last element of the list. C -prepends a list of values to the list, C -appends a list of valued to the list. +Recursively runs the C method on all items contained in the bundle -Likewise, C passes the LIST to the according -splice command. +=item CPAN::Bundle::test() -Finally, any other list of arguments is taken as a new list value for -the KEY variable discarding the previous value. +Recursively runs the C method on all items contained in the bundle -Examples: +=item CPAN::Distribution::as_glimpse() - 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 +Returns a one-line description of the distribution -=item interactive editing: o conf init [MATCH|LIST] +=item CPAN::Distribution::as_string() -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. +Returns a multi-line description of the distribution -Examples: +=item CPAN::Distribution::author - o conf init ftp_passive ftp_proxy - o conf init /color/ +Returns the CPAN::Author object of the maintainer who uploaded this +distribution -=item reverting to saved: o conf defaults +=item CPAN::Distribution::clean() -Reverts all config variables to the state in the saved config file. +Changes to the directory where the distribution has been unpacked and +runs C there. -=item saving the config: o conf commit +=item CPAN::Distribution::containsmods() -Saves all config variables to the current config file (CPAN/Config.pm -or CPAN/MyConfig.pm that was loaded at start). +Returns a list of IDs of modules contained in a distribution file. +Only works for distributions listed in the 02packages.details.txt.gz +file. This typically means that only the most recent version of a +distribution is covered. -=back +=item CPAN::Distribution::cvs_import() -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 -where WORD is any valid config variable or a regular expression. +Changes to the directory where the distribution has been unpacked and +runs something like -=head2 Config Variables + cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version -Currently the following keys in the hash reference $CPAN::Config are -defined: +there. - 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 - commands_quote prefered 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 - 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 - cpan_home local directory reserved for this package - curl path to external prg - dontload_hash DEPRECATED - dontload_list arrayref: modules in the list will not be - loaded by the CPAN::has_inst() routine - ftp path to external prg - ftp_passive if set, the envariable FTP_PASSIVE is set for downloads - ftp_proxy proxy host for ftp requests - getcwd see below - gpg path to external prg - gzip location of external program gzip - 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 - never break. - index_expire after this many days refetch index files - inhibit_startup_message - if true, does not print the startup message - keep_source_where directory in which to keep the source (if we do) - 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 - 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 in any case - prerequisites_policy - what to do if you are missing module prerequisites - ('follow' automatically, 'ask' me, or 'ignore') - prefs_dir local directory to store per-distro build options - proxy_user username for accessing an authenticating proxy - proxy_pass password for accessing an authenticating proxy - randomize_urllist add some randomness to the sequence of the urllist - scan_cache controls scanning of cache ('atstart' or 'never') - shell your favorite shell - show_upload_date boolean if commands should try to determine upload date - tar location of external program tar - term_is_latin if true internal UTF-8 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) - 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 - wait_list arrayref to a wait server to try (See CPAN::WAIT) - wget path to external prg - yaml_module which module to use to read/write YAML files +=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 and the C 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 there. If C has not +yet been run, it will be run first. A C will be issued in +any case and if this fails, the install will be canceled. The +cancellation can be avoided by letting C run the C for +you. + +This install method has only the power to install the distribution if +there are no dependencies in the way. To install an object and all of +its dependencies, use CPAN::Shell->install. + +Note that install() gives no meaningful return value. See uptodate(). + +=item CPAN::Distribution::install_tested() + +Install all the distributions that have been tested sucessfully but +not yet installed. See also C. + +=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::is_tested() + +List all the distributions that have been tested sucessfully but not +yet installed. See also C. + +=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 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 or C and C 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 lynx specified in C<$CPAN::Config->{lynx}>. If lynx +isn't available, it converts it to plain text with external +command 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 directory. The first +succeeding match wins. The files in the C are processed +alphabetically and the canonical distroname (e.g. +AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions +stored in the $root->{match}{distribution} attribute value. +Additionally all module names contained in a distribution are matched +agains 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 the C and C elements. These can be +declared either by the C (if authoritative) or can be +deposited after the run of C in the file C<./_build/prereqs> +or after the run of C written as the C hash in +a comment in the produced C. I: this method only works +after an attempt has been made to C 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::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 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 there. + +=item CPAN::Distribution::uptodate() + +Returns 1 if all the modules contained in the distribution are +uptodate. Relies on containsmods. + +=item CPAN::Index::force_reload() + +Forces a reload of all indices. + +=item CPAN::Index::reload() + +Reloads all indices if they have not been read for more than +C<$CPAN::Config->{index_expire}> days. + +=item CPAN::InfoObj::dump() + +CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution +inherit this method. It prints the data structure associated with an +object. Useful for debugging. Note: the data structure is considered +internal and thus subject to change without notice. + +=item CPAN::Module::as_glimpse() + +Returns a one-line description of the module in four columns: The +first column contains the word C, the second column consists +of one character: an equals sign if this module is already installed +and uptodate, a less-than sign if this module is installed but can be +upgraded, and a space if the module is not installed. The third column +is the name of the module and the fourth column gives maintainer or +distribution information. + +=item CPAN::Module::as_string() + +Returns a multi-line description of the module + +=item CPAN::Module::clean() + +Runs a clean on the distribution associated with this module. + +=item CPAN::Module::cpan_file() + +Returns the filename on CPAN that is associated with the module. + +=item CPAN::Module::cpan_version() + +Returns the latest version of this module available on CPAN. + +=item CPAN::Module::cvs_import() + +Runs a cvs_import on the distribution associated with this module. + +=item CPAN::Module::description() + +Returns a 44 character description of this module. Only available for +modules listed in The Module List (CPAN/modules/00modlist.long.html +or 00modlist.long.txt.gz) + +=item CPAN::Module::distribution() + +Returns the CPAN::Distribution object that contains the current +version of this module. + +=item CPAN::Module::dslip_status() + +Returns a hash reference. The keys of the hash are the letters C, +C, C, C, and

, 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, C, C, C, and that carry a more +verbose value of the 5 status variables. + +Where the 'DSLIP' characters have the following meanings: + + D - Development Stage (Note: *NO IMPLIED TIMESCALES*): + i - Idea, listed to gain consensus or as a placeholder + c - under construction but pre-alpha (not yet released) + a/b - Alpha/Beta testing + R - Released + M - Mature (no rigorous definition) + S - Standard, supplied with Perl 5 + + S - Support Level: + m - Mailing-list + d - Developer + u - Usenet newsgroup comp.lang.perl.modules + n - None known, try comp.lang.perl.modules + a - abandoned; volunteers welcome to take over maintainance + + L - Language Used: + p - Perl-only, no compiler needed, should be platform independent + c - C and perl, a C compiler will be needed + h - Hybrid, written in perl with optional C code, no compiler needed + + - C++ and perl, a C++ compiler will be needed + o - perl and another language other than C or C++ + + I - Interface Style + f - plain Functions, no references used + h - hybrid, object and function interfaces available + n - no interface at all (huh?) + r - some use of unblessed References or ties + O - Object oriented using blessed references and/or inheritance + + P - Public License + p - Standard-Perl: user may choose between GPL and Artistic + g - GPL: GNU General Public License + l - LGPL: "GNU Lesser General Public License" (previously known as + "GNU Library General Public License") + b - BSD: The BSD License + a - Artistic license alone + o - open source: appoved by www.opensource.org + d - allows distribution without restrictions + r - restricted distribtion + n - no license at all + +=item CPAN::Module::force($method,@args) + +Forces CPAN to perform a task 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 and the C 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 like perl itself stops searching @INC when it finds a +module. -You can set and query each of these options interactively in the cpan -shell with the command set defined within the C command: +=item CPAN::Module::available_file() -=over 2 +Returns the filename of the module found in PERL5LIB or @INC. The +first file found is reported. The advantage of this method over +C is that modules that have been tested but not yet +installed are included because PERL5LIB keeps track of tested modules. -=item Cscalar optionE> +=item CPAN::Module::inst_version() -prints the current value of the I +Returns the version number of the installed module in readable format. -=item Cscalar optionE EvalueE> +=item CPAN::Module::available_version() -Sets the value of the I to I +Returns the version number of the available module in readable format. -=item Clist optionE> +=item CPAN::Module::install() -prints the current value of the I in MakeMaker's -neatvalue format. +Runs an C on the distribution associated with this module. -=item Clist optionE [shift|pop]> +=item CPAN::Module::look() -shifts or pops the array in the I variable +Changes to the directory where the distribution associated with this +module has been unpacked and opens a subshell there. Exiting the +subshell returns. -=item Clist optionE [unshift|push|splice] ElistE> +=item CPAN::Module::make() -works like the corresponding perl commands. +Runs a C 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 is not installed. + +=item CPAN::Module::perldoc() + +Runs a C on this module. + +=item CPAN::Module::readme() + +Runs a C on the distribution associated with this module. + +=item CPAN::Module::test() + +Runs a C 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 CPAN::anycwd($path): Note on config variable getcwd +=head2 Cache Manager -CPAN.pm changes the current working directory often and needs to -determine its own current working directory. Per default it uses -Cwd::cwd but if this doesn't work on your system for some reason, -alternatives can be configured according to the following table: +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 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 exists starting with +(verbatim): + + =head1 CONTENTS + +In this pod section each line obeys the format + + Module_Name [Version_String] [- optional text] + +The only required part is the first field, the name of a module +(e.g. Foo::Bar, ie. I 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 + +If you have a local mirror of CPAN and can access all files with +"file:" URLs, then you only need a perl better 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. + +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 cwd +=item * -Calls Cwd::cwd +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 -=item getcwd + perl -MExtUtils::MakeMaker -le \ + 'print MM->parse_version(shift)' filename -Calls Cwd::getcwd +If you are author of a package and wonder if your $VERSION can be +parsed, please try the above method. -=item fastcwd +=item * -Calls Cwd::fastcwd +come as compressed or gzipped tarfiles or as zip files and contain a +C or C (well, we try to handle a bit more, but +without much enthusiasm). -=item backtickcwd +=back -Calls the external command cwd. +=head2 Debugging + +The debugging of this module is a bit complex, because we have +interferences of the software producing the indices on CPAN, of the +mirroring process on CPAN, of packaging, of configuration, of +synchronicity, and of bugs within CPAN.pm. + +For debugging the code of CPAN.pm itself in interactive mode some more +or less useful 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 -=head2 Note on the format of the urllist parameter +which sets the debugging packages directly. Note that C +turns debugging off. -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 URLs, please try the correct format. Either: +What seems quite a successful strategy is the combination of C and the debugging switches. Add a new debug statement while +running in the shell and then issue a C and see the new +debugging messages immediately without losing the current context. - file://localhost/whatever/ftp/pub/CPAN/ +C without an argument lists the valid package names and the +current set of packages in debugging mode. C has built-in +completion support. -or +For debugging of CPAN data there is the C 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. - file:///home/ftp/pub/CPAN/ +=head2 Floppy, Zip, Offline Mode -=head2 urllist parameter has CD-ROM support +CPAN.pm works nicely without network too. If you maintain machines +that are not networked at all, you should consider working with file: +URLs. Of course, you 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. -The C parameter of the configuration table contains a list of -URLs that are to be used for downloading. If the list contains any -C URLs, CPAN always tries to get files from 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 URL at the end of urllist, e.g. +=head2 Basic Utilities for Programmers - o conf urllist push file://localhost/CDROM/CPAN +=over 2 -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 if there is a local copy of the most recent version. +=item has_inst($module) -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. +Returns true if the module is installed. Used to load all modules into +the running CPAN.pm which are considered optional. The config variable +C can be used to intercept the C call such +that an optional module is not loaded despite being available. For +example the following command will prevent that C is being +loaded: -=head2 Maintaining the urllist parameter + cpan> o conf dontload_list push YAML -If you have YAML.pm (or some other YAML module configured in -C) installed, CPAN.pm collects a few statistical data -about recent downloads. You can view the statistics with the C -command or inspect them directly by looking into the C -file in your C directory. +See the source for details. -To get some interesting statistics it is recommended to set the -C parameter that introduces some amount of -randomness into the URL selection. +=item has_usable($module) + +Returns true if the module is installed and is in a usable state. Only +useful for a handful of modules that are used internally. See the +source for details. -=head2 prefs_dir for avoiding interactive questions (ALPHA) +=item instance($module) -(B This feature has been introduced in CPAN.pm 1.8854 and is -still considered experimental and may still be changed) - -The files in the directory specified in C are YAML files -that specify how CPAN.pm shall treat distributions that deviate from -the normal non-interactive model of building and installing CPAN -modules. - -Some modules try to get some data from the user interactively thus -disturbing the installation of large bundles like Phalanx100 or -modules like Plagger. - -CPAN.pm can use YAML files to either pass additional arguments to one -of the four commands, set environment variables or instantiate an -Expect object that reads from the console and enters answers on your -behalf (latter option requires Expect.pm installed). A further option -is to apply patches from the local disk or from CPAN. - -CPAN.pm comes with a couple of such YAML files. The structure is -currently not documented because in flux. Please see the distroprefs -directory of the CPAN distribution for examples and follow the -C<00.README> file in there. - -Please note that setting the environment variable PERL_MM_USE_DEFAULT -to a true value can also get you a long way if you want to always pick -the default answers. But this only works if the author of a package -used the prompt function provided by ExtUtils::MakeMaker and if the -defaults are OK for you. +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 diff --git a/lib/CPAN/FirstTime.pm b/lib/CPAN/FirstTime.pm index 8b412ab..06fe076 100644 --- a/lib/CPAN/FirstTime.pm +++ b/lib/CPAN/FirstTime.pm @@ -19,7 +19,7 @@ use File::Basename (); use File::Path (); use File::Spec (); use vars qw($VERSION $urllist); -$VERSION = sprintf "%.6f", substr(q$Rev: 1457 $,4)/1000000 + 5.4; +$VERSION = sprintf "%.6f", substr(q$Rev: 1536 $,4)/1000000 + 5.4; =head1 NAME @@ -58,6 +58,13 @@ sub init { $CPAN::Frontend->mysleep(2); } } elsif (0 == length $matcher) { + } elsif (0 && $matcher eq "~") { # extremely buggy, but a nice idea + my @unconfigured = grep { not exists $CPAN::Config->{$_} + or not defined $CPAN::Config->{$_} + or not length $CPAN::Config->{$_} + } keys %$CPAN::Config; + $matcher = "\\b(".join("|", @unconfigured).")\\b"; + $CPAN::Frontend->mywarn("matcher[$matcher]"); } else { # case WORD... => all arguments must be valid for my $arg (@{$args{args}}) { @@ -318,6 +325,11 @@ Shall we use it as the general CPAN build and cache directory? # if (!$matcher or "yaml_module" =~ /$matcher/) { my_dflt_prompt(yaml_module => "YAML", $matcher); + unless ($CPAN::META->has_inst($CPAN::Config->{yaml_module})) { + $CPAN::Frontend->mywarn + ("Warning (maybe harmless): '$CPAN::Config->{yaml_module}' not installed.\n"); + $CPAN::Frontend->mysleep(3); + } } # @@ -1489,7 +1501,7 @@ At the time of this writing there are two competing YAML modules, YAML.pm and YAML::Syck. The latter is faster but needs a C compiler installed on your system. There may be more alternative YAML conforming modules but at the time of writing a potential third -player, YAML::Tiny, is not yet sufficiently similar to the other two. +player, YAML::Tiny, seemed not powerful enough to work with CPAN.pm. }, diff --git a/lib/CPAN/HandleConfig.pm b/lib/CPAN/HandleConfig.pm index e8859fc..d4495ef 100644 --- a/lib/CPAN/HandleConfig.pm +++ b/lib/CPAN/HandleConfig.pm @@ -2,7 +2,7 @@ package CPAN::HandleConfig; use strict; use vars qw(%can %keys $VERSION); -$VERSION = sprintf "%.6f", substr(q$Rev: 1467 $,4)/1000000 + 5.4; +$VERSION = sprintf "%.6f", substr(q$Rev: 1566 $,4)/1000000 + 5.4; %can = ( commit => "Commit changes to disk", @@ -171,6 +171,7 @@ sub edit { # reset the cached values undef $CPAN::FTP::Thesite; undef $CPAN::FTP::Themethod; + $CPAN::Index::LAST_TIME = 0; } elsif ($o eq "dontload_list") { # empty it, it will be built up again $CPAN::META->{dontload_hash} = {}; @@ -684,7 +685,7 @@ sub prefs_lookup { use strict; use vars qw($AUTOLOAD $VERSION); - $VERSION = sprintf "%.2f", substr(q$Rev: 1467 $,4)/100; + $VERSION = sprintf "%.2f", substr(q$Rev: 1566 $,4)/100; # formerly CPAN::HandleConfig was known as CPAN::Config sub AUTOLOAD { diff --git a/lib/CPAN/Queue.pm b/lib/CPAN/Queue.pm index 7cbff38..fa70c68 100644 --- a/lib/CPAN/Queue.pm +++ b/lib/CPAN/Queue.pm @@ -48,7 +48,7 @@ use strict; # Hope that makes sense, my head is a bit off:-) -- AK use vars qw{ @All $VERSION }; -$VERSION = sprintf "%.6f", substr(q$Rev: 979 $,4)/1000000 + 5.4; +$VERSION = sprintf "%.6f", substr(q$Rev: 1486 $,4)/1000000 + 5.4; # CPAN::Queue::new ; sub new { @@ -117,13 +117,15 @@ sub jumpqueue { # CPAN->debug("i[$i]this[$All[$i]{qmod}]what[$what]") if $CPAN::DEBUG; if ($All[$i]{qmod} eq $what){ $jumped++; - if ($jumped > 100) { # one's OK if e.g. just - # processing now; more are OK if - # user typed it several times + if ($jumped > 25) { # one's OK if e.g. just processing + # now; more are OK if user typed + # it several times + my $sleep = sprintf "%.1f", $jumped/10; $CPAN::Frontend->mywarn( -qq{Object [$what] queued more than 100 times, ignoring} +qq{Warning: Object [$what] queued $jumped times, sleeping $sleep secs!\n} ); - next WHAT; + $CPAN::Frontend->mysleep($sleep); + # next WHAT; } } } diff --git a/lib/CPAN/Tarzip.pm b/lib/CPAN/Tarzip.pm index 071c0b9..e637e3e 100644 --- a/lib/CPAN/Tarzip.pm +++ b/lib/CPAN/Tarzip.pm @@ -4,7 +4,7 @@ use strict; use vars qw($VERSION @ISA $BUGHUNTING); use CPAN::Debug; use File::Basename (); -$VERSION = sprintf "%.6f", substr(q$Rev: 1301 $,4)/1000000 + 5.4; +$VERSION = sprintf "%.6f", substr(q$Rev: 1525 $,4)/1000000 + 5.4; # module is internal to CPAN.pm @ISA = qw(CPAN::Debug); @@ -210,7 +210,7 @@ sub untar { # should be default until Archive::Tar handles bzip2 $prefer = 1; } elsif ( - $CPAN::META->has_inst("Archive::Tar") + $CPAN::META->has_usable("Archive::Tar") && $CPAN::META->has_inst("Compress::Zlib") ) { $prefer = 2; @@ -257,7 +257,7 @@ installed. Can't continue. return 1; } } elsif ($prefer==2) { # 2 => modules - unless ($CPAN::META->has_inst("Archive::Tar")) { + unless ($CPAN::META->has_usable("Archive::Tar")) { $CPAN::Frontend->mydie("Archive::Tar not installed, please install it to continue"); } my $tar = Archive::Tar->new($file,1);