# -*- 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;
$AUTOLOAD
$Be_Silent
$CONFIG_DIRTY
- $DEBUG
$Defaultdocs
$Defaultrecent
$Frontend
$GOTOSHELL
$HAS_USABLE
$Have_warned
+ $MAX_RECURSION
$META
$RUN_DEGRADED
$Signal
@EXPORT
);
+$MAX_RECURSION = 32;
+
@CPAN::ISA = qw(CPAN::Debug Exporter);
# note that these functions live in CPAN::Shell and get executed via
get
install
install_tested
+ is_tested
make
mkmyconfig
notest
$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;
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 = <FH>;
+ 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");
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",$@);
clean
cvs_import
dump
+ failed
force
fforce
hosts
install
install_tested
+ is_tested
look
ls
make
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;
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) {
}
},
],
+ '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}}) {
$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{
$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) = @_;
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;
$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};
}
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}));
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 }.
$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;
"CPAN/Kwalify.pm",
"CPAN/Queue.pm",
"CPAN/Reporter.pm",
+ "CPAN/SQLite.pm",
"CPAN/Tarzip.pm",
"CPAN/Version.pm",
);
# re-run (as documented)
}
-# experimental (compare with _is_tested)
+# compare with is_tested
#-> sub CPAN::Shell::install_tested
sub install_tested {
my($self,@some) = @_;
$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;
}
}
-# 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}) {
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,
#-> sub CPAN::Shell::mysleep ;
sub mysleep {
my($self, $sleep) = @_;
+ use Time::HiRes qw(sleep);
sleep $sleep;
}
# 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) {
}
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))) {
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
}
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);
+ }
}
}
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")) {
# 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}}
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;
$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;
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;
# 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;
# 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;
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";
}
# 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
}
return $self->{prefs};
}
}
- return +{};
+ $self->{negative_prefs_cache} = $CPAN::CurrentCommandId;
+ return $self->{prefs} = +{};
}
# CPAN::Distribution::make_x_arg
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);
{
# 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);
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;
}
}
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;
}
# cannot read YAML's own
# META.yml
}
+ # not "authoritative"
if (not exists $self->{yaml_content}{dynamic_config}
or $self->{yaml_content}{dynamic_config}
) {
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
# 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;
}
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}) {
) 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};
} 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) {
# 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.
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;
# 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;
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';
- }
}
}
# 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;
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
Interactive mode:
- perl -MCPAN -e shell;
+ perl -MCPAN -e shell
-Batch mode:
+--or--
- use CPAN;
+ cpan
+
+Basic commands:
# Modules:
=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<bundles> of modules. Bundles simplify the handling of sets of
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<Term::ReadKey> and
+either C<Term::ReadLine::Perl> or C<Term::ReadLine::Gnu> 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<h> to get a one page help
screen and the rest should be self-explanatory.
The function call C<shell> takes two optional arguments, one is the
more than one, we display each object with the terse method
C<as_glimpse>.
-=item get, make, test, install, clean modules or distributions
+=item C<get>, C<make>, C<test>, C<install>, C<clean> modules or distributions
These commands take any number of arguments and investigate what is
necessary to perform the action. If the argument is a distribution
The C<force> pragma may precede another command (currently: C<get>,
C<make>, C<test>, or C<install>) and executes the command from scratch
and tries to continue in case of some errors. See the section below on
-The C<force> and the C<fforce> pragma.
+the C<force> and the C<fforce> pragma.
The C<notest> pragma may be used to skip the test part in the build
process.
being executed within the distribution file's working directory.
-=item readme, perldoc, look module or distribution
+=item C<readme>, C<perldoc>, C<look> module or distribution
C<readme> displays the README file of the associated distribution.
C<Look> gets and untars (if not yet done) the distribution file,
that directory. C<perldoc> displays the pod documentation of the
module in html or plain text format.
-=item ls author
+=item C<ls> author
-=item ls globbing_expression
+=item C<ls> 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
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<failed>
The C<failed> command reports all distributions that failed on one of
C<make>, C<test> or C<install> for some reason in the currently
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 (C<CPAN::Shell-E<gt>install(...)>) and as
-functions in the calling package (C<install(...)>). Before calling low-level
-commands it makes sense to initialize components of CPAN you need, e.g.:
-
- CPAN::HandleConfig->load;
- CPAN::Shell::setup_output;
- CPAN::Index->reload;
-
-High-level commands do such initializations automatically.
-
-There's currently only one class that has a stable interface -
-CPAN::Shell. All commands that are available in the CPAN shell are
-methods of the class CPAN::Shell. Each of the commands that produce
-listings of modules (C<r>, C<autobundle>, C<u>) also return a list of
-the IDs of all modules within the list.
-
-=over 2
-
-=item expand($type,@things)
-
-The IDs of all objects available within a program are strings that can
-be expanded to the corresponding real objects with the
-C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a
-list of CPAN::Module objects according to the C<@things> arguments
-given. In scalar context it 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<o conf> 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<o conf> 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<list>, it is a list. C<o conf
+KEY shift> removes the first element of the list, C<o conf KEY pop>
+removes the last element of the list. C<o conf KEYS unshift LIST>
+prepends a list of values to the list, C<o conf KEYS push LIST>
+appends a list of valued to the list.
-Returns the author's email address
+Likewise, C<o conf KEY splice LIST> 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<o conf init WORD>
+where WORD is any valid config variable or a regular expression.
-Recursively runs the C<clean> 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<o conf> or the C<o conf init> 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<force> is passed recursively
-to all contained objects. See also the section above on the C<force>
-and the C<fforce> pragma.
+=over 2
-=item CPAN::Bundle::get()
+=item C<o conf E<lt>scalar optionE<gt>>
-Recursively runs the C<get> method on all items contained in the bundle
+prints the current value of the I<scalar option>
-=item CPAN::Bundle::inst_file()
+=item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>>
-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<scalar option> to I<value>
-=item CPAN::Bundle::inst_version()
+=item C<o conf E<lt>list optionE<gt>>
-Like CPAN::Bundle::inst_file, but returns the $VERSION
+prints the current value of the I<list option> in MakeMaker's
+neatvalue format.
-=item CPAN::Bundle::uptodate()
+=item C<o conf E<lt>list optionE<gt> [shift|pop]>
-Returns 1 if the bundle itself and all its members are uptodate.
+shifts or pops the array in the I<list option> variable
-=item CPAN::Bundle::install()
+=item C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>>
-Recursively runs the C<install> 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<make> 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<readme> 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<test> 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<make clean> 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<file> 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<force> and the C<fforce> pragma.
+=head2 The urllist parameter has CD-ROM support
-=item CPAN::Distribution::get()
+The C<urllist> parameter of the configuration table contains a list of
+URLs that are to be used for downloading. If the list contains any
+C<file> 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<file> 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<make install> there. If C<make> has not
-yet been run, it will be run first. A C<make test> will be issued in
-any case and if this fails, the install will be canceled. The
-cancellation can be avoided by letting C<force> run the C<install> 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<yaml_module>) installed, CPAN.pm collects a few statistical data
+about recent downloads. You can view the statistics with the C<hosts>
+command or inspect them directly by looking into the C<FTPstats.yml>
+file in your C<cpan_home> directory.
-=item CPAN::Distribution::isa_perl()
+To get some interesting statistics it is recommended to set the
+C<randomize_urllist> 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<requires> and C<build_requires> dependency declarations
-=item CPAN::Distribution::look()
+Since CPAN.pm version 1.88_51 modules declared as C<build_requires> by
+a distribution are treated differently depending on the config
+variable C<build_requires_install_policy>. By setting
+C<build_requires_install_policy> to C<no> such a module is not 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<blib/arch> and C<blib/lib> directories in the environment variable
+PERL5LIB. If C<build_requires_install_policy> is set ti C<yes>, then
+both modules declared as C<requires> and those declared as
+C<build_requires> are treated alike. By setting to C<ask/yes> or
+C<ask/no>, CPAN.pm asks the user and sets the default accordingly.
-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<Distroprefs>)
-=item CPAN::Distribution::make()
+(B<Note:> This feature has been introduced in CPAN.pm 1.8854 and is
+still considered beta quality)
-First runs the C<get> method to make sure the distribution is
-downloaded and unpacked. Changes to the directory where the
-distribution has been unpacked and runs the external commands C<perl
-Makefile.PL> or C<perl Build.PL> and C<make> there.
+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<CPAN.pm> 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<prefs_dir/> directory. The first
-succeeding match wins. The files in the C<prefs_dir/> are processed
-alphabetically and the canonical distroname (e.g.
-AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions
-stored in the $root->{match}{distribution} attribute value.
-Additionally all module names contained in a distribution are matched
-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<requires> element and the C<build_requires>
-element of the META.yml or the C<PREREQ_PM> hash in the
-C<Makefile.PL>. Note: works only after an attempt has been made to
-C<make> 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<make> 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<make test> 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<CPAN.pm> 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<CPAN.pm>
+distribution in the C<distroprefs/> 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<Fallback Data::Dumper and
+Storable> below). The containing directory can be specified in
+C<CPAN.pm> in the C<prefs_dir> config variable. Try C<o conf init
+prefs_dir> in the CPAN shell to set and activate the distroprefs
+system.
-=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<Module>, the second column consists
-of one character: an equals sign if this module is already installed
-and uptodate, a less-than sign if this module is installed but can be
-upgraded, and a space if the module is not installed. The third column
-is the name of the module and the fourth column gives maintainer or
-distribution information.
+The names of the files can be picked freely, C<CPAN.pm> always reads
+all files (in alphabetical order) and takes the key C<match> (see
+below in I<Language Specs>) as a hashref containing match criteria
+that determine if the current distribution matches the YAML document
+or not.
-=item CPAN::Module::as_string()
+=head2 Fallback Data::Dumper and Storable
-Returns a multi-line description of the module
+If neither your configured C<yaml_module> nor YAML.pm is installed
+CPAN.pm falls back to using Data::Dumper and Storable and looks for
+files with the extensions C<.dd> or C<.st> in the C<prefs_dir>
+directory. These files are expected to contain one or more hashrefs.
+For Data::Dumper generated files, this is expected to be done with by
+defining C<$VAR1>, C<$VAR2>, etc. The YAML shell would produce these
+with the command
-=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<Storable::retrieve(file)> 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<YAML::Syck>, C<YAML.pm> and C<Expect.pm>. If you prefer Storable
+over Data::Dumper, remember to pull out a Storable version that writes
+an older format than all the other Storable versions that will need to
+read them.
-=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<eexpect> which can be used instead of
+C<expect>.
-=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<D>,
-C<S>, C<L>, C<I>, and <P>, for development status, support level,
-language, interface and public licence respectively. The data for the
-DSLIP status are collected by pause.perl.org when authors register
-their namespaces. The values of the 5 hash elements are one-character
-words whose meaning is described in the table below. There are also 5
-hash elements C<DV>, C<SV>, C<LV>, C<IV>, and <PV> that carry a more
-verbose value of the 5 status variables.
+ 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<force> and the C<fforce> 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<inst_file> is that modules that have been tested but not yet
-installed are included because PERL5LIB keeps track of tested modules.
+Temporarily override assorted C<CPAN.pm> configuration variables.
-=item CPAN::Module::inst_version()
+Supported are: C<build_requires_install_policy>, C<check_sigs>,
+C<make>, C<make_install_make_command>, C<prefer_installer>,
+C<test_report>. Please report as a bug when you need another one
+supported.
-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<install> on the distribution associated with this module.
+=item install [hash]
-=item CPAN::Module::look()
+Processing instructions for the C<make install> or C<./Build install>
+phase of the CPAN mantra. See below under I<Processiong Instructions>.
-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<make> or C<./Build> phase of the
+CPAN mantra. See below under I<Processiong Instructions>.
-Runs a C<make> 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<distribution>, C<modules>, or
+C<perl> 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<distribution> 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<module> related one will be matched against I<all> modules
+contained in the distribution until one module matches.
-Runs a C<perldoc> on this module.
+The C<perl> related one will be matched against C<$^X>.
-=item CPAN::Module::readme()
+If more than one restriction of C<module>, C<distribution>, and
+C<perl> 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<readme> 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<test> on the distribution associated with this module.
+Note: if the C<applypatch> program is installed and C<CPAN::Config>
+knows about it B<and> a patch is written by the C<makepatch> program,
+then C<CPAN.pm> lets C<applypatch> apply the patch. Both C<makepatch>
+and C<applypatch> are available from CPAN in the C<JV/makepatch-*>
+distribution.
-=item CPAN::Module::uptodate()
+=item pl [hash]
-Returns 1 if the module is installed and up-to-date.
+Processing instructions for the C<perl Makefile.PL> or C<perl
+Build.PL> phase of the CPAN mantra. See below under I<Processiong
+Instructions>.
-=item CPAN::Module::userid()
+=item test [hash]
-Returns the author's ID of the module.
+Processing instructions for the C<make test> or C<./Build test> phase
+of the CPAN mantra. See below under I<Processiong Instructions>.
=back
-=head2 Cache Manager
-
-Currently the cache manager only keeps track of the build directory
-($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that
-deletes complete directories below C<build_dir> as soon as the size of
-all directories there gets bigger than $CPAN::Config->{build_cache}
-(in MB). The contents of this cache may be used for later
-re-installations that you intend to do manually, but will never be
-trusted by CPAN itself. This is due to the fact that the user might
-use these directories for building modules on different architectures.
-
-There is another directory ($CPAN::Config->{keep_source_where}) where
-the original distribution files are kept. This directory is not
-covered by the cache manager and must be controlled by the user. If
-you choose to have the same directory as build_dir and as
-keep_source_where directory, then your sources will be deleted with
-the same fifo mechanism.
+=head2 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<one special pod section> 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<commandline> is specified, the content of C<args> 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<not> the name of the distribution file). The rest
-of the line is optional. The comment part is delimited by a dash just
-as in the man page header.
+Extended C<expect>. This is a hash reference with three allowed keys,
+C<mode>, C<timeout>, and C<talk>.
-The distribution of a bundle should follow the same convention as
-other distributions.
+C<mode> may have the values C<deterministic> for the case where all
+questions come in the order written down and C<anyorder> for the case
+where the questions may come in any order. The default mode is
+C<deterministic>.
-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<timeout> denotes a timeout in seconds. Floating point timeouts are
+OK. In the case of a C<mode=deterministic> the timeout denotes the
+timeout per question, in the case of C<mode=anyorder> it denotes the
+timeout per byte received from the stream or questions.
-=head1 PREREQUISITES
+C<talk> is a reference to an array that contains alternating questions
+and answers. Questions are regular expressions and answers are literal
+strings. The Expect module will then watch the stream coming from the
+execution of the external program (C<perl Makefile.PL>, C<perl
+Build.PL>, C<make>, 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<ftp:>.
+In the case of C<mode=deterministic> the CPAN.pm will inject the
+according answer as soon as the stream matches the regular expression.
+In the case of C<mode=anyorder> 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<Do you really want
+to do that> several times, then it must be included in the array at
+least as often as you want this answer to be given.
-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: <array> >> is a short notation for
-=over 2
+ eexpect:
+ mode: deterministic
+ timeout: 15
+ talk: <array>
-=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<Kwalify>
- perl -MExtUtils::MakeMaker -le \
- 'print MM->parse_version(shift)' filename
+If you have the C<Kwalify> 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<CPAN.pm> comes with a collection of example YAML files. Note that these
+are really just examples and should not be used without care because
+they cannot fit everybody's purpose. After all the authors of the
+packages that ask questions had a need to ask, so you should watch
+their questions and adjust the examples to your environment and your
+needs. You have beend warned:-)
-come as compressed or gzipped tarfiles or as zip files and contain a
-C<Makefile.PL> or C<Build.PL> (well, we try to handle a bit more, but
-without much enthusiasm).
+=head1 PROGRAMMER'S INTERFACE
-=back
+If you do not enter the shell, the available shell commands are both
+available as methods (C<CPAN::Shell-E<gt>install(...)>) and as
+functions in the calling package (C<install(...)>). Before calling low-level
+commands it makes sense to initialize components of CPAN you need, e.g.:
-=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<r>, C<autobundle>, C<u>) 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
+C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a
+list of CPAN::Module objects according to the C<@things> arguments
+given. In scalar context it 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<o debug 0>
-turns debugging off.
+=head2 Methods in the other Classes
-What seems quite a successful strategy is the combination of C<reload
-cpan> and the debugging switches. Add a new debug statement while
-running in the shell and then issue a C<reload cpan> and see the new
-debugging messages immediately without losing the current context.
+=over 4
-C<o debug> without an argument lists the valid package names and the
-current set of packages in debugging mode. C<o debug> has built-in
-completion support.
+=item CPAN::Author::as_glimpse()
-For debugging of CPAN data there is the C<dump> command which takes
-the same arguments as make/test/install and outputs each object's
-Data::Dumper dump. If an argument looks like a perl variable and
-contains one of C<$>, C<@> or C<%>, it is eval()ed and fed to
-Data::Dumper directly.
+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<dontload_list> can be used to intercept the C<has_inst()> call such
-that an optional module is not loaded despite being available. For
-example the following command will prevent that C<YAML.pm> 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<clean> 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<o conf> 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<force> is passed recursively
+to all contained objects. See also the section above on the C<force>
+and the C<fforce> 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<o conf> will offer you completion for the
-built-in subcommands and/or config variable names.
+Recursively runs the C<get> 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<install> method on all items contained in the bundle
-Example:
+=item CPAN::Bundle::make()
- o conf wget /usr/bin/wget
+Recursively runs the C<make> 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<list>, it is a list. C<o conf
-KEY shift> removes the first element of the list, C<o conf KEY pop>
-removes the last element of the list. C<o conf KEYS unshift LIST>
-prepends a list of values to the list, C<o conf KEYS push LIST>
-appends a list of valued to the list.
+Recursively runs the C<readme> method on all items contained in the bundle
-Likewise, C<o conf KEY splice LIST> 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<test> 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<make clean> 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<o conf init WORD>
-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<force> and the C<fforce> pragma.
+
+=item CPAN::Distribution::get()
+
+Downloads the distribution from CPAN and unpacks it. Does nothing if
+the distribution has already been downloaded and unpacked within the
+current session.
+
+=item CPAN::Distribution::install()
+
+Changes to the directory where the distribution has been unpacked and
+runs the external command C<make install> there. If C<make> has not
+yet been run, it will be run first. A C<make test> will be issued in
+any case and if this fails, the install will be canceled. The
+cancellation can be avoided by letting C<force> run the C<install> 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<is_tested>.
+
+=item CPAN::Distribution::isa_perl()
+
+Returns 1 if this distribution file seems to be a perl distribution.
+Normally this is derived from the file name only, but the index from
+CPAN can contain a hint to achieve a return value of true for other
+filenames too.
+
+=item CPAN::Distribution::is_tested()
+
+List all the distributions that have been tested sucessfully but not
+yet installed. See also C<install_tested>.
+
+=item CPAN::Distribution::look()
+
+Changes to the directory where the distribution has been unpacked and
+opens a subshell there. Exiting the subshell returns.
+
+=item CPAN::Distribution::make()
+
+First runs the C<get> method to make sure the distribution is
+downloaded and unpacked. Changes to the directory where the
+distribution has been unpacked and runs the external commands C<perl
+Makefile.PL> or C<perl Build.PL> and C<make> there.
+
+=item CPAN::Distribution::perldoc()
+
+Downloads the pod documentation of the file associated with a
+distribution (in html format) and runs it through the external
+command 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<prefs_dir/> directory. The first
+succeeding match wins. The files in the C<prefs_dir/> are processed
+alphabetically and the canonical distroname (e.g.
+AUTHOR/Foo-Bar-3.14.tar.gz) is matched against the regular expressions
+stored in the $root->{match}{distribution} attribute value.
+Additionally all module names contained in a distribution are matched
+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<requires> and C<build_requires> elements. These can be
+declared either by the C<META.yml> (if authoritative) or can be
+deposited after the run of C<Build.PL> in the file C<./_build/prereqs>
+or after the run of C<Makfile.PL> written as the C<PREREQ_PM> hash in
+a comment in the produced C<Makefile>. I<Note>: this method only works
+after an attempt has been made to C<make> the distribution. Returns
+undef otherwise.
+
+=item CPAN::Distribution::readme()
+
+Downloads the README file associated with a distribution and runs it
+through the pager specified in C<$CPAN::Config->{pager}>.
+
+=item CPAN::Distribution::read_yaml()
+
+Returns the content of the META.yml of this distro as a hashref. Note:
+works only after an attempt has been made to C<make> the distribution.
+Returns undef otherwise. Also returns undef if the content of META.yml
+is not authoritative. (The rules about what exactly makes the content
+authoritative are still in flux.)
+
+=item CPAN::Distribution::test()
+
+Changes to the directory where the distribution has been unpacked and
+runs C<make test> there.
+
+=item CPAN::Distribution::uptodate()
+
+Returns 1 if all the modules contained in the distribution are
+uptodate. Relies on containsmods.
+
+=item CPAN::Index::force_reload()
+
+Forces a reload of all indices.
+
+=item CPAN::Index::reload()
+
+Reloads all indices if they have not been read for more than
+C<$CPAN::Config->{index_expire}> days.
+
+=item CPAN::InfoObj::dump()
+
+CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution
+inherit this method. It prints the data structure associated with an
+object. Useful for debugging. Note: the data structure is considered
+internal and thus subject to change without notice.
+
+=item CPAN::Module::as_glimpse()
+
+Returns a one-line description of the module in four columns: The
+first column contains the word C<Module>, the second column consists
+of one character: an equals sign if this module is already installed
+and uptodate, a less-than sign if this module is installed but can be
+upgraded, and a space if the module is not installed. The third column
+is the name of the module and the fourth column gives maintainer or
+distribution information.
+
+=item CPAN::Module::as_string()
+
+Returns a multi-line description of the module
+
+=item CPAN::Module::clean()
+
+Runs a clean on the distribution associated with this module.
+
+=item CPAN::Module::cpan_file()
+
+Returns the filename on CPAN that is associated with the module.
+
+=item CPAN::Module::cpan_version()
+
+Returns the latest version of this module available on CPAN.
+
+=item CPAN::Module::cvs_import()
+
+Runs a cvs_import on the distribution associated with this module.
+
+=item CPAN::Module::description()
+
+Returns a 44 character description of this module. Only available for
+modules listed in The Module List (CPAN/modules/00modlist.long.html
+or 00modlist.long.txt.gz)
+
+=item CPAN::Module::distribution()
+
+Returns the CPAN::Distribution object that contains the current
+version of this module.
+
+=item CPAN::Module::dslip_status()
+
+Returns a hash reference. The keys of the hash are the letters C<D>,
+C<S>, C<L>, C<I>, and <P>, for development status, support level,
+language, interface and public licence respectively. The data for the
+DSLIP status are collected by pause.perl.org when authors register
+their namespaces. The values of the 5 hash elements are one-character
+words whose meaning is described in the table below. There are also 5
+hash elements C<DV>, C<SV>, C<LV>, C<IV>, and <PV> that carry a more
+verbose value of the 5 status variables.
+
+Where the 'DSLIP' characters have the following meanings:
+
+ D - Development Stage (Note: *NO IMPLIED TIMESCALES*):
+ i - Idea, listed to gain consensus or as a placeholder
+ c - under construction but pre-alpha (not yet released)
+ a/b - Alpha/Beta testing
+ R - Released
+ M - Mature (no rigorous definition)
+ S - Standard, supplied with Perl 5
+
+ S - Support Level:
+ m - Mailing-list
+ d - Developer
+ u - Usenet newsgroup comp.lang.perl.modules
+ n - None known, try comp.lang.perl.modules
+ a - abandoned; volunteers welcome to take over maintainance
+
+ L - Language Used:
+ p - Perl-only, no compiler needed, should be platform independent
+ c - C and perl, a C compiler will be needed
+ h - Hybrid, written in perl with optional C code, no compiler needed
+ + - C++ and perl, a C++ compiler will be needed
+ o - perl and another language other than C or C++
+
+ I - Interface Style
+ f - plain Functions, no references used
+ h - hybrid, object and function interfaces available
+ n - no interface at all (huh?)
+ r - some use of unblessed References or ties
+ O - Object oriented using blessed references and/or inheritance
+
+ P - Public License
+ p - Standard-Perl: user may choose between GPL and Artistic
+ g - GPL: GNU General Public License
+ l - LGPL: "GNU Lesser General Public License" (previously known as
+ "GNU Library General Public License")
+ b - BSD: The BSD License
+ a - Artistic license alone
+ 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<force> and the C<fforce> pragma.
+
+=item CPAN::Module::get()
+
+Runs a get on the distribution associated with this module.
+
+=item CPAN::Module::inst_file()
+
+Returns the filename of the module found in @INC. The first file found
+is reported just 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<o conf> 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<inst_file> is that modules that have been tested but not yet
+installed are included because PERL5LIB keeps track of tested modules.
-=item C<o conf E<lt>scalar optionE<gt>>
+=item CPAN::Module::inst_version()
-prints the current value of the I<scalar option>
+Returns the version number of the installed module in readable format.
-=item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>>
+=item CPAN::Module::available_version()
-Sets the value of the I<scalar option> to I<value>
+Returns the version number of the available module in readable format.
-=item C<o conf E<lt>list optionE<gt>>
+=item CPAN::Module::install()
-prints the current value of the I<list option> in MakeMaker's
-neatvalue format.
+Runs an C<install> on the distribution associated with this module.
-=item C<o conf E<lt>list optionE<gt> [shift|pop]>
+=item CPAN::Module::look()
-shifts or pops the array in the I<list option> 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 C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>>
+=item CPAN::Module::make()
-works like the corresponding perl commands.
+Runs a C<make> on the distribution associated with this module.
+
+=item CPAN::Module::manpage_headline()
+
+If module is installed, peeks into the module's manpage, reads the
+headline and returns it. Moreover, if the module has been downloaded
+within this session, does the equivalent on the downloaded module even
+if it is not installed.
+
+=item CPAN::Module::perldoc()
+
+Runs a C<perldoc> on this module.
+
+=item CPAN::Module::readme()
+
+Runs a C<readme> on the distribution associated with this module.
+
+=item CPAN::Module::test()
+
+Runs a C<test> on the distribution associated with this module.
+
+=item CPAN::Module::uptodate()
+
+Returns 1 if the module is installed and up-to-date.
+
+=item CPAN::Module::userid()
+
+Returns the author's ID of the module.
=back
-=head2 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<build_dir> as soon as the size of
+all directories there gets bigger than $CPAN::Config->{build_cache}
+(in MB). The contents of this cache may be used for later
+re-installations that you intend to do manually, but will never be
+trusted by CPAN itself. This is due to the fact that the user might
+use these directories for building modules on different architectures.
+
+There is another directory ($CPAN::Config->{keep_source_where}) where
+the original distribution files are kept. This directory is not
+covered by the cache manager and must be controlled by the user. If
+you choose to have the same directory as build_dir and as
+keep_source_where directory, then your sources will be deleted with
+the same fifo mechanism.
+
+=head2 Bundles
+
+A bundle is just a perl module in the namespace Bundle:: that does not
+define any functions or methods. It usually only contains documentation.
+
+It starts like a perl module with a package declaration and a $VERSION
+variable. After that the pod section looks like any other pod with the
+only difference being that I<one special pod section> exists starting with
+(verbatim):
+
+ =head1 CONTENTS
+
+In this pod section each line obeys the format
+
+ Module_Name [Version_String] [- optional text]
+
+The only required part is the first field, the name of a module
+(e.g. Foo::Bar, ie. I<not> the name of the distribution file). The rest
+of the line is optional. The comment part is delimited by a dash just
+as in the man page header.
+
+The distribution of a bundle should follow the same convention as
+other distributions.
+
+Bundles are treated specially in the CPAN package. If you say 'install
+Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all
+the modules in the CONTENTS section of the pod. You can install your
+own Bundles locally by placing a conformant Bundle file somewhere into
+your @INC path. The autobundle() command which is available in the
+shell interface does that for you by including all currently installed
+modules in a snapshot bundle file.
+
+=head1 PREREQUISITES
+
+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<ftp:>.
+
+If you have neither Net::FTP nor LWP, there is a fallback mechanism
+implemented for an external ftp command or for an external lynx
+command.
+
+=head1 UTILITIES
+
+=head2 Finding packages and VERSION
+
+This module presumes that all packages on CPAN
=over 2
-=item 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<Makefile.PL> or C<Build.PL> (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<o debug 0>
+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<file> URLs, please try the correct format. Either:
+What seems quite a successful strategy is the combination of C<reload
+cpan> and the debugging switches. Add a new debug statement while
+running in the shell and then issue a C<reload cpan> and see the new
+debugging messages immediately without losing the current context.
- file://localhost/whatever/ftp/pub/CPAN/
+C<o debug> without an argument lists the valid package names and the
+current set of packages in debugging mode. C<o debug> has built-in
+completion support.
-or
+For debugging of CPAN data there is the C<dump> command which takes
+the same arguments as make/test/install and outputs each object's
+Data::Dumper dump. If an argument looks like a perl variable and
+contains one of C<$>, C<@> or C<%>, it is eval()ed and fed to
+Data::Dumper directly.
- 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<urllist> parameter of the configuration table contains a list of
-URLs that are to be used for downloading. If the list contains any
-C<file> 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<file> 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<dontload_list> can be used to intercept the C<has_inst()> call such
+that an optional module is not loaded despite being available. For
+example the following command will prevent that C<YAML.pm> 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<yaml_module>) installed, CPAN.pm collects a few statistical data
-about recent downloads. You can view the statistics with the C<hosts>
-command or inspect them directly by looking into the C<FTPstats.yml>
-file in your C<cpan_home> directory.
+See the source for details.
-To get some interesting statistics it is recommended to set the
-C<randomize_urllist> 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<Note:> 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<prefs_dir> 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