This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
The byteorder code doesn't need to be in Config.pm if byteorder
[perl5.git] / lib / CPAN.pm
CommitLineData
c4d24d4c 1# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
5f05dabc 2package CPAN;
1426a145
JH
3$VERSION = '1.76_01';
4$VERSION = eval $VERSION;
6f14f089 5# $Id: CPAN.pm,v 1.412 2003/07/31 14:53:04 k Exp $
5f05dabc 6
c356248b
A
7# only used during development:
8$Revision = "";
6f14f089 9# $Revision = "[".substr(q$Revision: 1.412 $, 10)."]";
5f05dabc 10
11use Carp ();
12use Config ();
13use Cwd ();
14use DirHandle;
15use Exporter ();
2e2b7522 16use ExtUtils::MakeMaker (); # $SelfLoader::DEBUG=1;
5f05dabc 17use File::Basename ();
10b2abe6 18use File::Copy ();
5f05dabc 19use File::Find;
20use File::Path ();
da199366 21use FileHandle ();
5f05dabc 22use Safe ();
10b2abe6 23use Text::ParseWords ();
05454584 24use Text::Wrap;
f14b5cec 25use File::Spec;
0dfa0441 26use Sys::Hostname;
de34a54b
JH
27no lib "."; # we need to run chdir all over and we would get at wrong
28 # libraries there
5f05dabc 29
be708cc0
JH
30require Mac::BuildTools if $^O eq 'MacOS';
31
5f05dabc 32END { $End++; &cleanup; }
33
2e2b7522 34%CPAN::DEBUG = qw[
5f05dabc 35 CPAN 1
36 Index 2
37 InfoObj 4
38 Author 8
39 Distribution 16
40 Bundle 32
41 Module 64
42 CacheMgr 128
43 Complete 256
44 FTP 512
45 Shell 1024
46 Eval 2048
47 Config 4096
09d9d230 48 Tarzip 8192
5e05dca5 49 Version 16384
6d29edf5 50 Queue 32768
2e2b7522 51];
5f05dabc 52
53$CPAN::DEBUG ||= 0;
da199366 54$CPAN::Signal ||= 0;
c356248b 55$CPAN::Frontend ||= "CPAN::Shell";
09d9d230 56$CPAN::Defaultsite ||= "ftp://ftp.perl.org/pub/CPAN";
5f05dabc 57
58package CPAN;
5f05dabc 59use strict qw(vars);
60
6d29edf5 61use vars qw($VERSION @EXPORT $AUTOLOAD $DEBUG $META $HAS_USABLE $term
9d61fa1d 62 $Revision $Signal $End $Suppress_readline $Frontend
5a5fac02 63 $Defaultsite $Have_warned);
6d29edf5 64
2e2b7522 65@CPAN::ISA = qw(CPAN::Debug Exporter);
5f05dabc 66
55e314ee 67@EXPORT = qw(
911a92db 68 autobundle bundle expand force get cvs_import
da199366
A
69 install make readme recompile shell test clean
70 );
5f05dabc 71
55e314ee
A
72#-> sub CPAN::AUTOLOAD ;
73sub AUTOLOAD {
74 my($l) = $AUTOLOAD;
75 $l =~ s/.*:://;
76 my(%EXPORT);
77 @EXPORT{@EXPORT} = '';
36263cb3 78 CPAN::Config->load unless $CPAN::Config_loaded++;
55e314ee
A
79 if (exists $EXPORT{$l}){
80 CPAN::Shell->$l(@_);
81 } else {
c356248b
A
82 $CPAN::Frontend->mywarn(qq{Unknown command "$AUTOLOAD". }.
83 qq{Type ? for help.
84});
55e314ee
A
85 }
86}
87
88#-> sub CPAN::shell ;
89sub shell {
36263cb3 90 my($self) = @_;
911a92db 91 $Suppress_readline = ! -t STDIN unless defined $Suppress_readline;
36263cb3 92 CPAN::Config->load unless $CPAN::Config_loaded++;
55e314ee 93
9d61fa1d
A
94 my $oprompt = shift || "cpan> ";
95 my $prompt = $oprompt;
96 my $commandline = shift || "";
5e05dca5 97
55e314ee
A
98 local($^W) = 1;
99 unless ($Suppress_readline) {
100 require Term::ReadLine;
9d61fa1d
A
101 if (! $term
102 or
103 $term->ReadLine eq "Term::ReadLine::Stub"
104 ) {
105 $term = Term::ReadLine->new('CPAN Monitor');
106 }
36263cb3
GS
107 if ($term->ReadLine eq "Term::ReadLine::Gnu") {
108 my $attribs = $term->Attribs;
36263cb3
GS
109 $attribs->{attempted_completion_function} = sub {
110 &CPAN::Complete::gnu_cpl;
111 }
36263cb3
GS
112 } else {
113 $readline::rl_completion_function =
114 $readline::rl_completion_function = 'CPAN::Complete::cpl';
115 }
5fc0f0f6
JH
116 if (my $histfile = $CPAN::Config->{'histfile'}) {{
117 unless ($term->can("AddHistory")) {
118 $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n");
119 last;
120 }
121 my($fh) = FileHandle->new;
122 open $fh, "<$histfile" or last;
123 local $/ = "\n";
124 while (<$fh>) {
125 chomp;
126 $term->AddHistory($_);
127 }
128 close $fh;
129 }}
911a92db
GS
130 # $term->OUT is autoflushed anyway
131 my $odef = select STDERR;
132 $| = 1;
133 select STDOUT;
134 $| = 1;
135 select $odef;
55e314ee
A
136 }
137
6d29edf5 138 # no strict; # I do not recall why no strict was here (2000-09-03)
55e314ee 139 $META->checklock();
9d61fa1d 140 my $cwd = CPAN::anycwd();
911a92db
GS
141 my $try_detect_readline;
142 $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub" if $term;
55e314ee
A
143 my $rl_avail = $Suppress_readline ? "suppressed" :
144 ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" :
c4d24d4c 145 "available (try 'install Bundle::CPAN')";
55e314ee 146
c356248b 147 $CPAN::Frontend->myprint(
6d29edf5
JH
148 sprintf qq{
149cpan shell -- CPAN exploration and modules installation (v%s%s)
150ReadLine support %s
55e314ee 151
6d29edf5
JH
152},
153 $CPAN::VERSION,
154 $CPAN::Revision,
155 $rl_avail
156 )
157 unless $CPAN::Config->{'inhibit_startup_message'} ;
c356248b 158 my($continuation) = "";
8d97e4a1 159 SHELLCOMMAND: while () {
55e314ee
A
160 if ($Suppress_readline) {
161 print $prompt;
8d97e4a1 162 last SHELLCOMMAND unless defined ($_ = <> );
55e314ee
A
163 chomp;
164 } else {
8d97e4a1
JH
165 last SHELLCOMMAND unless
166 defined ($_ = $term->readline($prompt, $commandline));
55e314ee 167 }
c356248b 168 $_ = "$continuation$_" if $continuation;
55e314ee 169 s/^\s+//;
8d97e4a1 170 next SHELLCOMMAND if /^$/;
2e2b7522 171 $_ = 'h' if /^\s*\?/;
09d9d230 172 if (/^(?:q(?:uit)?|bye|exit)$/i) {
8d97e4a1 173 last SHELLCOMMAND;
c356248b
A
174 } elsif (s/\\$//s) {
175 chomp;
176 $continuation = $_;
177 $prompt = " > ";
178 } elsif (/^\!/) {
55e314ee
A
179 s/^\!//;
180 my($eval) = $_;
181 package CPAN::Eval;
182 use vars qw($import_done);
183 CPAN->import(':DEFAULT') unless $import_done++;
184 CPAN->debug("eval[$eval]") if $CPAN::DEBUG;
185 eval($eval);
186 warn $@ if $@;
c356248b 187 $continuation = "";
9d61fa1d 188 $prompt = $oprompt;
55e314ee
A
189 } elsif (/./) {
190 my(@line);
191 if ($] < 5.00322) { # parsewords had a bug until recently
192 @line = split;
193 } else {
194 eval { @line = Text::ParseWords::shellwords($_) };
8d97e4a1
JH
195 warn($@), next SHELLCOMMAND if $@;
196 warn("Text::Parsewords could not parse the line [$_]"),
197 next SHELLCOMMAND unless @line;
55e314ee
A
198 }
199 $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG;
200 my $command = shift @line;
201 eval { CPAN::Shell->$command(@line) };
202 warn $@ if $@;
05d2a450 203 chdir $cwd or $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd": $!});
c356248b
A
204 $CPAN::Frontend->myprint("\n");
205 $continuation = "";
9d61fa1d 206 $prompt = $oprompt;
55e314ee
A
207 }
208 } continue {
9d61fa1d
A
209 $commandline = ""; # I do want to be able to pass a default to
210 # shell, but on the second command I see no
211 # use in that
09d9d230 212 $Signal=0;
36263cb3
GS
213 CPAN::Queue->nullify_queue;
214 if ($try_detect_readline) {
215 if ($CPAN::META->has_inst("Term::ReadLine::Gnu")
216 ||
217 $CPAN::META->has_inst("Term::ReadLine::Perl")
218 ) {
219 delete $INC{"Term/ReadLine.pm"};
6d29edf5
JH
220 my $redef = 0;
221 local($SIG{__WARN__}) = CPAN::Shell::paintdots_onreload(\$redef);
36263cb3 222 require Term::ReadLine;
911a92db
GS
223 $CPAN::Frontend->myprint("\n$redef subroutines in ".
224 "Term::ReadLine redefined\n");
9d61fa1d 225 @_ = ($oprompt,"");
36263cb3
GS
226 goto &shell;
227 }
228 }
55e314ee 229 }
9d61fa1d 230 chdir $cwd or $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd": $!});
55e314ee
A
231}
232
233package CPAN::CacheMgr;
c356248b 234@CPAN::CacheMgr::ISA = qw(CPAN::InfoObj CPAN);
55e314ee
A
235use File::Find;
236
237package CPAN::Config;
55e314ee
A
238use vars qw(%can $dot_cpan);
239
240%can = (
241 'commit' => "Commit changes to disk",
242 'defaults' => "Reload defaults from disk",
243 'init' => "Interactive setting of all options",
244);
245
246package CPAN::FTP;
c356248b 247use vars qw($Ua $Thesite $Themethod);
55e314ee
A
248@CPAN::FTP::ISA = qw(CPAN::Debug);
249
c049f953
JH
250package CPAN::LWP::UserAgent;
251use vars qw(@ISA $USER $PASSWD $SETUPDONE);
252# we delay requiring LWP::UserAgent and setting up inheritence until we need it
253
55e314ee
A
254package CPAN::Complete;
255@CPAN::Complete::ISA = qw(CPAN::Debug);
9d61fa1d
A
256@CPAN::Complete::COMMANDS = sort qw(
257 ! a b d h i m o q r u autobundle clean dump
8d97e4a1
JH
258 make test install force readme reload look
259 cvs_import ls
9d61fa1d 260) unless @CPAN::Complete::COMMANDS;
55e314ee
A
261
262package CPAN::Index;
c049f953 263use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03);
55e314ee 264@CPAN::Index::ISA = qw(CPAN::Debug);
c049f953
JH
265$LAST_TIME ||= 0;
266$DATE_OF_03 ||= 0;
6d29edf5
JH
267# use constant PROTOCOL => "2.0"; # outcommented to avoid warning on upgrade from 1.57
268sub PROTOCOL { 2.0 }
55e314ee
A
269
270package CPAN::InfoObj;
271@CPAN::InfoObj::ISA = qw(CPAN::Debug);
272
273package CPAN::Author;
274@CPAN::Author::ISA = qw(CPAN::InfoObj);
275
276package CPAN::Distribution;
277@CPAN::Distribution::ISA = qw(CPAN::InfoObj);
278
279package CPAN::Bundle;
280@CPAN::Bundle::ISA = qw(CPAN::Module);
281
282package CPAN::Module;
283@CPAN::Module::ISA = qw(CPAN::InfoObj);
10b2abe6 284
35576f8c
A
285package CPAN::Exception::RecursiveDependency;
286use overload '""' => "as_string";
287
288sub new {
289 my($class) = shift;
290 my($deps) = shift;
291 my @deps;
292 my %seen;
293 for my $dep (@$deps) {
294 push @deps, $dep;
295 last if $seen{$dep}++;
296 }
297 bless { deps => \@deps }, $class;
298}
299
300sub as_string {
301 my($self) = shift;
302 "\nRecursive dependency detected:\n " .
303 join("\n => ", @{$self->{deps}}) .
304 ".\nCannot continue.\n";
305}
306
55e314ee 307package CPAN::Shell;
8d97e4a1 308use vars qw($AUTOLOAD @ISA $COLOR_REGISTERED $ADVANCED_QUERY $PRINT_ORNAMENTING);
55e314ee 309@CPAN::Shell::ISA = qw(CPAN::Debug);
9d61fa1d 310$COLOR_REGISTERED ||= 0;
8d97e4a1 311$PRINT_ORNAMENTING ||= 0;
55e314ee
A
312
313#-> sub CPAN::Shell::AUTOLOAD ;
314sub AUTOLOAD {
315 my($autoload) = $AUTOLOAD;
c356248b 316 my $class = shift(@_);
09d9d230 317 # warn "autoload[$autoload] class[$class]";
55e314ee
A
318 $autoload =~ s/.*:://;
319 if ($autoload =~ /^w/) {
320 if ($CPAN::META->has_inst('CPAN::WAIT')) {
c356248b 321 CPAN::WAIT->$autoload(@_);
55e314ee 322 } else {
c356248b 323 $CPAN::Frontend->mywarn(qq{
55e314ee
A
324Commands starting with "w" require CPAN::WAIT to be installed.
325Please consider installing CPAN::WAIT to use the fulltext index.
f610777f 326For this you just need to type
55e314ee 327 install CPAN::WAIT
c356248b 328});
55e314ee
A
329 }
330 } else {
c356248b
A
331 $CPAN::Frontend->mywarn(qq{Unknown command '$autoload'. }.
332 qq{Type ? for help.
333});
55e314ee
A
334 }
335}
336
09d9d230 337package CPAN::Tarzip;
8d97e4a1 338use vars qw($AUTOLOAD @ISA $BUGHUNTING);
09d9d230 339@CPAN::Tarzip::ISA = qw(CPAN::Debug);
8d97e4a1 340$BUGHUNTING = 0; # released code must have turned off
09d9d230
A
341
342package CPAN::Queue;
f610777f 343
f14b5cec
JH
344# One use of the queue is to determine if we should or shouldn't
345# announce the availability of a new CPAN module
346
347# Now we try to use it for dependency tracking. For that to happen
f610777f
A
348# we need to draw a dependency tree and do the leaves first. This can
349# easily be reached by running CPAN.pm recursively, but we don't want
350# to waste memory and run into deep recursion. So what we can do is
f14b5cec
JH
351# this:
352
353# CPAN::Queue is the package where the queue is maintained. Dependencies
354# often have high priority and must be brought to the head of the queue,
355# possibly by jumping the queue if they are already there. My first code
356# attempt tried to be extremely correct. Whenever a module needed
357# immediate treatment, I either unshifted it to the front of the queue,
358# or, if it was already in the queue, I spliced and let it bypass the
359# others. This became a too correct model that made it impossible to put
360# an item more than once into the queue. Why would you need that? Well,
361# you need temporary duplicates as the manager of the queue is a loop
362# that
363#
364# (1) looks at the first item in the queue without shifting it off
365#
366# (2) cares for the item
367#
368# (3) removes the item from the queue, *even if its agenda failed and
369# even if the item isn't the first in the queue anymore* (that way
370# protecting against never ending queues)
371#
372# So if an item has prerequisites, the installation fails now, but we
373# want to retry later. That's easy if we have it twice in the queue.
374#
375# I also expect insane dependency situations where an item gets more
376# than two lives in the queue. Simplest example is triggered by 'install
377# Foo Foo Foo'. People make this kind of mistakes and I don't want to
378# get in the way. I wanted the queue manager to be a dumb servant, not
379# one that knows everything.
380#
381# Who would I tell in this model that the user wants to be asked before
382# processing? I can't attach that information to the module object,
383# because not modules are installed but distributions. So I'd have to
384# tell the distribution object that it should ask the user before
385# processing. Where would the question be triggered then? Most probably
386# in CPAN::Distribution::rematein.
387# Hope that makes sense, my head is a bit off:-) -- AK
f610777f
A
388
389use vars qw{ @All };
390
6d29edf5 391# CPAN::Queue::new ;
09d9d230 392sub new {
6d29edf5
JH
393 my($class,$s) = @_;
394 my $self = bless { qmod => $s }, $class;
f610777f 395 push @All, $self;
f610777f 396 return $self;
f610777f
A
397}
398
6d29edf5 399# CPAN::Queue::first ;
f610777f
A
400sub first {
401 my $obj = $All[0];
6d29edf5 402 $obj->{qmod};
f610777f
A
403}
404
6d29edf5 405# CPAN::Queue::delete_first ;
f610777f
A
406sub delete_first {
407 my($class,$what) = @_;
408 my $i;
409 for my $i (0..$#All) {
6d29edf5 410 if ( $All[$i]->{qmod} eq $what ) {
f610777f
A
411 splice @All, $i, 1;
412 return;
413 }
414 }
415}
416
6d29edf5 417# CPAN::Queue::jumpqueue ;
f610777f 418sub jumpqueue {
6d29edf5
JH
419 my $class = shift;
420 my @what = @_;
421 CPAN->debug(sprintf("before jumpqueue All[%s] what[%s]",
422 join(",",map {$_->{qmod}} @All),
423 join(",",@what)
424 )) if $CPAN::DEBUG;
f610777f 425 WHAT: for my $what (reverse @what) {
6d29edf5
JH
426 my $jumped = 0;
427 for (my $i=0; $i<$#All;$i++) { #prevent deep recursion
428 CPAN->debug("i[$All[$i]]what[$what]") if $CPAN::DEBUG;
429 if ($All[$i]->{qmod} eq $what){
430 $jumped++;
431 if ($jumped > 100) { # one's OK if e.g. just
432 # processing now; more are OK if
433 # user typed it several times
434 $CPAN::Frontend->mywarn(
f610777f
A
435qq{Object [$what] queued more than 100 times, ignoring}
436 );
6d29edf5
JH
437 next WHAT;
438 }
439 }
440 }
441 my $obj = bless { qmod => $what }, $class;
442 unshift @All, $obj;
f610777f 443 }
6d29edf5
JH
444 CPAN->debug(sprintf("after jumpqueue All[%s] what[%s]",
445 join(",",map {$_->{qmod}} @All),
446 join(",",@what)
447 )) if $CPAN::DEBUG;
f610777f
A
448}
449
6d29edf5 450# CPAN::Queue::exists ;
f610777f
A
451sub exists {
452 my($self,$what) = @_;
6d29edf5
JH
453 my @all = map { $_->{qmod} } @All;
454 my $exists = grep { $_->{qmod} eq $what } @All;
455 # warn "in exists what[$what] all[@all] exists[$exists]";
f610777f
A
456 $exists;
457}
458
6d29edf5 459# CPAN::Queue::delete ;
f610777f
A
460sub delete {
461 my($self,$mod) = @_;
6d29edf5 462 @All = grep { $_->{qmod} ne $mod } @All;
09d9d230 463}
55e314ee 464
6d29edf5 465# CPAN::Queue::nullify_queue ;
36263cb3
GS
466sub nullify_queue {
467 @All = ();
468}
469
470
471
55e314ee
A
472package CPAN;
473
2e2b7522 474$META ||= CPAN->new; # In case we re-eval ourselves we need the ||
55e314ee 475
6d29edf5
JH
476# from here on only subs.
477################################################################################
55e314ee 478
6d29edf5 479#-> sub CPAN::all_objects ;
36263cb3 480sub all_objects {
5f05dabc 481 my($mgr,$class) = @_;
36263cb3 482 CPAN::Config->load unless $CPAN::Config_loaded++;
5f05dabc 483 CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG;
484 CPAN::Index->reload;
6d29edf5 485 values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok
5f05dabc 486}
36263cb3 487*all = \&all_objects;
5f05dabc 488
c4d24d4c
A
489# Called by shell, not in batch mode. In batch mode I see no risk in
490# having many processes updating something as installations are
491# continually checked at runtime. In shell mode I suspect it is
492# unintentional to open more than one shell at a time
493
10b2abe6 494#-> sub CPAN::checklock ;
5f05dabc 495sub checklock {
496 my($self) = @_;
5de3f0da 497 my $lockfile = File::Spec->catfile($CPAN::Config->{cpan_home},".lock");
5f05dabc 498 if (-f $lockfile && -M _ > 0) {
6d29edf5
JH
499 my $fh = FileHandle->new($lockfile) or
500 $CPAN::Frontend->mydie("Could not open $lockfile: $!");
0dfa0441
JH
501 my $otherpid = <$fh>;
502 my $otherhost = <$fh>;
5f05dabc 503 $fh->close;
0dfa0441
JH
504 if (defined $otherpid && $otherpid) {
505 chomp $otherpid;
506 }
507 if (defined $otherhost && $otherhost) {
508 chomp $otherhost;
509 }
510 my $thishost = hostname();
511 if (defined $otherhost && defined $thishost &&
512 $otherhost ne '' && $thishost ne '' &&
513 $otherhost ne $thishost) {
514 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile $lockfile\n".
515 "reports other host $otherhost and other process $otherpid.\n".
516 "Cannot proceed.\n"));
517 }
518 elsif (defined $otherpid && $otherpid) {
519 return if $$ == $otherpid; # should never happen
c356248b
A
520 $CPAN::Frontend->mywarn(
521 qq{
0dfa0441 522There seems to be running another CPAN process (pid $otherpid). Contacting...
c356248b 523});
0dfa0441 524 if (kill 0, $otherpid) {
c356248b
A
525 $CPAN::Frontend->mydie(qq{Other job is running.
526You may want to kill it and delete the lockfile, maybe. On UNIX try:
0dfa0441 527 kill $otherpid
c356248b
A
528 rm $lockfile
529});
5f05dabc 530 } elsif (-w $lockfile) {
e50380aa 531 my($ans) =
5f05dabc 532 ExtUtils::MakeMaker::prompt
05454584
A
533 (qq{Other job not responding. Shall I overwrite }.
534 qq{the lockfile? (Y/N)},"y");
c356248b
A
535 $CPAN::Frontend->myexit("Ok, bye\n")
536 unless $ans =~ /^y/i;
5f05dabc 537 } else {
538 Carp::croak(
05454584
A
539 qq{Lockfile $lockfile not writeable by you. }.
540 qq{Cannot proceed.\n}.
5f05dabc 541 qq{ On UNIX try:\n}.
542 qq{ rm $lockfile\n}.
543 qq{ and then rerun us.\n}
544 );
545 }
6d29edf5 546 } else {
0dfa0441 547 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile $lockfile\n".
6d29edf5 548 "reports other process with ID ".
0dfa0441 549 "$otherpid. Cannot proceed.\n"));
6d29edf5 550 }
5f05dabc 551 }
36263cb3
GS
552 my $dotcpan = $CPAN::Config->{cpan_home};
553 eval { File::Path::mkpath($dotcpan);};
554 if ($@) {
555 # A special case at least for Jarkko.
556 my $firsterror = $@;
557 my $seconderror;
558 my $symlinkcpan;
559 if (-l $dotcpan) {
560 $symlinkcpan = readlink $dotcpan;
561 die "readlink $dotcpan failed: $!" unless defined $symlinkcpan;
562 eval { File::Path::mkpath($symlinkcpan); };
563 if ($@) {
564 $seconderror = $@;
565 } else {
566 $CPAN::Frontend->mywarn(qq{
567Working directory $symlinkcpan created.
568});
569 }
570 }
571 unless (-d $dotcpan) {
572 my $diemess = qq{
573Your configuration suggests "$dotcpan" as your
574CPAN.pm working directory. I could not create this directory due
575to this error: $firsterror\n};
576 $diemess .= qq{
577As "$dotcpan" is a symlink to "$symlinkcpan",
578I tried to create that, but I failed with this error: $seconderror
579} if $seconderror;
580 $diemess .= qq{
581Please make sure the directory exists and is writable.
582};
583 $CPAN::Frontend->mydie($diemess);
584 }
585 }
5f05dabc 586 my $fh;
da199366 587 unless ($fh = FileHandle->new(">$lockfile")) {
911a92db 588 if ($! =~ /Permission/) {
5f05dabc 589 my $incc = $INC{'CPAN/Config.pm'};
5de3f0da 590 my $myincc = File::Spec->catfile($ENV{HOME},'.cpan','CPAN','MyConfig.pm');
c356248b 591 $CPAN::Frontend->myprint(qq{
5f05dabc 592
593Your configuration suggests that CPAN.pm should use a working
594directory of
595 $CPAN::Config->{cpan_home}
596Unfortunately we could not create the lock file
597 $lockfile
598due to permission problems.
599
600Please make sure that the configuration variable
601 \$CPAN::Config->{cpan_home}
602points to a directory where you can write a .lock file. You can set
603this variable in either
604 $incc
605or
606 $myincc
607
c356248b 608});
5f05dabc 609 }
c356248b 610 $CPAN::Frontend->mydie("Could not open >$lockfile: $!");
5f05dabc 611 }
c356248b 612 $fh->print($$, "\n");
0dfa0441 613 $fh->print(hostname(), "\n");
5f05dabc 614 $self->{LOCK} = $lockfile;
615 $fh->close;
6d29edf5 616 $SIG{TERM} = sub {
2e2b7522
GS
617 &cleanup;
618 $CPAN::Frontend->mydie("Got SIGTERM, leaving");
c356248b 619 };
6d29edf5 620 $SIG{INT} = sub {
09d9d230
A
621 # no blocks!!!
622 &cleanup if $Signal;
623 $CPAN::Frontend->mydie("Got another SIGINT") if $Signal;
624 print "Caught SIGINT\n";
625 $Signal++;
da199366 626 };
911a92db
GS
627
628# From: Larry Wall <larry@wall.org>
629# Subject: Re: deprecating SIGDIE
630# To: perl5-porters@perl.org
631# Date: Thu, 30 Sep 1999 14:58:40 -0700 (PDT)
632#
633# The original intent of __DIE__ was only to allow you to substitute one
634# kind of death for another on an application-wide basis without respect
635# to whether you were in an eval or not. As a global backstop, it should
636# not be used any more lightly (or any more heavily :-) than class
637# UNIVERSAL. Any attempt to build a general exception model on it should
638# be politely squashed. Any bug that causes every eval {} to have to be
639# modified should be not so politely squashed.
640#
641# Those are my current opinions. It is also my optinion that polite
642# arguments degenerate to personal arguments far too frequently, and that
643# when they do, it's because both people wanted it to, or at least didn't
644# sufficiently want it not to.
645#
646# Larry
647
6d29edf5
JH
648 # global backstop to cleanup if we should really die
649 $SIG{__DIE__} = \&cleanup;
e50380aa 650 $self->debug("Signal handler set.") if $CPAN::DEBUG;
5f05dabc 651}
652
10b2abe6 653#-> sub CPAN::DESTROY ;
5f05dabc 654sub DESTROY {
655 &cleanup; # need an eval?
656}
657
9d61fa1d
A
658#-> sub CPAN::anycwd ;
659sub anycwd () {
660 my $getcwd;
661 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
662 CPAN->$getcwd();
663}
664
55e314ee
A
665#-> sub CPAN::cwd ;
666sub cwd {Cwd::cwd();}
667
668#-> sub CPAN::getcwd ;
669sub getcwd {Cwd::getcwd();}
670
10b2abe6 671#-> sub CPAN::exists ;
5f05dabc 672sub exists {
673 my($mgr,$class,$id) = @_;
9d61fa1d 674 CPAN::Config->load unless $CPAN::Config_loaded++;
5f05dabc 675 CPAN::Index->reload;
e50380aa 676 ### Carp::croak "exists called without class argument" unless $class;
5f05dabc 677 $id ||= "";
6d29edf5
JH
678 exists $META->{readonly}{$class}{$id} or
679 exists $META->{readwrite}{$class}{$id}; # unsafe meta access, ok
5f05dabc 680}
681
09d9d230
A
682#-> sub CPAN::delete ;
683sub delete {
684 my($mgr,$class,$id) = @_;
6d29edf5
JH
685 delete $META->{readonly}{$class}{$id}; # unsafe meta access, ok
686 delete $META->{readwrite}{$class}{$id}; # unsafe meta access, ok
09d9d230
A
687}
688
de34a54b
JH
689#-> sub CPAN::has_usable
690# has_inst is sometimes too optimistic, we should replace it with this
691# has_usable whenever a case is given
692sub has_usable {
693 my($self,$mod,$message) = @_;
694 return 1 if $HAS_USABLE->{$mod};
695 my $has_inst = $self->has_inst($mod,$message);
696 return unless $has_inst;
6d29edf5
JH
697 my $usable;
698 $usable = {
699 LWP => [ # we frequently had "Can't locate object
700 # method "new" via package "LWP::UserAgent" at
701 # (eval 69) line 2006
702 sub {require LWP},
703 sub {require LWP::UserAgent},
704 sub {require HTTP::Request},
705 sub {require URI::URL},
706 ],
707 Net::FTP => [
708 sub {require Net::FTP},
709 sub {require Net::Config},
710 ]
711 };
712 if ($usable->{$mod}) {
713 for my $c (0..$#{$usable->{$mod}}) {
714 my $code = $usable->{$mod}[$c];
de34a54b
JH
715 my $ret = eval { &$code() };
716 if ($@) {
717 warn "DEBUG: c[$c]\$\@[$@]ret[$ret]";
718 return;
719 }
720 }
721 }
722 return $HAS_USABLE->{$mod} = 1;
723}
724
55e314ee
A
725#-> sub CPAN::has_inst
726sub has_inst {
727 my($self,$mod,$message) = @_;
728 Carp::croak("CPAN->has_inst() called without an argument")
729 unless defined $mod;
de34a54b
JH
730 if (defined $message && $message eq "no"
731 ||
6d29edf5 732 exists $CPAN::META->{dontload_hash}{$mod} # unsafe meta access, ok
de34a54b
JH
733 ||
734 exists $CPAN::Config->{dontload_hash}{$mod}
735 ) {
6d29edf5 736 $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok
de34a54b 737 return 0;
55e314ee
A
738 }
739 my $file = $mod;
c356248b 740 my $obj;
55e314ee
A
741 $file =~ s|::|/|g;
742 $file =~ s|/|\\|g if $^O eq 'MSWin32';
743 $file .= ".pm";
c356248b 744 if ($INC{$file}) {
f14b5cec
JH
745 # checking %INC is wrong, because $INC{LWP} may be true
746 # although $INC{"URI/URL.pm"} may have failed. But as
747 # I really want to say "bla loaded OK", I have to somehow
748 # cache results.
749 ### warn "$file in %INC"; #debug
55e314ee 750 return 1;
55e314ee 751 } elsif (eval { require $file }) {
c356248b
A
752 # eval is good: if we haven't yet read the database it's
753 # perfect and if we have installed the module in the meantime,
754 # it tries again. The second require is only a NOOP returning
755 # 1 if we had success, otherwise it's retrying
f14b5cec 756
c356248b
A
757 $CPAN::Frontend->myprint("CPAN: $mod loaded ok\n");
758 if ($mod eq "CPAN::WAIT") {
759 push @CPAN::Shell::ISA, CPAN::WAIT;
760 }
55e314ee
A
761 return 1;
762 } elsif ($mod eq "Net::FTP") {
6d29edf5 763 $CPAN::Frontend->mywarn(qq{
55e314ee
A
764 Please, install Net::FTP as soon as possible. CPAN.pm installs it for you
765 if you just type
766 install Bundle::libnet
5f05dabc 767
5a5fac02
JH
768}) unless $Have_warned->{"Net::FTP"}++;
769 sleep 3;
5b6aeab6 770 } elsif ($mod eq "Digest::MD5"){
c356248b 771 $CPAN::Frontend->myprint(qq{
5b6aeab6
GA
772 CPAN: MD5 security checks disabled because Digest::MD5 not installed.
773 Please consider installing the Digest::MD5 module.
c356248b
A
774
775});
776 sleep 2;
f14b5cec
JH
777 } else {
778 delete $INC{$file}; # if it inc'd LWP but failed during, say, URI
05454584 779 }
55e314ee 780 return 0;
05454584
A
781}
782
10b2abe6 783#-> sub CPAN::instance ;
5f05dabc 784sub instance {
785 my($mgr,$class,$id) = @_;
786 CPAN::Index->reload;
5f05dabc 787 $id ||= "";
6d29edf5
JH
788 # unsafe meta access, ok?
789 return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id};
790 $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id);
5f05dabc 791}
792
10b2abe6 793#-> sub CPAN::new ;
5f05dabc 794sub new {
795 bless {}, shift;
796}
797
10b2abe6 798#-> sub CPAN::cleanup ;
5f05dabc 799sub cleanup {
2e2b7522
GS
800 # warn "cleanup called with arg[@_] End[$End] Signal[$Signal]";
801 local $SIG{__DIE__} = '';
802 my($message) = @_;
803 my $i = 0;
804 my $ineval = 0;
5fc0f0f6
JH
805 my($subroutine);
806 while ((undef,undef,undef,$subroutine) = caller(++$i)) {
2e2b7522
GS
807 $ineval = 1, last if
808 $subroutine eq '(eval)';
2e2b7522
GS
809 }
810 return if $ineval && !$End;
5fc0f0f6
JH
811 return unless defined $META->{LOCK};
812 return unless -f $META->{LOCK};
813 $META->savehist;
814 unlink $META->{LOCK};
2e2b7522
GS
815 # require Carp;
816 # Carp::cluck("DEBUGGING");
817 $CPAN::Frontend->mywarn("Lockfile removed.\n");
5f05dabc 818}
819
5fc0f0f6
JH
820#-> sub CPAN::savehist
821sub savehist {
822 my($self) = @_;
823 my($histfile,$histsize);
824 unless ($histfile = $CPAN::Config->{'histfile'}){
825 $CPAN::Frontend->mywarn("No history written (no histfile specified).\n");
826 return;
827 }
828 $histsize = $CPAN::Config->{'histsize'} || 100;
35576f8c
A
829 if ($CPAN::term){
830 unless ($CPAN::term->can("GetHistory")) {
831 $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n");
832 return;
833 }
834 } else {
5fc0f0f6
JH
835 return;
836 }
837 my @h = $CPAN::term->GetHistory;
838 splice @h, 0, @h-$histsize if @h>$histsize;
839 my($fh) = FileHandle->new;
35576f8c 840 open $fh, ">$histfile" or $CPAN::Frontend->mydie("Couldn't open >$histfile: $!");
5fc0f0f6
JH
841 local $\ = local $, = "\n";
842 print $fh @h;
843 close $fh;
844}
845
4c070e31
IZ
846sub is_tested {
847 my($self,$what) = @_;
848 $self->{is_tested}{$what} = 1;
849}
850
851sub is_installed {
852 my($self,$what) = @_;
853 delete $self->{is_tested}{$what};
854}
855
856sub set_perl5lib {
857 my($self) = @_;
0362b508 858 $self->{is_tested} ||= {};
4c070e31
IZ
859 return unless %{$self->{is_tested}};
860 my $env = $ENV{PERL5LIB};
861 $env = $ENV{PERLLIB} unless defined $env;
862 my @env;
863 push @env, $env if defined $env and length $env;
864 my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}};
865 $CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n");
866 $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env;
867}
868
05454584 869package CPAN::CacheMgr;
5f05dabc 870
05454584
A
871#-> sub CPAN::CacheMgr::as_string ;
872sub as_string {
873 eval { require Data::Dumper };
874 if ($@) {
875 return shift->SUPER::as_string;
5f05dabc 876 } else {
05454584 877 return Data::Dumper::Dumper(shift);
5f05dabc 878 }
879}
880
05454584
A
881#-> sub CPAN::CacheMgr::cachesize ;
882sub cachesize {
883 shift->{DU};
5f05dabc 884}
5f05dabc 885
c4d24d4c 886#-> sub CPAN::CacheMgr::tidyup ;
09d9d230
A
887sub tidyup {
888 my($self) = @_;
889 return unless -d $self->{ID};
890 while ($self->{DU} > $self->{'MAX'} ) {
891 my($toremove) = shift @{$self->{FIFO}};
892 $CPAN::Frontend->myprint(sprintf(
893 "Deleting from cache".
894 ": $toremove (%.1f>%.1f MB)\n",
895 $self->{DU}, $self->{'MAX'})
896 );
897 return if $CPAN::Signal;
898 $self->force_clean_cache($toremove);
899 return if $CPAN::Signal;
900 }
901}
5f05dabc 902
05454584
A
903#-> sub CPAN::CacheMgr::dir ;
904sub dir {
905 shift->{ID};
906}
907
908#-> sub CPAN::CacheMgr::entries ;
909sub entries {
910 my($self,$dir) = @_;
55e314ee 911 return unless defined $dir;
e50380aa 912 $self->debug("reading dir[$dir]") if $CPAN::DEBUG;
05454584 913 $dir ||= $self->{ID};
9d61fa1d 914 my($cwd) = CPAN::anycwd();
05454584 915 chdir $dir or Carp::croak("Can't chdir to $dir: $!");
f14b5cec
JH
916 my $dh = DirHandle->new(File::Spec->curdir)
917 or Carp::croak("Couldn't opendir $dir: $!");
05454584
A
918 my(@entries);
919 for ($dh->read) {
920 next if $_ eq "." || $_ eq "..";
921 if (-f $_) {
5de3f0da 922 push @entries, File::Spec->catfile($dir,$_);
05454584 923 } elsif (-d _) {
5de3f0da 924 push @entries, File::Spec->catdir($dir,$_);
5f05dabc 925 } else {
c356248b 926 $CPAN::Frontend->mywarn("Warning: weird direntry in $dir: $_\n");
5f05dabc 927 }
5f05dabc 928 }
05454584 929 chdir $cwd or Carp::croak("Can't chdir to $cwd: $!");
e50380aa 930 sort { -M $b <=> -M $a} @entries;
5f05dabc 931}
932
05454584
A
933#-> sub CPAN::CacheMgr::disk_usage ;
934sub disk_usage {
935 my($self,$dir) = @_;
09d9d230
A
936 return if exists $self->{SIZE}{$dir};
937 return if $CPAN::Signal;
938 my($Du) = 0;
05454584
A
939 find(
940 sub {
f14b5cec
JH
941 $File::Find::prune++ if $CPAN::Signal;
942 return if -l $_;
943 if ($^O eq 'MacOS') {
944 require Mac::Files;
945 my $cat = Mac::Files::FSpGetCatInfo($_);
911a92db 946 $Du += $cat->ioFlLgLen() + $cat->ioFlRLgLen() if $cat;
f14b5cec
JH
947 } else {
948 $Du += (-s _);
949 }
05454584
A
950 },
951 $dir
952 );
09d9d230 953 return if $CPAN::Signal;
05454584
A
954 $self->{SIZE}{$dir} = $Du/1024/1024;
955 push @{$self->{FIFO}}, $dir;
956 $self->debug("measured $dir is $Du") if $CPAN::DEBUG;
957 $self->{DU} += $Du/1024/1024;
05454584 958 $self->{DU};
5f05dabc 959}
960
05454584
A
961#-> sub CPAN::CacheMgr::force_clean_cache ;
962sub force_clean_cache {
963 my($self,$dir) = @_;
09d9d230 964 return unless -e $dir;
05454584
A
965 $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}")
966 if $CPAN::DEBUG;
967 File::Path::rmtree($dir);
968 $self->{DU} -= $self->{SIZE}{$dir};
969 delete $self->{SIZE}{$dir};
5f05dabc 970}
971
05454584
A
972#-> sub CPAN::CacheMgr::new ;
973sub new {
974 my $class = shift;
e50380aa
A
975 my $time = time;
976 my($debug,$t2);
977 $debug = "";
05454584
A
978 my $self = {
979 ID => $CPAN::Config->{'build_dir'},
980 MAX => $CPAN::Config->{'build_cache'},
f610777f 981 SCAN => $CPAN::Config->{'scan_cache'} || 'atstart',
05454584
A
982 DU => 0
983 };
984 File::Path::mkpath($self->{ID});
985 my $dh = DirHandle->new($self->{ID});
986 bless $self, $class;
f610777f
A
987 $self->scan_cache;
988 $t2 = time;
989 $debug .= "timing of CacheMgr->new: ".($t2 - $time);
990 $time = $t2;
991 CPAN->debug($debug) if $CPAN::DEBUG;
992 $self;
993}
994
995#-> sub CPAN::CacheMgr::scan_cache ;
996sub scan_cache {
997 my $self = shift;
998 return if $self->{SCAN} eq 'never';
999 $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}")
1000 unless $self->{SCAN} eq 'atstart';
09d9d230
A
1001 $CPAN::Frontend->myprint(
1002 sprintf("Scanning cache %s for sizes\n",
1003 $self->{ID}));
f610777f 1004 my $e;
09d9d230 1005 for $e ($self->entries($self->{ID})) {
05454584 1006 next if $e eq ".." || $e eq ".";
05454584 1007 $self->disk_usage($e);
09d9d230 1008 return if $CPAN::Signal;
5f05dabc 1009 }
09d9d230 1010 $self->tidyup;
5f05dabc 1011}
1012
05454584
A
1013package CPAN::Debug;
1014
1015#-> sub CPAN::Debug::debug ;
1016sub debug {
1017 my($self,$arg) = @_;
1018 my($caller,$func,$line,@rest) = caller(1); # caller(0) eg
1019 # Complete, caller(1)
1020 # eg readline
1021 ($caller) = caller(0);
1022 $caller =~ s/.*:://;
55e314ee 1023 $arg = "" unless defined $arg;
c356248b 1024 my $rest = join "|", map { defined $_ ? $_ : "UNDEF" } @rest;
05454584 1025 if ($CPAN::DEBUG{$caller} & $CPAN::DEBUG){
55e314ee 1026 if ($arg and ref $arg) {
05454584
A
1027 eval { require Data::Dumper };
1028 if ($@) {
c356248b 1029 $CPAN::Frontend->myprint($arg->as_string);
05454584 1030 } else {
c356248b 1031 $CPAN::Frontend->myprint(Data::Dumper::Dumper($arg));
5f05dabc 1032 }
1033 } else {
c356248b 1034 $CPAN::Frontend->myprint("Debug($caller:$func,$line,[$rest]): $arg\n");
5f05dabc 1035 }
05454584
A
1036 }
1037}
1038
1039package CPAN::Config;
05454584
A
1040
1041#-> sub CPAN::Config::edit ;
de34a54b 1042# returns true on successful action
05454584 1043sub edit {
5e05dca5 1044 my($self,@args) = @_;
05454584 1045 return unless @args;
5e05dca5 1046 CPAN->debug("self[$self]args[".join(" | ",@args)."]");
05454584
A
1047 my($o,$str,$func,$args,$key_exists);
1048 $o = shift @args;
1049 if($can{$o}) {
5e05dca5 1050 $self->$o(@args);
05454584
A
1051 return 1;
1052 } else {
05d2a450 1053 CPAN->debug("o[$o]") if $CPAN::DEBUG;
de34a54b 1054 if ($o =~ /list$/) {
05454584
A
1055 $func = shift @args;
1056 $func ||= "";
05d2a450 1057 CPAN->debug("func[$func]") if $CPAN::DEBUG;
de34a54b 1058 my $changed;
05454584
A
1059 # Let's avoid eval, it's easier to comprehend without.
1060 if ($func eq "push") {
1061 push @{$CPAN::Config->{$o}}, @args;
de34a54b 1062 $changed = 1;
05454584
A
1063 } elsif ($func eq "pop") {
1064 pop @{$CPAN::Config->{$o}};
de34a54b 1065 $changed = 1;
05454584
A
1066 } elsif ($func eq "shift") {
1067 shift @{$CPAN::Config->{$o}};
de34a54b 1068 $changed = 1;
05454584
A
1069 } elsif ($func eq "unshift") {
1070 unshift @{$CPAN::Config->{$o}}, @args;
de34a54b 1071 $changed = 1;
05454584
A
1072 } elsif ($func eq "splice") {
1073 splice @{$CPAN::Config->{$o}}, @args;
de34a54b 1074 $changed = 1;
05454584
A
1075 } elsif (@args) {
1076 $CPAN::Config->{$o} = [@args];
de34a54b 1077 $changed = 1;
05454584 1078 } else {
5e05dca5 1079 $self->prettyprint($o);
05454584 1080 }
de34a54b
JH
1081 if ($o eq "urllist" && $changed) {
1082 # reset the cached values
1083 undef $CPAN::FTP::Thesite;
1084 undef $CPAN::FTP::Themethod;
1085 }
1086 return $changed;
05454584
A
1087 } else {
1088 $CPAN::Config->{$o} = $args[0] if defined $args[0];
5e05dca5 1089 $self->prettyprint($o);
5f05dabc 1090 }
5f05dabc 1091 }
05454584
A
1092}
1093
5e05dca5
A
1094sub prettyprint {
1095 my($self,$k) = @_;
1096 my $v = $CPAN::Config->{$k};
1097 if (ref $v) {
1098 my(@report) = ref $v eq "ARRAY" ?
1099 @$v :
1100 map { sprintf(" %-18s => %s\n",
1101 $_,
1102 defined $v->{$_} ? $v->{$_} : "UNDEFINED"
1103 )} keys %$v;
1104 $CPAN::Frontend->myprint(
1105 join(
1106 "",
1107 sprintf(
1108 " %-18s\n",
1109 $k
1110 ),
1111 map {"\t$_\n"} @report
1112 )
1113 );
1114 } elsif (defined $v) {
1115 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, $v);
1116 } else {
1117 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, "UNDEFINED");
1118 }
1119}
1120
05454584
A
1121#-> sub CPAN::Config::commit ;
1122sub commit {
1123 my($self,$configpm) = @_;
1124 unless (defined $configpm){
1125 $configpm ||= $INC{"CPAN/MyConfig.pm"};
1126 $configpm ||= $INC{"CPAN/Config.pm"};
2e2b7522 1127 $configpm || Carp::confess(q{
05454584
A
1128CPAN::Config::commit called without an argument.
1129Please specify a filename where to save the configuration or try
1130"o conf init" to have an interactive course through configing.
1131});
1132 }
1133 my($mode);
1134 if (-f $configpm) {
1135 $mode = (stat $configpm)[2];
1136 if ($mode && ! -w _) {
1137 Carp::confess("$configpm is not writable");
5f05dabc 1138 }
1139 }
05454584 1140
de34a54b
JH
1141 my $msg;
1142 $msg = <<EOF unless $configpm =~ /MyConfig/;
05454584 1143
09d9d230 1144# This is CPAN.pm's systemwide configuration file. This file provides
55e314ee
A
1145# defaults for users, and the values can be changed in a per-user
1146# configuration file. The user-config file is being looked for as
1147# ~/.cpan/CPAN/MyConfig.pm.
05454584
A
1148
1149EOF
1150 $msg ||= "\n";
1151 my($fh) = FileHandle->new;
f610777f 1152 rename $configpm, "$configpm~" if -f $configpm;
6d29edf5 1153 open $fh, ">$configpm" or
9d61fa1d 1154 $CPAN::Frontend->mydie("Couldn't open >$configpm: $!");
c356248b 1155 $fh->print(qq[$msg\$CPAN::Config = \{\n]);
05454584
A
1156 foreach (sort keys %$CPAN::Config) {
1157 $fh->print(
1158 " '$_' => ",
1159 ExtUtils::MakeMaker::neatvalue($CPAN::Config->{$_}),
1160 ",\n"
1161 );
5f05dabc 1162 }
05454584 1163
c356248b 1164 $fh->print("};\n1;\n__END__\n");
05454584
A
1165 close $fh;
1166
1167 #$mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
1168 #chmod $mode, $configpm;
e50380aa 1169###why was that so? $self->defaults;
c356248b 1170 $CPAN::Frontend->myprint("commit: wrote $configpm\n");
05454584 1171 1;
5f05dabc 1172}
1173
05454584
A
1174*default = \&defaults;
1175#-> sub CPAN::Config::defaults ;
1176sub defaults {
1177 my($self) = @_;
1178 $self->unload;
1179 $self->load;
1180 1;
5f05dabc 1181}
1182
05454584
A
1183sub init {
1184 my($self) = @_;
1185 undef $CPAN::Config->{'inhibit_startup_message'}; # lazy trick to
1186 # have the least
1187 # important
1188 # variable
1189 # undefined
1190 $self->load;
1191 1;
5f05dabc 1192}
1193
c076f9f6
RB
1194# This is a piece of repeated code that is abstracted here for
1195# maintainability. RMB
1196#
1197sub _configpmtest {
1198 my($configpmdir, $configpmtest) = @_;
1199 if (-w $configpmtest) {
1200 return $configpmtest;
1201 } elsif (-w $configpmdir) {
1202 #_#_# following code dumped core on me with 5.003_11, a.k.
1203 my $configpm_bak = "$configpmtest.bak";
1204 unlink $configpm_bak if -f $configpm_bak;
1205 if( -f $configpmtest ) {
1206 if( rename $configpmtest, $configpm_bak ) {
1207 $CPAN::Frontend->mywarn(<<END)
1208Old configuration file $configpmtest
1209 moved to $configpm_bak
1210END
1211 }
1212 }
1213 my $fh = FileHandle->new;
1214 if ($fh->open(">$configpmtest")) {
1215 $fh->print("1;\n");
1216 return $configpmtest;
1217 } else {
1218 # Should never happen
1219 Carp::confess("Cannot open >$configpmtest");
1220 }
1221 } else { return }
1222}
1223
05454584
A
1224#-> sub CPAN::Config::load ;
1225sub load {
e50380aa
A
1226 my($self) = shift;
1227 my(@miss);
f610777f 1228 use Carp;
c356248b
A
1229 eval {require CPAN::Config;}; # We eval because of some
1230 # MakeMaker problems
09d9d230 1231 unless ($dot_cpan++){
5de3f0da 1232 unshift @INC, File::Spec->catdir($ENV{HOME},".cpan");
09d9d230 1233 eval {require CPAN::MyConfig;}; # where you can override
c356248b 1234 # system wide settings
09d9d230
A
1235 shift @INC;
1236 }
c4d24d4c
A
1237 return unless @miss = $self->missing_config_data;
1238
e50380aa 1239 require CPAN::FirstTime;
55e314ee 1240 my($configpm,$fh,$redo,$theycalled);
e50380aa 1241 $redo ||= "";
55e314ee 1242 $theycalled++ if @miss==1 && $miss[0] eq 'inhibit_startup_message';
e50380aa
A
1243 if (defined $INC{"CPAN/Config.pm"} && -w $INC{"CPAN/Config.pm"}) {
1244 $configpm = $INC{"CPAN/Config.pm"};
1245 $redo++;
1246 } elsif (defined $INC{"CPAN/MyConfig.pm"} && -w $INC{"CPAN/MyConfig.pm"}) {
1247 $configpm = $INC{"CPAN/MyConfig.pm"};
1248 $redo++;
1249 } else {
1250 my($path_to_cpan) = File::Basename::dirname($INC{"CPAN.pm"});
5de3f0da
DR
1251 my($configpmdir) = File::Spec->catdir($path_to_cpan,"CPAN");
1252 my($configpmtest) = File::Spec->catfile($configpmdir,"Config.pm");
e50380aa 1253 if (-d $configpmdir or File::Path::mkpath($configpmdir)) {
c076f9f6 1254 $configpm = _configpmtest($configpmdir,$configpmtest);
e50380aa
A
1255 }
1256 unless ($configpm) {
5de3f0da 1257 $configpmdir = File::Spec->catdir($ENV{HOME},".cpan","CPAN");
e50380aa 1258 File::Path::mkpath($configpmdir);
5de3f0da 1259 $configpmtest = File::Spec->catfile($configpmdir,"MyConfig.pm");
c076f9f6
RB
1260 $configpm = _configpmtest($configpmdir,$configpmtest);
1261 unless ($configpm) {
e50380aa
A
1262 Carp::confess(qq{WARNING: CPAN.pm is unable to }.
1263 qq{create a configuration file.});
1264 }
1265 }
1266 }
1267 local($") = ", ";
f610777f 1268 $CPAN::Frontend->myprint(<<END) if $redo && ! $theycalled;
e50380aa
A
1269We have to reconfigure CPAN.pm due to following uninitialized parameters:
1270
1271@miss
f610777f 1272END
c356248b 1273 $CPAN::Frontend->myprint(qq{
05454584 1274$configpm initialized.
c356248b 1275});
e50380aa
A
1276 sleep 2;
1277 CPAN::FirstTime::init($configpm);
5f05dabc 1278}
1279
c4d24d4c
A
1280#-> sub CPAN::Config::missing_config_data ;
1281sub missing_config_data {
e50380aa 1282 my(@miss);
c4d24d4c
A
1283 for (
1284 "cpan_home", "keep_source_where", "build_dir", "build_cache",
5a5fac02
JH
1285 "scan_cache", "index_expire", "gzip", "tar", "unzip", "make",
1286 "pager",
c4d24d4c
A
1287 "makepl_arg", "make_arg", "make_install_arg", "urllist",
1288 "inhibit_startup_message", "ftp_proxy", "http_proxy", "no_proxy",
1289 "prerequisites_policy",
5a5fac02 1290 "cache_metadata",
c4d24d4c 1291 ) {
e50380aa 1292 push @miss, $_ unless defined $CPAN::Config->{$_};
5f05dabc 1293 }
e50380aa 1294 return @miss;
5f05dabc 1295}
1296
05454584
A
1297#-> sub CPAN::Config::unload ;
1298sub unload {
1299 delete $INC{'CPAN/MyConfig.pm'};
1300 delete $INC{'CPAN/Config.pm'};
5f05dabc 1301}
1302
05454584
A
1303#-> sub CPAN::Config::help ;
1304sub help {
2e2b7522 1305 $CPAN::Frontend->myprint(q[
05454584
A
1306Known options:
1307 defaults reload default config values from disk
1308 commit commit session changes to disk
1309 init go through a dialog to set all parameters
5f05dabc 1310
911a92db
GS
1311You may edit key values in the follow fashion (the "o" is a literal
1312letter o):
5f05dabc 1313
05454584 1314 o conf build_cache 15
5f05dabc 1315
05454584 1316 o conf build_dir "/foo/bar"
5f05dabc 1317
05454584 1318 o conf urllist shift
5f05dabc 1319
05454584 1320 o conf urllist unshift ftp://ftp.foo.bar/
5f05dabc 1321
2e2b7522 1322]);
05454584
A
1323 undef; #don't reprint CPAN::Config
1324}
5f05dabc 1325
55e314ee
A
1326#-> sub CPAN::Config::cpl ;
1327sub cpl {
05454584
A
1328 my($word,$line,$pos) = @_;
1329 $word ||= "";
c356248b
A
1330 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
1331 my(@words) = split " ", substr($line,0,$pos+1);
1332 if (
09d9d230
A
1333 defined($words[2])
1334 and
1335 (
1336 $words[2] =~ /list$/ && @words == 3
1337 ||
1338 $words[2] =~ /list$/ && @words == 4 && length($word)
1339 )
c356248b
A
1340 ) {
1341 return grep /^\Q$word\E/, qw(splice shift unshift pop push);
1342 } elsif (@words >= 4) {
1343 return ();
1344 }
05454584
A
1345 my(@o_conf) = (keys %CPAN::Config::can, keys %$CPAN::Config);
1346 return grep /^\Q$word\E/, @o_conf;
1347}
1348
1349package CPAN::Shell;
5f05dabc 1350
05454584
A
1351#-> sub CPAN::Shell::h ;
1352sub h {
1353 my($class,$about) = @_;
1354 if (defined $about) {
c356248b 1355 $CPAN::Frontend->myprint("Detailed help not yet implemented\n");
05454584 1356 } else {
c356248b 1357 $CPAN::Frontend->myprint(q{
911a92db 1358Display Information
c049f953
JH
1359 command argument description
1360 a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules
1361 i WORD or /REGEXP/ about anything of above
1362 r NONE reinstall recommendations
1363 ls AUTHOR about files in the author's directory
911a92db
GS
1364
1365Download, Test, Make, Install...
1366 get download
1367 make make (implies get)
c049f953
JH
1368 test MODULES, make test (implies make)
1369 install DISTS, BUNDLES make install (implies test)
911a92db
GS
1370 clean make clean
1371 look open subshell in these dists' directories
1372 readme display these dists' README files
1373
1374Other
1375 h,? display this menu ! perl-code eval a perl command
1376 o conf [opt] set and query options q quit the cpan shell
1377 reload cpan load CPAN.pm again reload index load newer indices
1378 autobundle Snapshot force cmd unconditionally do cmd});
05454584
A
1379 }
1380}
da199366 1381
09d9d230
A
1382*help = \&h;
1383
05454584 1384#-> sub CPAN::Shell::a ;
de34a54b
JH
1385sub a {
1386 my($self,@arg) = @_;
1387 # authors are always UPPERCASE
1388 for (@arg) {
c049f953 1389 $_ = uc $_ unless /=/;
de34a54b
JH
1390 }
1391 $CPAN::Frontend->myprint($self->format_result('Author',@arg));
1392}
6d29edf5 1393
8d97e4a1
JH
1394#-> sub CPAN::Shell::ls ;
1395sub ls {
1396 my($self,@arg) = @_;
c049f953 1397 my @accept;
8d97e4a1 1398 for (@arg) {
c049f953 1399 unless (/^[A-Z\-]+$/i) {
5fc0f0f6 1400 $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author\n");
c049f953
JH
1401 next;
1402 }
1403 push @accept, uc $_;
8d97e4a1 1404 }
c049f953 1405 for my $a (@accept){
8d97e4a1
JH
1406 my $author = $self->expand('Author',$a) or die "No author found for $a";
1407 $author->ls;
1408 }
1409}
6d29edf5 1410
8d97e4a1 1411#-> sub CPAN::Shell::local_bundles ;
6d29edf5 1412sub local_bundles {
05454584 1413 my($self,@which) = @_;
55e314ee 1414 my($incdir,$bdir,$dh);
05454584 1415 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) {
8d97e4a1
JH
1416 my @bbase = "Bundle";
1417 while (my $bbase = shift @bbase) {
5de3f0da 1418 $bdir = File::Spec->catdir($incdir,split /::/, $bbase);
8d97e4a1
JH
1419 CPAN->debug("bdir[$bdir]\@bbase[@bbase]") if $CPAN::DEBUG;
1420 if ($dh = DirHandle->new($bdir)) { # may fail
1421 my($entry);
1422 for $entry ($dh->read) {
c049f953 1423 next if $entry =~ /^\./;
5de3f0da 1424 if (-d File::Spec->catdir($bdir,$entry)){
8d97e4a1
JH
1425 push @bbase, "$bbase\::$entry";
1426 } else {
1427 next unless $entry =~ s/\.pm(?!\n)\Z//;
1428 $CPAN::META->instance('CPAN::Bundle',"$bbase\::$entry");
1429 }
1430 }
1431 }
1432 }
05454584 1433 }
6d29edf5
JH
1434}
1435
1436#-> sub CPAN::Shell::b ;
1437sub b {
1438 my($self,@which) = @_;
1439 CPAN->debug("which[@which]") if $CPAN::DEBUG;
1440 $self->local_bundles;
c356248b 1441 $CPAN::Frontend->myprint($self->format_result('Bundle',@which));
05454584 1442}
6d29edf5 1443
05454584 1444#-> sub CPAN::Shell::d ;
c356248b 1445sub d { $CPAN::Frontend->myprint(shift->format_result('Distribution',@_));}
6d29edf5 1446
05454584 1447#-> sub CPAN::Shell::m ;
f610777f 1448sub m { # emacs confused here }; sub mimimimimi { # emacs in sync here
35576f8c
A
1449 my $self = shift;
1450 $CPAN::Frontend->myprint($self->format_result('Module',@_));
f610777f 1451}
da199366 1452
05454584
A
1453#-> sub CPAN::Shell::i ;
1454sub i {
1455 my($self) = shift;
1456 my(@args) = @_;
1457 my(@type,$type,@m);
1458 @type = qw/Author Bundle Distribution Module/;
1459 @args = '/./' unless @args;
1460 my(@result);
1461 for $type (@type) {
1462 push @result, $self->expand($type,@args);
1463 }
8d97e4a1 1464 my $result = @result == 1 ?
05454584 1465 $result[0]->as_string :
8d97e4a1
JH
1466 @result == 0 ?
1467 "No objects found of any type for argument @args\n" :
1468 join("",
1469 (map {$_->as_glimpse} @result),
1470 scalar @result, " items found\n",
1471 );
c356248b 1472 $CPAN::Frontend->myprint($result);
da199366 1473}
da199366 1474
05454584 1475#-> sub CPAN::Shell::o ;
5e05dca5 1476
6d29edf5
JH
1477# CPAN::Shell::o and CPAN::Config::edit are closely related. 'o conf'
1478# should have been called set and 'o debug' maybe 'set debug'
05454584
A
1479sub o {
1480 my($self,$o_type,@o_what) = @_;
1481 $o_type ||= "";
1482 CPAN->debug("o_type[$o_type] o_what[".join(" | ",@o_what)."]\n");
1483 if ($o_type eq 'conf') {
1484 shift @o_what if @o_what && $o_what[0] eq 'help';
5e05dca5 1485 if (!@o_what) { # print all things, "o conf"
05454584 1486 my($k,$v);
09d9d230
A
1487 $CPAN::Frontend->myprint("CPAN::Config options");
1488 if (exists $INC{'CPAN/Config.pm'}) {
1489 $CPAN::Frontend->myprint(" from $INC{'CPAN/Config.pm'}");
1490 }
1491 if (exists $INC{'CPAN/MyConfig.pm'}) {
1492 $CPAN::Frontend->myprint(" and $INC{'CPAN/MyConfig.pm'}");
1493 }
1494 $CPAN::Frontend->myprint(":\n");
05454584
A
1495 for $k (sort keys %CPAN::Config::can) {
1496 $v = $CPAN::Config::can{$k};
c356248b 1497 $CPAN::Frontend->myprint(sprintf " %-18s %s\n", $k, $v);
05454584 1498 }
c356248b 1499 $CPAN::Frontend->myprint("\n");
05454584 1500 for $k (sort keys %$CPAN::Config) {
5e05dca5 1501 CPAN::Config->prettyprint($k);
10b2abe6 1502 }
c356248b 1503 $CPAN::Frontend->myprint("\n");
05454584 1504 } elsif (!CPAN::Config->edit(@o_what)) {
6d29edf5
JH
1505 $CPAN::Frontend->myprint(qq{Type 'o conf' to view configuration }.
1506 qq{edit options\n\n});
5f05dabc 1507 }
05454584
A
1508 } elsif ($o_type eq 'debug') {
1509 my(%valid);
1510 @o_what = () if defined $o_what[0] && $o_what[0] =~ /help/i;
1511 if (@o_what) {
1512 while (@o_what) {
1513 my($what) = shift @o_what;
8d97e4a1
JH
1514 if ($what =~ s/^-// && exists $CPAN::DEBUG{$what}) {
1515 $CPAN::DEBUG &= $CPAN::DEBUG ^ $CPAN::DEBUG{$what};
1516 next;
1517 }
05454584
A
1518 if ( exists $CPAN::DEBUG{$what} ) {
1519 $CPAN::DEBUG |= $CPAN::DEBUG{$what};
1520 } elsif ($what =~ /^\d/) {
1521 $CPAN::DEBUG = $what;
1522 } elsif (lc $what eq 'all') {
1523 my($max) = 0;
1524 for (values %CPAN::DEBUG) {
1525 $max += $_;
10b2abe6 1526 }
05454584 1527 $CPAN::DEBUG = $max;
10b2abe6 1528 } else {
d4fd5c69 1529 my($known) = 0;
05454584
A
1530 for (keys %CPAN::DEBUG) {
1531 next unless lc($_) eq lc($what);
1532 $CPAN::DEBUG |= $CPAN::DEBUG{$_};
d4fd5c69 1533 $known = 1;
10b2abe6 1534 }
c356248b
A
1535 $CPAN::Frontend->myprint("unknown argument [$what]\n")
1536 unless $known;
10b2abe6
CS
1537 }
1538 }
05454584 1539 } else {
911a92db
GS
1540 my $raw = "Valid options for debug are ".
1541 join(", ",sort(keys %CPAN::DEBUG), 'all').
1542 qq{ or a number. Completion works on the options. }.
1543 qq{Case is ignored.};
1544 require Text::Wrap;
1545 $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw));
1546 $CPAN::Frontend->myprint("\n\n");
05454584
A
1547 }
1548 if ($CPAN::DEBUG) {
c356248b 1549 $CPAN::Frontend->myprint("Options set for debugging:\n");
05454584
A
1550 my($k,$v);
1551 for $k (sort {$CPAN::DEBUG{$a} <=> $CPAN::DEBUG{$b}} keys %CPAN::DEBUG) {
1552 $v = $CPAN::DEBUG{$k};
05d2a450
A
1553 $CPAN::Frontend->myprint(sprintf " %-14s(%s)\n", $k, $v)
1554 if $v & $CPAN::DEBUG;
05454584
A
1555 }
1556 } else {
c356248b 1557 $CPAN::Frontend->myprint("Debugging turned off completely.\n");
10b2abe6 1558 }
05454584 1559 } else {
c356248b 1560 $CPAN::Frontend->myprint(qq{
05454584
A
1561Known options:
1562 conf set or get configuration variables
1563 debug set or get debugging options
c356248b 1564});
5f05dabc 1565 }
5f05dabc 1566}
1567
6d29edf5 1568sub paintdots_onreload {
36263cb3
GS
1569 my($ref) = shift;
1570 sub {
5fc0f0f6 1571 if ( $_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) {
36263cb3
GS
1572 my($subr) = $1;
1573 ++$$ref;
1574 local($|) = 1;
1575 # $CPAN::Frontend->myprint(".($subr)");
1576 $CPAN::Frontend->myprint(".");
1577 return;
1578 }
1579 warn @_;
1580 };
1581}
1582
05454584
A
1583#-> sub CPAN::Shell::reload ;
1584sub reload {
d4fd5c69
A
1585 my($self,$command,@arg) = @_;
1586 $command ||= "";
1587 $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG;
1588 if ($command =~ /cpan/i) {
5fc0f0f6
JH
1589 for my $f (qw(CPAN.pm CPAN/FirstTime.pm)) {
1590 next unless $INC{$f};
1591 CPAN->debug("reloading the whole $f") if $CPAN::DEBUG;
1592 my $fh = FileHandle->new($INC{$f});
1593 local($/);
1594 my $redef = 0;
1595 local($SIG{__WARN__}) = paintdots_onreload(\$redef);
1596 eval <$fh>;
1597 warn $@ if $@;
1598 $CPAN::Frontend->myprint("\n$redef subroutines redefined\n");
1599 }
d4fd5c69 1600 } elsif ($command =~ /index/) {
2e2b7522 1601 CPAN::Index->force_reload;
d4fd5c69 1602 } else {
2e2b7522 1603 $CPAN::Frontend->myprint(qq{cpan re-evals the CPAN.pm file
f14b5cec 1604index re-reads the index files\n});
05454584
A
1605 }
1606}
1607
1608#-> sub CPAN::Shell::_binary_extensions ;
1609sub _binary_extensions {
1610 my($self) = shift @_;
1611 my(@result,$module,%seen,%need,$headerdone);
1612 for $module ($self->expand('Module','/./')) {
1613 my $file = $module->cpan_file;
1614 next if $file eq "N/A";
1615 next if $file =~ /^Contact Author/;
05d2a450
A
1616 my $dist = $CPAN::META->instance('CPAN::Distribution',$file);
1617 next if $dist->isa_perl;
05454584
A
1618 next unless $module->xs_file;
1619 local($|) = 1;
c356248b 1620 $CPAN::Frontend->myprint(".");
05454584
A
1621 push @result, $module;
1622 }
1623# print join " | ", @result;
c356248b 1624 $CPAN::Frontend->myprint("\n");
05454584
A
1625 return @result;
1626}
1627
1628#-> sub CPAN::Shell::recompile ;
1629sub recompile {
1630 my($self) = shift @_;
1631 my($module,@module,$cpan_file,%dist);
1632 @module = $self->_binary_extensions();
c356248b
A
1633 for $module (@module){ # we force now and compile later, so we
1634 # don't do it twice
05454584
A
1635 $cpan_file = $module->cpan_file;
1636 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
1637 $pack->force;
1638 $dist{$cpan_file}++;
1639 }
1640 for $cpan_file (sort keys %dist) {
c356248b 1641 $CPAN::Frontend->myprint(" CPAN: Recompiling $cpan_file\n\n");
05454584
A
1642 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
1643 $pack->install;
1644 $CPAN::Signal = 0; # it's tempting to reset Signal, so we can
1645 # stop a package from recompiling,
1646 # e.g. IO-1.12 when we have perl5.003_10
1647 }
1648}
1649
1650#-> sub CPAN::Shell::_u_r_common ;
1651sub _u_r_common {
1652 my($self) = shift @_;
1653 my($what) = shift @_;
1654 CPAN->debug("self[$self] what[$what] args[@_]") if $CPAN::DEBUG;
c4d24d4c
A
1655 Carp::croak "Usage: \$obj->_u_r_common(a|r|u)" unless
1656 $what && $what =~ /^[aru]$/;
05454584
A
1657 my(@args) = @_;
1658 @args = '/./' unless @args;
c356248b
A
1659 my(@result,$module,%seen,%need,$headerdone,
1660 $version_undefs,$version_zeroes);
1661 $version_undefs = $version_zeroes = 0;
9d61fa1d 1662 my $sprintf = "%s%-25s%s %9s %9s %s\n";
6d29edf5
JH
1663 my @expand = $self->expand('Module',@args);
1664 my $expand = scalar @expand;
1665 if (0) { # Looks like noise to me, was very useful for debugging
1666 # for metadata cache
1667 $CPAN::Frontend->myprint(sprintf "%d matches in the database\n", $expand);
1668 }
1669 for $module (@expand) {
05454584
A
1670 my $file = $module->cpan_file;
1671 next unless defined $file; # ??
6d29edf5 1672 my($latest) = $module->cpan_version;
05454584
A
1673 my($inst_file) = $module->inst_file;
1674 my($have);
09d9d230 1675 return if $CPAN::Signal;
05454584
A
1676 if ($inst_file){
1677 if ($what eq "a") {
6d29edf5 1678 $have = $module->inst_version;
05454584 1679 } elsif ($what eq "r") {
6d29edf5 1680 $have = $module->inst_version;
05454584 1681 local($^W) = 0;
c356248b
A
1682 if ($have eq "undef"){
1683 $version_undefs++;
1684 } elsif ($have == 0){
1685 $version_zeroes++;
1686 }
5e05dca5 1687 next unless CPAN::Version->vgt($latest, $have);
c356248b
A
1688# to be pedantic we should probably say:
1689# && !($have eq "undef" && $latest ne "undef" && $latest gt "");
1690# to catch the case where CPAN has a version 0 and we have a version undef
05454584
A
1691 } elsif ($what eq "u") {
1692 next;
1693 }
1694 } else {
1695 if ($what eq "a") {
1696 next;
1697 } elsif ($what eq "r") {
1698 next;
1699 } elsif ($what eq "u") {
1700 $have = "-";
1701 }
1702 }
1703 return if $CPAN::Signal; # this is sometimes lengthy
1704 $seen{$file} ||= 0;
1705 if ($what eq "a") {
1706 push @result, sprintf "%s %s\n", $module->id, $have;
1707 } elsif ($what eq "r") {
1708 push @result, $module->id;
1709 next if $seen{$file}++;
1710 } elsif ($what eq "u") {
1711 push @result, $module->id;
1712 next if $seen{$file}++;
1713 next if $file =~ /^Contact/;
1714 }
1715 unless ($headerdone++){
c356248b
A
1716 $CPAN::Frontend->myprint("\n");
1717 $CPAN::Frontend->myprint(sprintf(
9d61fa1d
A
1718 $sprintf,
1719 "",
1720 "Package namespace",
1721 "",
1722 "installed",
1723 "latest",
1724 "in CPAN file"
1725 ));
05454584 1726 }
9d61fa1d
A
1727 my $color_on = "";
1728 my $color_off = "";
1729 if (
1730 $COLOR_REGISTERED
1731 &&
1732 $CPAN::META->has_inst("Term::ANSIColor")
1733 &&
1734 $module->{RO}{description}
1735 ) {
1736 $color_on = Term::ANSIColor::color("green");
1737 $color_off = Term::ANSIColor::color("reset");
1738 }
05d2a450 1739 $CPAN::Frontend->myprint(sprintf $sprintf,
9d61fa1d 1740 $color_on,
05d2a450 1741 $module->id,
9d61fa1d 1742 $color_off,
05d2a450
A
1743 $have,
1744 $latest,
1745 $file);
05454584
A
1746 $need{$module->id}++;
1747 }
1748 unless (%need) {
1749 if ($what eq "u") {
c356248b 1750 $CPAN::Frontend->myprint("No modules found for @args\n");
05454584 1751 } elsif ($what eq "r") {
c356248b 1752 $CPAN::Frontend->myprint("All modules are up to date for @args\n");
05454584
A
1753 }
1754 }
c356248b
A
1755 if ($what eq "r") {
1756 if ($version_zeroes) {
1757 my $s_has = $version_zeroes > 1 ? "s have" : " has";
1758 $CPAN::Frontend->myprint(qq{$version_zeroes installed module$s_has }.
1759 qq{a version number of 0\n});
1760 }
1761 if ($version_undefs) {
1762 my $s_has = $version_undefs > 1 ? "s have" : " has";
1763 $CPAN::Frontend->myprint(qq{$version_undefs installed module$s_has no }.
1764 qq{parseable version number\n});
1765 }
05454584
A
1766 }
1767 @result;
1768}
1769
1770#-> sub CPAN::Shell::r ;
1771sub r {
1772 shift->_u_r_common("r",@_);
1773}
1774
1775#-> sub CPAN::Shell::u ;
1776sub u {
1777 shift->_u_r_common("u",@_);
1778}
1779
1780#-> sub CPAN::Shell::autobundle ;
1781sub autobundle {
1782 my($self) = shift;
36263cb3 1783 CPAN::Config->load unless $CPAN::Config_loaded++;
05454584 1784 my(@bundle) = $self->_u_r_common("a",@_);
5de3f0da 1785 my($todir) = File::Spec->catdir($CPAN::Config->{'cpan_home'},"Bundle");
05454584
A
1786 File::Path::mkpath($todir);
1787 unless (-d $todir) {
c356248b 1788 $CPAN::Frontend->myprint("Couldn't mkdir $todir for some reason\n");
05454584
A
1789 return;
1790 }
1791 my($y,$m,$d) = (localtime)[5,4,3];
1792 $y+=1900;
1793 $m++;
1794 my($c) = 0;
1795 my($me) = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, $c;
5de3f0da 1796 my($to) = File::Spec->catfile($todir,"$me.pm");
05454584
A
1797 while (-f $to) {
1798 $me = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, ++$c;
5de3f0da 1799 $to = File::Spec->catfile($todir,"$me.pm");
05454584
A
1800 }
1801 my($fh) = FileHandle->new(">$to") or Carp::croak "Can't open >$to: $!";
1802 $fh->print(
1803 "package Bundle::$me;\n\n",
1804 "\$VERSION = '0.01';\n\n",
1805 "1;\n\n",
1806 "__END__\n\n",
1807 "=head1 NAME\n\n",
1808 "Bundle::$me - Snapshot of installation on ",
1809 $Config::Config{'myhostname'},
1810 " on ",
1811 scalar(localtime),
1812 "\n\n=head1 SYNOPSIS\n\n",
1813 "perl -MCPAN -e 'install Bundle::$me'\n\n",
1814 "=head1 CONTENTS\n\n",
1815 join("\n", @bundle),
1816 "\n\n=head1 CONFIGURATION\n\n",
1817 Config->myconfig,
1818 "\n\n=head1 AUTHOR\n\n",
1819 "This Bundle has been generated automatically ",
1820 "by the autobundle routine in CPAN.pm.\n",
1821 );
1822 $fh->close;
c356248b
A
1823 $CPAN::Frontend->myprint("\nWrote bundle file
1824 $to\n\n");
05454584
A
1825}
1826
6d29edf5
JH
1827#-> sub CPAN::Shell::expandany ;
1828sub expandany {
1829 my($self,$s) = @_;
1830 CPAN->debug("s[$s]") if $CPAN::DEBUG;
1831 if ($s =~ m|/|) { # looks like a file
8d97e4a1 1832 $s = CPAN::Distribution->normalize($s);
6d29edf5
JH
1833 return $CPAN::META->instance('CPAN::Distribution',$s);
1834 # Distributions spring into existence, not expand
1835 } elsif ($s =~ m|^Bundle::|) {
1836 $self->local_bundles; # scanning so late for bundles seems
1837 # both attractive and crumpy: always
1838 # current state but easy to forget
1839 # somewhere
1840 return $self->expand('Bundle',$s);
1841 } else {
1842 return $self->expand('Module',$s)
1843 if $CPAN::META->exists('CPAN::Module',$s);
1844 }
1845 return;
1846}
1847
05454584
A
1848#-> sub CPAN::Shell::expand ;
1849sub expand {
1850 shift;
1851 my($type,@args) = @_;
1852 my($arg,@m);
8d97e4a1 1853 CPAN->debug("type[$type]args[@args]") if $CPAN::DEBUG;
05454584 1854 for $arg (@args) {
6d29edf5 1855 my($regex,$command);
05454584
A
1856 if ($arg =~ m|^/(.*)/$|) {
1857 $regex = $1;
8d97e4a1
JH
1858 } elsif ($arg =~ m/=/) {
1859 $command = 1;
6d29edf5 1860 }
05454584
A
1861 my $class = "CPAN::$type";
1862 my $obj;
8d97e4a1
JH
1863 CPAN->debug(sprintf "class[%s]regex[%s]command[%s]",
1864 $class,
1865 defined $regex ? $regex : "UNDEFINED",
1866 $command || "UNDEFINED",
1867 ) if $CPAN::DEBUG;
05454584 1868 if (defined $regex) {
6d29edf5
JH
1869 for $obj (
1870 sort
1871 {$a->id cmp $b->id}
1872 $CPAN::META->all_objects($class)
1873 ) {
1874 unless ($obj->id){
1875 # BUG, we got an empty object somewhere
8d97e4a1 1876 require Data::Dumper;
6d29edf5 1877 CPAN->debug(sprintf(
8d97e4a1 1878 "Bug in CPAN: Empty id on obj[%s][%s]",
6d29edf5 1879 $obj,
8d97e4a1 1880 Data::Dumper::Dumper($obj)
6d29edf5
JH
1881 )) if $CPAN::DEBUG;
1882 next;
1883 }
1884 push @m, $obj
1885 if $obj->id =~ /$regex/i
1886 or
1887 (
1888 (
1889 $] < 5.00303 ### provide sort of
1890 ### compatibility with 5.003
1891 ||
1892 $obj->can('name')
1893 )
1894 &&
1895 $obj->name =~ /$regex/i
1896 );
1897 }
1898 } elsif ($command) {
8d97e4a1
JH
1899 die "equal sign in command disabled (immature interface), ".
1900 "you can set
1901 ! \$CPAN::Shell::ADVANCED_QUERY=1
1902to enable it. But please note, this is HIGHLY EXPERIMENTAL code
1903that may go away anytime.\n"
1904 unless $ADVANCED_QUERY;
1905 my($method,$criterion) = $arg =~ /(.+?)=(.+)/;
1906 my($matchcrit) = $criterion =~ m/^~(.+)/;
6d29edf5
JH
1907 for my $self (
1908 sort
1909 {$a->id cmp $b->id}
1910 $CPAN::META->all_objects($class)
1911 ) {
8d97e4a1
JH
1912 my $lhs = $self->$method() or next; # () for 5.00503
1913 if ($matchcrit) {
1914 push @m, $self if $lhs =~ m/$matchcrit/;
1915 } else {
1916 push @m, $self if $lhs eq $criterion;
1917 }
6d29edf5 1918 }
05454584
A
1919 } else {
1920 my($xarg) = $arg;
1921 if ( $type eq 'Bundle' ) {
1922 $xarg =~ s/^(Bundle::)?(.*)/Bundle::$2/;
8d97e4a1
JH
1923 } elsif ($type eq "Distribution") {
1924 $xarg = CPAN::Distribution->normalize($arg);
1925 }
05454584
A
1926 if ($CPAN::META->exists($class,$xarg)) {
1927 $obj = $CPAN::META->instance($class,$xarg);
1928 } elsif ($CPAN::META->exists($class,$arg)) {
1929 $obj = $CPAN::META->instance($class,$arg);
1930 } else {
1931 next;
1932 }
1933 push @m, $obj;
1934 }
1935 }
e50380aa 1936 return wantarray ? @m : $m[0];
05454584
A
1937}
1938
1939#-> sub CPAN::Shell::format_result ;
1940sub format_result {
1941 my($self) = shift;
1942 my($type,@args) = @_;
1943 @args = '/./' unless @args;
1944 my(@result) = $self->expand($type,@args);
8d97e4a1 1945 my $result = @result == 1 ?
05454584 1946 $result[0]->as_string :
8d97e4a1
JH
1947 @result == 0 ?
1948 "No objects of type $type found for argument @args\n" :
1949 join("",
1950 (map {$_->as_glimpse} @result),
1951 scalar @result, " items found\n",
1952 );
05454584
A
1953 $result;
1954}
1955
c356248b
A
1956# The only reason for this method is currently to have a reliable
1957# debugging utility that reveals which output is going through which
1958# channel. No, I don't like the colors ;-)
8d97e4a1
JH
1959
1960#-> sub CPAN::Shell::print_ornameted ;
c356248b
A
1961sub print_ornamented {
1962 my($self,$what,$ornament) = @_;
1963 my $longest = 0;
8d97e4a1 1964 return unless defined $what;
c356248b 1965
8d97e4a1
JH
1966 if ($CPAN::Config->{term_is_latin}){
1967 # courtesy jhi:
1968 $what
1969 =~ s{([\xC0-\xDF])([\x80-\xBF])}{chr(ord($1)<<6&0xC0|ord($2)&0x3F)}eg; #};
1970 }
1971 if ($PRINT_ORNAMENTING) {
c356248b
A
1972 unless (defined &color) {
1973 if ($CPAN::META->has_inst("Term::ANSIColor")) {
1974 import Term::ANSIColor "color";
1975 } else {
1976 *color = sub { return "" };
1977 }
1978 }
09d9d230
A
1979 my $line;
1980 for $line (split /\n/, $what) {
c356248b
A
1981 $longest = length($line) if length($line) > $longest;
1982 }
1983 my $sprintf = "%-" . $longest . "s";
1984 while ($what){
1985 $what =~ s/(.*\n?)//m;
1986 my $line = $1;
1987 last unless $line;
1988 my($nl) = chomp $line ? "\n" : "";
1989 # print "line[$line]ornament[$ornament]sprintf[$sprintf]\n";
1990 print color($ornament), sprintf($sprintf,$line), color("reset"), $nl;
1991 }
1992 } else {
5fc0f0f6
JH
1993 # chomp $what;
1994 # $what .= "\n"; # newlines unless $PRINT_ORNAMENTING
c356248b
A
1995 print $what;
1996 }
1997}
1998
1999sub myprint {
2000 my($self,$what) = @_;
8d97e4a1 2001
c356248b
A
2002 $self->print_ornamented($what, 'bold blue on_yellow');
2003}
2004
2005sub myexit {
2006 my($self,$what) = @_;
2007 $self->myprint($what);
2008 exit;
2009}
2010
2011sub mywarn {
2012 my($self,$what) = @_;
2013 $self->print_ornamented($what, 'bold red on_yellow');
2014}
2015
2016sub myconfess {
2017 my($self,$what) = @_;
2018 $self->print_ornamented($what, 'bold red on_white');
2019 Carp::confess "died";
2020}
2021
2022sub mydie {
2023 my($self,$what) = @_;
2024 $self->print_ornamented($what, 'bold red on_white');
2025 die "\n";
2026}
2027
911a92db
GS
2028sub setup_output {
2029 return if -t STDOUT;
2030 my $odef = select STDERR;
2031 $| = 1;
2032 select STDOUT;
2033 $| = 1;
2034 select $odef;
2035}
2036
05454584 2037#-> sub CPAN::Shell::rematein ;
09d9d230 2038# RE-adme||MA-ke||TE-st||IN-stall
05454584
A
2039sub rematein {
2040 shift;
2041 my($meth,@some) = @_;
2042 my $pragma = "";
2043 if ($meth eq 'force') {
2044 $pragma = $meth;
2045 $meth = shift @some;
2046 }
911a92db 2047 setup_output();
05454584 2048 CPAN->debug("pragma[$pragma]meth[$meth] some[@some]") if $CPAN::DEBUG;
6d29edf5
JH
2049
2050 # Here is the place to set "test_count" on all involved parties to
2051 # 0. We then can pass this counter on to the involved
2052 # distributions and those can refuse to test if test_count > X. In
2053 # the first stab at it we could use a 1 for "X".
2054
2055 # But when do I reset the distributions to start with 0 again?
2056 # Jost suggested to have a random or cycling interaction ID that
2057 # we pass through. But the ID is something that is just left lying
2058 # around in addition to the counter, so I'd prefer to set the
2059 # counter to 0 now, and repeat at the end of the loop. But what
2060 # about dependencies? They appear later and are not reset, they
2061 # enter the queue but not its copy. How do they get a sensible
2062 # test_count?
2063
2064 # construct the queue
2065 my($s,@s,@qcopy);
05454584
A
2066 foreach $s (@some) {
2067 my $obj;
2068 if (ref $s) {
6d29edf5 2069 CPAN->debug("s is an object[$s]") if $CPAN::DEBUG;
05454584 2070 $obj = $s;
c4d24d4c 2071 } elsif ($s =~ m|^/|) { # looks like a regexp
6d29edf5
JH
2072 $CPAN::Frontend->mywarn("Sorry, $meth with a regular expression is ".
2073 "not supported\n");
2074 sleep 2;
2075 next;
05454584 2076 } else {
6d29edf5
JH
2077 CPAN->debug("calling expandany [$s]") if $CPAN::DEBUG;
2078 $obj = CPAN::Shell->expandany($s);
05454584
A
2079 }
2080 if (ref $obj) {
6d29edf5 2081 $obj->color_cmd_tmps(0,1);
c049f953 2082 CPAN::Queue->new($obj->id);
6d29edf5 2083 push @qcopy, $obj;
05454584
A
2084 } elsif ($CPAN::META->exists('CPAN::Author',$s)) {
2085 $obj = $CPAN::META->instance('CPAN::Author',$s);
5fc0f0f6
JH
2086 if ($meth =~ /^(dump|ls)$/) {
2087 $obj->$meth();
8d97e4a1
JH
2088 } else {
2089 $CPAN::Frontend->myprint(
2090 join "",
2091 "Don't be silly, you can't $meth ",
2092 $obj->fullname,
2093 " ;-)\n"
2094 );
2095 sleep 2;
2096 }
05454584 2097 } else {
f610777f
A
2098 $CPAN::Frontend
2099 ->myprint(qq{Warning: Cannot $meth $s, }.
2100 qq{don\'t know what it is.
e50380aa
A
2101Try the command
2102
2103 i /$s/
2104
6d29edf5 2105to find objects with matching identifiers.
c356248b 2106});
6d29edf5
JH
2107 sleep 2;
2108 }
2109 }
2110
2111 # queuerunner (please be warned: when I started to change the
2112 # queue to hold objects instead of names, I made one or two
2113 # mistakes and never found which. I reverted back instead)
2114 while ($s = CPAN::Queue->first) {
2115 my $obj;
2116 if (ref $s) {
2117 $obj = $s; # I do not believe, we would survive if this happened
2118 } else {
2119 $obj = CPAN::Shell->expandany($s);
05454584 2120 }
6d29edf5
JH
2121 if ($pragma
2122 &&
2123 ($] < 5.00303 || $obj->can($pragma))){
2124 ### compatibility with 5.003
2125 $obj->$pragma($meth); # the pragma "force" in
2126 # "CPAN::Distribution" must know
2127 # what we are intending
2128 }
2129 if ($]>=5.00303 && $obj->can('called_for')) {
2130 $obj->called_for($s);
2131 }
2132 CPAN->debug(
2133 qq{pragma[$pragma]meth[$meth]obj[$obj]as_string\[}.
2134 $obj->as_string.
2135 qq{\]}
2136 ) if $CPAN::DEBUG;
2137
2138 if ($obj->$meth()){
2139 CPAN::Queue->delete($s);
2140 } else {
2141 CPAN->debug("failed");
2142 }
2143
2144 $obj->undelay;
f610777f 2145 CPAN::Queue->delete_first($s);
05454584 2146 }
6d29edf5
JH
2147 for my $obj (@qcopy) {
2148 $obj->color_cmd_tmps(0,0);
2149 }
05454584
A
2150}
2151
6d29edf5
JH
2152#-> sub CPAN::Shell::dump ;
2153sub dump { shift->rematein('dump',@_); }
05454584
A
2154#-> sub CPAN::Shell::force ;
2155sub force { shift->rematein('force',@_); }
2156#-> sub CPAN::Shell::get ;
2157sub get { shift->rematein('get',@_); }
2158#-> sub CPAN::Shell::readme ;
2159sub readme { shift->rematein('readme',@_); }
2160#-> sub CPAN::Shell::make ;
2161sub make { shift->rematein('make',@_); }
2162#-> sub CPAN::Shell::test ;
2163sub test { shift->rematein('test',@_); }
2164#-> sub CPAN::Shell::install ;
2165sub install { shift->rematein('install',@_); }
2166#-> sub CPAN::Shell::clean ;
2167sub clean { shift->rematein('clean',@_); }
2168#-> sub CPAN::Shell::look ;
2169sub look { shift->rematein('look',@_); }
911a92db
GS
2170#-> sub CPAN::Shell::cvs_import ;
2171sub cvs_import { shift->rematein('cvs_import',@_); }
05454584 2172
c049f953
JH
2173package CPAN::LWP::UserAgent;
2174
2175sub config {
2176 return if $SETUPDONE;
2177 if ($CPAN::META->has_usable('LWP::UserAgent')) {
2178 require LWP::UserAgent;
2179 @ISA = qw(Exporter LWP::UserAgent);
2180 $SETUPDONE++;
2181 } else {
e662ec5f 2182 $CPAN::Frontend->mywarn("LWP::UserAgent not available\n");
c049f953
JH
2183 }
2184}
2185
2186sub get_basic_credentials {
2187 my($self, $realm, $uri, $proxy) = @_;
2188 return unless $proxy;
2189 if ($USER && $PASSWD) {
2190 } elsif (defined $CPAN::Config->{proxy_user} &&
1426a145 2191 defined $CPAN::Config->{proxy_pass}) {
c049f953
JH
2192 $USER = $CPAN::Config->{proxy_user};
2193 $PASSWD = $CPAN::Config->{proxy_pass};
2194 } else {
2195 require ExtUtils::MakeMaker;
2196 ExtUtils::MakeMaker->import(qw(prompt));
2197 $USER = prompt("Proxy authentication needed!
2198 (Note: to permanently configure username and password run
2199 o conf proxy_user your_username
2200 o conf proxy_pass your_password
2201 )\nUsername:");
2202 if ($CPAN::META->has_inst("Term::ReadKey")) {
2203 Term::ReadKey::ReadMode("noecho");
2204 } else {
2205 $CPAN::Frontend->mywarn("Warning: Term::ReadKey seems not to be available, your password will be echoed to the terminal!\n");
2206 }
2207 $PASSWD = prompt("Password:");
2208 if ($CPAN::META->has_inst("Term::ReadKey")) {
2209 Term::ReadKey::ReadMode("restore");
2210 }
2211 $CPAN::Frontend->myprint("\n\n");
2212 }
2213 return($USER,$PASSWD);
2214}
2215
1426a145
JH
2216# mirror(): Its purpose is to deal with proxy authentication. When we
2217# call SUPER::mirror, we relly call the mirror method in
2218# LWP::UserAgent. LWP::UserAgent will then call
2219# $self->get_basic_credentials or some equivalent and this will be
2220# $self->dispatched to our own get_basic_credentials method.
2221
2222# Our own get_basic_credentials sets $USER and $PASSWD, two globals.
2223
2224# 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means
2225# although we have gone through our get_basic_credentials, the proxy
2226# server refuses to connect. This could be a case where the username or
2227# password has changed in the meantime, so I'm trying once again without
2228# $USER and $PASSWD to give the get_basic_credentials routine another
2229# chance to set $USER and $PASSWD.
2230
c049f953
JH
2231sub mirror {
2232 my($self,$url,$aslocal) = @_;
2233 my $result = $self->SUPER::mirror($url,$aslocal);
2234 if ($result->code == 407) {
2235 undef $USER;
2236 undef $PASSWD;
2237 $result = $self->SUPER::mirror($url,$aslocal);
2238 }
2239 $result;
2240}
2241
05454584 2242package CPAN::FTP;
05454584
A
2243
2244#-> sub CPAN::FTP::ftp_get ;
2245sub ftp_get {
2e2b7522
GS
2246 my($class,$host,$dir,$file,$target) = @_;
2247 $class->debug(
2248 qq[Going to fetch file [$file] from dir [$dir]
05454584
A
2249 on host [$host] as local [$target]\n]
2250 ) if $CPAN::DEBUG;
2e2b7522
GS
2251 my $ftp = Net::FTP->new($host);
2252 return 0 unless defined $ftp;
2253 $ftp->debug(1) if $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG;
6d29edf5 2254 $class->debug(qq[Going to login("anonymous","$Config::Config{cf_email}")]);
2e2b7522
GS
2255 unless ( $ftp->login("anonymous",$Config::Config{'cf_email'}) ){
2256 warn "Couldn't login on $host";
2257 return;
2258 }
2259 unless ( $ftp->cwd($dir) ){
2260 warn "Couldn't cwd $dir";
2261 return;
2262 }
2263 $ftp->binary;
2264 $class->debug(qq[Going to ->get("$file","$target")\n]) if $CPAN::DEBUG;
2265 unless ( $ftp->get($file,$target) ){
2266 warn "Couldn't fetch $file from $host\n";
2267 return;
2268 }
2269 $ftp->quit; # it's ok if this fails
2270 return 1;
05454584
A
2271}
2272
09d9d230 2273# If more accuracy is wanted/needed, Chris Leach sent me this patch...
f610777f 2274
6d29edf5
JH
2275 # > *** /install/perl/live/lib/CPAN.pm- Wed Sep 24 13:08:48 1997
2276 # > --- /tmp/cp Wed Sep 24 13:26:40 1997
2277 # > ***************
2278 # > *** 1562,1567 ****
2279 # > --- 1562,1580 ----
2280 # > return 1 if substr($url,0,4) eq "file";
2281 # > return 1 unless $url =~ m|://([^/]+)|;
2282 # > my $host = $1;
2283 # > + my $proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'};
2284 # > + if ($proxy) {
2285 # > + $proxy =~ m|://([^/:]+)|;
2286 # > + $proxy = $1;
2287 # > + my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'};
2288 # > + if ($noproxy) {
2289 # > + if ($host !~ /$noproxy$/) {
2290 # > + $host = $proxy;
2291 # > + }
2292 # > + } else {
2293 # > + $host = $proxy;
2294 # > + }
2295 # > + }
2296 # > require Net::Ping;
2297 # > return 1 unless $Net::Ping::VERSION >= 2;
2298 # > my $p;
09d9d230
A
2299
2300
05454584
A
2301#-> sub CPAN::FTP::localize ;
2302sub localize {
2303 my($self,$file,$aslocal,$force) = @_;
2304 $force ||= 0;
2305 Carp::croak "Usage: ->localize(cpan_file,as_local_file[,$force])"
2306 unless defined $aslocal;
55e314ee
A
2307 $self->debug("file[$file] aslocal[$aslocal] force[$force]")
2308 if $CPAN::DEBUG;
05454584 2309
f14b5cec 2310 if ($^O eq 'MacOS') {
6d29edf5
JH
2311 # Comment by AK on 2000-09-03: Uniq short filenames would be
2312 # available in CHECKSUMS file
f14b5cec
JH
2313 my($name, $path) = File::Basename::fileparse($aslocal, '');
2314 if (length($name) > 31) {
6d29edf5
JH
2315 $name =~ s/(
2316 \.(
2317 readme(\.(gz|Z))? |
2318 (tar\.)?(gz|Z) |
2319 tgz |
2320 zip |
2321 pm\.(gz|Z)
2322 )
2323 )$//x;
f14b5cec
JH
2324 my $suf = $1;
2325 my $size = 31 - length($suf);
2326 while (length($name) > $size) {
2327 chop $name;
2328 }
2329 $name .= $suf;
2330 $aslocal = File::Spec->catfile($path, $name);
2331 }
2332 }
2333
c356248b 2334 return $aslocal if -f $aslocal && -r _ && !($force & 1);
55e314ee
A
2335 my($restore) = 0;
2336 if (-f $aslocal){
2337 rename $aslocal, "$aslocal.bak";
2338 $restore++;
2339 }
05454584
A
2340
2341 my($aslocal_dir) = File::Basename::dirname($aslocal);
2342 File::Path::mkpath($aslocal_dir);
c356248b 2343 $CPAN::Frontend->mywarn(qq{Warning: You are not allowed to write into }.
05454584 2344 qq{directory "$aslocal_dir".
c356248b
A
2345 I\'ll continue, but if you encounter problems, they may be due
2346 to insufficient permissions.\n}) unless -w $aslocal_dir;
05454584
A
2347
2348 # Inheritance is not easier to manage than a few if/else branches
de34a54b 2349 if ($CPAN::META->has_usable('LWP::UserAgent')) {
05454584 2350 unless ($Ua) {
c049f953
JH
2351 CPAN::LWP::UserAgent->config;
2352 eval {$Ua = CPAN::LWP::UserAgent->new;}; # Why is has_usable still not fit enough?
d8773709 2353 if ($@) {
5fc0f0f6 2354 $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n")
d8773709
JH
2355 if $CPAN::DEBUG;
2356 } else {
2357 my($var);
2358 $Ua->proxy('ftp', $var)
2359 if $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy};
2360 $Ua->proxy('http', $var)
2361 if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy};
c049f953
JH
2362
2363
2364# >>>>> On Wed, 13 Dec 2000 09:21:34 -0500, "Robison, Jonathon (J.M.)" <jrobiso2@visteon.com> said:
2365#
2366# > I note that although CPAN.pm can use proxies, it doesn't seem equipped to
2367# > use ones that require basic autorization.
2368#
2369# > Example of when I use it manually in my own stuff:
2370#
2371# > $ua->proxy(['http','ftp'], http://my.proxy.server:83');
2372# > $req->proxy_authorization_basic("username","password");
2373# > $res = $ua->request($req);
2374#
2375
d8773709
JH
2376 $Ua->no_proxy($var)
2377 if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy};
2378 }
05454584
A
2379 }
2380 }
35576f8c
A
2381 for my $prx (qw(ftp_proxy http_proxy no_proxy)) {
2382 $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx};
2383 }
05454584
A
2384
2385 # Try the list of urls for each single object. We keep a record
2386 # where we did get a file from
c356248b 2387 my(@reordered,$last);
09d9d230 2388 $CPAN::Config->{urllist} ||= [];
909b20b5
MJD
2389 unless (ref $CPAN::Config->{urllist} eq 'ARRAY') {
2390 warn "Malformed urllist; ignoring. Configuration file corrupt?\n";
2391 }
c356248b
A
2392 $last = $#{$CPAN::Config->{urllist}};
2393 if ($force & 2) { # local cpans probably out of date, don't reorder
2394 @reordered = (0..$last);
2395 } else {
2396 @reordered =
2397 sort {
2398 (substr($CPAN::Config->{urllist}[$b],0,4) eq "file")
f610777f 2399 <=>
c356248b
A
2400 (substr($CPAN::Config->{urllist}[$a],0,4) eq "file")
2401 or
2402 defined($Thesite)
2403 and
2404 ($b == $Thesite)
2405 <=>
2406 ($a == $Thesite)
2407 } 0..$last;
c356248b 2408 }
c4d24d4c 2409 my(@levels);
c356248b
A
2410 if ($Themethod) {
2411 @levels = ($Themethod, grep {$_ ne $Themethod} qw/easy hard hardest/);
2412 } else {
2413 @levels = qw/easy hard hardest/;
2414 }
f14b5cec 2415 @levels = qw/easy/ if $^O eq 'MacOS';
c4d24d4c
A
2416 my($levelno);
2417 for $levelno (0..$#levels) {
2418 my $level = $levels[$levelno];
c356248b
A
2419 my $method = "host$level";
2420 my @host_seq = $level eq "easy" ?
2421 @reordered : 0..$last; # reordered has CDROM up front
09d9d230 2422 @host_seq = (0) unless @host_seq;
c356248b
A
2423 my $ret = $self->$method(\@host_seq,$file,$aslocal);
2424 if ($ret) {
2e2b7522 2425 $Themethod = $level;
911a92db
GS
2426 my $now = time;
2427 # utime $now, $now, $aslocal; # too bad, if we do that, we
2428 # might alter a local mirror
2e2b7522
GS
2429 $self->debug("level[$level]") if $CPAN::DEBUG;
2430 return $ret;
2431 } else {
2432 unlink $aslocal;
c4d24d4c 2433 last if $CPAN::Signal; # need to cleanup
c356248b
A
2434 }
2435 }
c4d24d4c
A
2436 unless ($CPAN::Signal) {
2437 my(@mess);
2438 push @mess,
2439 qq{Please check, if the URLs I found in your configuration file \(}.
2440 join(", ", @{$CPAN::Config->{urllist}}).
2441 qq{\) are valid. The urllist can be edited.},
2442 qq{E.g. with 'o conf urllist push ftp://myurl/'};
2443 $CPAN::Frontend->myprint(Text::Wrap::wrap("","",@mess). "\n\n");
2444 sleep 2;
8d97e4a1 2445 $CPAN::Frontend->myprint("Could not fetch $file\n");
c4d24d4c 2446 }
c356248b
A
2447 if ($restore) {
2448 rename "$aslocal.bak", $aslocal;
2449 $CPAN::Frontend->myprint("Trying to get away with old file:\n" .
2450 $self->ls($aslocal));
2451 return $aslocal;
2452 }
2453 return;
2454}
2455
2456sub hosteasy {
2457 my($self,$host_seq,$file,$aslocal) = @_;
05454584 2458 my($i);
c356248b 2459 HOSTEASY: for $i (@$host_seq) {
c4d24d4c 2460 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite;
05454584
A
2461 $url .= "/" unless substr($url,-1) eq "/";
2462 $url .= $file;
c356248b 2463 $self->debug("localizing perlish[$url]") if $CPAN::DEBUG;
05454584
A
2464 if ($url =~ /^file:/) {
2465 my $l;
de34a54b 2466 if ($CPAN::META->has_inst('URI::URL')) {
55e314ee 2467 my $u = URI::URL->new($url);
05454584
A
2468 $l = $u->path;
2469 } else { # works only on Unix, is poorly constructed, but
c356248b
A
2470 # hopefully better than nothing.
2471 # RFC 1738 says fileurl BNF is
2472 # fileurl = "file://" [ host | "localhost" ] "/" fpath
2473 # Thanks to "Mark D. Baushke" <mdb@cisco.com> for
2474 # the code
36263cb3
GS
2475 ($l = $url) =~ s|^file://[^/]*/|/|; # discard the host part
2476 $l =~ s|^file:||; # assume they
2477 # meant
2478 # file://localhost
392d8ab8 2479 $l =~ s|^/||s unless -f $l; # e.g. /P:
c049f953 2480 $self->debug("without URI::URL we try local file $l") if $CPAN::DEBUG;
05454584 2481 }
c356248b
A
2482 if ( -f $l && -r _) {
2483 $Thesite = $i;
2484 return $l;
2485 }
05454584
A
2486 # Maybe mirror has compressed it?
2487 if (-f "$l.gz") {
d4fd5c69 2488 $self->debug("found compressed $l.gz") if $CPAN::DEBUG;
09d9d230 2489 CPAN::Tarzip->gunzip("$l.gz", $aslocal);
c356248b
A
2490 if ( -f $aslocal) {
2491 $Thesite = $i;
2492 return $aslocal;
2493 }
05454584
A
2494 }
2495 }
c4d24d4c 2496 if ($CPAN::META->has_usable('LWP')) {
09d9d230 2497 $CPAN::Frontend->myprint("Fetching with LWP:
c356248b
A
2498 $url
2499");
f610777f 2500 unless ($Ua) {
c049f953
JH
2501 CPAN::LWP::UserAgent->config;
2502 eval { $Ua = CPAN::LWP::UserAgent->new; };
2503 if ($@) {
5fc0f0f6 2504 $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n");
c049f953 2505 }
f610777f 2506 }
09d9d230
A
2507 my $res = $Ua->mirror($url, $aslocal);
2508 if ($res->is_success) {
2509 $Thesite = $i;
911a92db
GS
2510 my $now = time;
2511 utime $now, $now, $aslocal; # download time is more
2512 # important than upload time
09d9d230 2513 return $aslocal;
05d2a450 2514 } elsif ($url !~ /\.gz(?!\n)\Z/) {
09d9d230
A
2515 my $gzurl = "$url.gz";
2516 $CPAN::Frontend->myprint("Fetching with LWP:
c356248b
A
2517 $gzurl
2518");
09d9d230
A
2519 $res = $Ua->mirror($gzurl, "$aslocal.gz");
2520 if ($res->is_success &&
2521 CPAN::Tarzip->gunzip("$aslocal.gz",$aslocal)
2522 ) {
2523 $Thesite = $i;
2524 return $aslocal;
05454584 2525 }
09d9d230 2526 } else {
c049f953
JH
2527 $CPAN::Frontend->myprint(sprintf(
2528 "LWP failed with code[%s] message[%s]\n",
2529 $res->code,
2530 $res->message,
2531 ));
c4d24d4c
A
2532 # Alan Burlison informed me that in firewall environments
2533 # Net::FTP can still succeed where LWP fails. So we do not
2534 # skip Net::FTP anymore when LWP is available.
09d9d230
A
2535 }
2536 } else {
c049f953 2537 $CPAN::Frontend->myprint("LWP not available\n");
05454584 2538 }
c4d24d4c 2539 return if $CPAN::Signal;
05454584
A
2540 if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
2541 # that's the nice and easy way thanks to Graham
2542 my($host,$dir,$getfile) = ($1,$2,$3);
de34a54b 2543 if ($CPAN::META->has_usable('Net::FTP')) {
05454584 2544 $dir =~ s|/+|/|g;
c356248b 2545 $CPAN::Frontend->myprint("Fetching with Net::FTP:
09d9d230 2546 $url
c356248b
A
2547");
2548 $self->debug("getfile[$getfile]dir[$dir]host[$host]" .
2549 "aslocal[$aslocal]") if $CPAN::DEBUG;
2550 if (CPAN::FTP->ftp_get($host,$dir,$getfile,$aslocal)) {
2551 $Thesite = $i;
2552 return $aslocal;
2553 }
05d2a450 2554 if ($aslocal !~ /\.gz(?!\n)\Z/) {
c356248b
A
2555 my $gz = "$aslocal.gz";
2556 $CPAN::Frontend->myprint("Fetching with Net::FTP
09d9d230 2557 $url.gz
c356248b 2558");
2e2b7522 2559 if (CPAN::FTP->ftp_get($host,
09d9d230
A
2560 $dir,
2561 "$getfile.gz",
2562 $gz) &&
2563 CPAN::Tarzip->gunzip($gz,$aslocal)
2564 ){
c356248b
A
2565 $Thesite = $i;
2566 return $aslocal;
2567 }
2568 }
09d9d230 2569 # next HOSTEASY;
05454584
A
2570 }
2571 }
c4d24d4c 2572 return if $CPAN::Signal;
c356248b
A
2573 }
2574}
05454584 2575
c356248b 2576sub hosthard {
2e2b7522 2577 my($self,$host_seq,$file,$aslocal) = @_;
05454584 2578
2e2b7522
GS
2579 # Came back if Net::FTP couldn't establish connection (or
2580 # failed otherwise) Maybe they are behind a firewall, but they
2581 # gave us a socksified (or other) ftp program...
c356248b 2582
2e2b7522 2583 my($i);
f610777f 2584 my($devnull) = $CPAN::Config->{devnull} || "";
2e2b7522
GS
2585 # < /dev/null ";
2586 my($aslocal_dir) = File::Basename::dirname($aslocal);
2587 File::Path::mkpath($aslocal_dir);
c356248b 2588 HOSTHARD: for $i (@$host_seq) {
09d9d230 2589 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite;
c356248b
A
2590 $url .= "/" unless substr($url,-1) eq "/";
2591 $url .= $file;
09d9d230
A
2592 my($proto,$host,$dir,$getfile);
2593
2594 # Courtesy Mark Conty mark_conty@cargill.com change from
2595 # if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
2596 # to
2597 if ($url =~ m|^([^:]+)://(.*?)/(.*)/(.*)|) {
911a92db
GS
2598 # proto not yet used
2599 ($proto,$host,$dir,$getfile) = ($1,$2,$3,$4);
c356248b 2600 } else {
911a92db 2601 next HOSTHARD; # who said, we could ftp anything except ftp?
c356248b 2602 }
5a5fac02
JH
2603 next HOSTHARD if $proto eq "file"; # file URLs would have had
2604 # success above. Likely a bogus URL
911a92db 2605
c356248b
A
2606 $self->debug("localizing funkyftpwise[$url]") if $CPAN::DEBUG;
2607 my($f,$funkyftp);
9d61fa1d 2608 for $f ('lynx','ncftpget','ncftp','wget') {
911a92db
GS
2609 next unless exists $CPAN::Config->{$f};
2610 $funkyftp = $CPAN::Config->{$f};
2611 next unless defined $funkyftp;
2612 next if $funkyftp =~ /^\s*$/;
de34a54b
JH
2613 my($asl_ungz, $asl_gz);
2614 ($asl_ungz = $aslocal) =~ s/\.gz//;
2615 $asl_gz = "$asl_ungz.gz";
2616 my($src_switch) = "";
911a92db 2617 if ($f eq "lynx"){
de34a54b 2618 $src_switch = " -source";
911a92db 2619 } elsif ($f eq "ncftp"){
de34a54b 2620 $src_switch = " -c";
9d61fa1d
A
2621 } elsif ($f eq "wget"){
2622 $src_switch = " -O -";
911a92db
GS
2623 }
2624 my($chdir) = "";
de34a54b 2625 my($stdout_redir) = " > $asl_ungz";
911a92db
GS
2626 if ($f eq "ncftpget"){
2627 $chdir = "cd $aslocal_dir && ";
2628 $stdout_redir = "";
2629 }
2630 $CPAN::Frontend->myprint(
2631 qq[
de34a54b 2632Trying with "$funkyftp$src_switch" to get
c356248b 2633 $url
2e2b7522 2634]);
911a92db 2635 my($system) =
e662ec5f 2636 "$chdir$funkyftp$src_switch \"$url\" $devnull$stdout_redir";
911a92db
GS
2637 $self->debug("system[$system]") if $CPAN::DEBUG;
2638 my($wstatus);
2639 if (($wstatus = system($system)) == 0
2640 &&
2641 ($f eq "lynx" ?
5a5fac02 2642 -s $asl_ungz # lynx returns 0 when it fails somewhere
911a92db
GS
2643 : 1
2644 )
2645 ) {
2646 if (-s $aslocal) {
2647 # Looks good
de34a54b 2648 } elsif ($asl_ungz ne $aslocal) {
911a92db 2649 # test gzip integrity
5a5fac02
JH
2650 if (CPAN::Tarzip->gtest($asl_ungz)) {
2651 # e.g. foo.tar is gzipped --> foo.tar.gz
2652 rename $asl_ungz, $aslocal;
911a92db 2653 } else {
5a5fac02 2654 CPAN::Tarzip->gzip($asl_ungz,$asl_gz);
911a92db
GS
2655 }
2656 }
2657 $Thesite = $i;
2658 return $aslocal;
05d2a450 2659 } elsif ($url !~ /\.gz(?!\n)\Z/) {
de34a54b
JH
2660 unlink $asl_ungz if
2661 -f $asl_ungz && -s _ == 0;
911a92db
GS
2662 my $gz = "$aslocal.gz";
2663 my $gzurl = "$url.gz";
2664 $CPAN::Frontend->myprint(
2665 qq[
de34a54b 2666Trying with "$funkyftp$src_switch" to get
911a92db
GS
2667 $url.gz
2668]);
e662ec5f 2669 my($system) = "$funkyftp$src_switch \"$url.gz\" $devnull > $asl_gz";
55e314ee 2670 $self->debug("system[$system]") if $CPAN::DEBUG;
05454584 2671 my($wstatus);
55e314ee
A
2672 if (($wstatus = system($system)) == 0
2673 &&
de34a54b 2674 -s $asl_gz
55e314ee 2675 ) {
911a92db 2676 # test gzip integrity
de34a54b 2677 if (CPAN::Tarzip->gtest($asl_gz)) {
5a5fac02 2678 CPAN::Tarzip->gunzip($asl_gz,$aslocal);
2e2b7522 2679 } else {
5a5fac02
JH
2680 # somebody uncompressed file for us?
2681 rename $asl_ungz, $aslocal;
2e2b7522 2682 }
911a92db
GS
2683 $Thesite = $i;
2684 return $aslocal;
05454584 2685 } else {
de34a54b 2686 unlink $asl_gz if -f $asl_gz;
911a92db
GS
2687 }
2688 } else {
2689 my $estatus = $wstatus >> 8;
2690 my $size = -f $aslocal ?
2691 ", left\n$aslocal with size ".-s _ :
2692 "\nWarning: expected file [$aslocal] doesn't exist";
2693 $CPAN::Frontend->myprint(qq{
05454584 2694System call "$system"
c356248b
A
2695returned status $estatus (wstat $wstatus)$size
2696});
911a92db 2697 }
c4d24d4c
A
2698 return if $CPAN::Signal;
2699 } # lynx,ncftpget,ncftp
2700 } # host
c356248b 2701}
05454584 2702
c356248b
A
2703sub hosthardest {
2704 my($self,$host_seq,$file,$aslocal) = @_;
2705
2706 my($i);
2707 my($aslocal_dir) = File::Basename::dirname($aslocal);
2708 File::Path::mkpath($aslocal_dir);
35576f8c 2709 my $ftpbin = $CPAN::Config->{ftp};
c356248b 2710 HOSTHARDEST: for $i (@$host_seq) {
35576f8c 2711 unless (length $ftpbin && MM->maybe_command($ftpbin)) {
c356248b
A
2712 $CPAN::Frontend->myprint("No external ftp command available\n\n");
2713 last HOSTHARDEST;
2714 }
09d9d230 2715 my $url = $CPAN::Config->{urllist}[$i] || $CPAN::Defaultsite;
c356248b
A
2716 $url .= "/" unless substr($url,-1) eq "/";
2717 $url .= $file;
2718 $self->debug("localizing ftpwise[$url]") if $CPAN::DEBUG;
2719 unless ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
2720 next;
2721 }
2722 my($host,$dir,$getfile) = ($1,$2,$3);
c356248b
A
2723 my $timestamp = 0;
2724 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
2725 $ctime,$blksize,$blocks) = stat($aslocal);
2726 $timestamp = $mtime ||= 0;
2727 my($netrc) = CPAN::FTP::netrc->new;
911a92db 2728 my($netrcfile) = $netrc->netrc;
c356248b
A
2729 my($verbose) = $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG ? " -v" : "";
2730 my $targetfile = File::Basename::basename($aslocal);
2731 my(@dialog);
2732 push(
2733 @dialog,
2734 "lcd $aslocal_dir",
2735 "cd /",
5fc0f0f6 2736 map("cd $_", split /\//, $dir), # RFC 1738
c356248b
A
2737 "bin",
2738 "get $getfile $targetfile",
2739 "quit"
2740 );
911a92db 2741 if (! $netrcfile) {
c356248b
A
2742 CPAN->debug("No ~/.netrc file found") if $CPAN::DEBUG;
2743 } elsif ($netrc->hasdefault || $netrc->contains($host)) {
2744 CPAN->debug(sprintf("hasdef[%d]cont($host)[%d]",
2745 $netrc->hasdefault,
2746 $netrc->contains($host))) if $CPAN::DEBUG;
2747 if ($netrc->protected) {
2748 $CPAN::Frontend->myprint(qq{
05454584
A
2749 Trying with external ftp to get
2750 $url
2751 As this requires some features that are not thoroughly tested, we\'re
2752 not sure, that we get it right....
2753
2754}
c356248b 2755 );
35576f8c 2756 $self->talk_ftp("$ftpbin$verbose $host",
c356248b 2757 @dialog);
05454584 2758 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
c356248b 2759 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal);
05454584
A
2760 $mtime ||= 0;
2761 if ($mtime > $timestamp) {
c356248b
A
2762 $CPAN::Frontend->myprint("GOT $aslocal\n");
2763 $Thesite = $i;
05454584
A
2764 return $aslocal;
2765 } else {
c356248b 2766 $CPAN::Frontend->myprint("Hmm... Still failed!\n");
05454584 2767 }
c4d24d4c 2768 return if $CPAN::Signal;
c356248b
A
2769 } else {
2770 $CPAN::Frontend->mywarn(qq{Your $netrcfile is not }.
2771 qq{correctly protected.\n});
05454584 2772 }
c356248b
A
2773 } else {
2774 $CPAN::Frontend->mywarn("Your ~/.netrc neither contains $host
2775 nor does it have a default entry\n");
05454584 2776 }
36263cb3 2777
c356248b
A
2778 # OK, they don't have a valid ~/.netrc. Use 'ftp -n'
2779 # then and login manually to host, using e-mail as
2780 # password.
35576f8c 2781 $CPAN::Frontend->myprint(qq{Issuing "$ftpbin$verbose -n"\n});
c356248b
A
2782 unshift(
2783 @dialog,
2784 "open $host",
2785 "user anonymous $Config::Config{'cf_email'}"
2786 );
35576f8c 2787 $self->talk_ftp("$ftpbin$verbose -n", @dialog);
c356248b
A
2788 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
2789 $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal);
2790 $mtime ||= 0;
2791 if ($mtime > $timestamp) {
2792 $CPAN::Frontend->myprint("GOT $aslocal\n");
2793 $Thesite = $i;
2794 return $aslocal;
2795 } else {
2796 $CPAN::Frontend->myprint("Bad luck... Still failed!\n");
05454584 2797 }
c4d24d4c 2798 return if $CPAN::Signal;
c356248b
A
2799 $CPAN::Frontend->myprint("Can't access URL $url.\n\n");
2800 sleep 2;
c4d24d4c 2801 } # host
c356248b
A
2802}
2803
2804sub talk_ftp {
2805 my($self,$command,@dialog) = @_;
2806 my $fh = FileHandle->new;
2807 $fh->open("|$command") or die "Couldn't open ftp: $!";
2808 foreach (@dialog) { $fh->print("$_\n") }
2809 $fh->close; # Wait for process to complete
2810 my $wstatus = $?;
2811 my $estatus = $wstatus >> 8;
2812 $CPAN::Frontend->myprint(qq{
2813Subprocess "|$command"
2814 returned status $estatus (wstat $wstatus)
2815}) if $wstatus;
05454584
A
2816}
2817
e50380aa
A
2818# find2perl needs modularization, too, all the following is stolen
2819# from there
09d9d230 2820# CPAN::FTP::ls
e50380aa
A
2821sub ls {
2822 my($self,$name) = @_;
2823 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm,
2824 $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name);
2825
2826 my($perms,%user,%group);
2827 my $pname = $name;
2828
55e314ee 2829 if ($blocks) {
e50380aa
A
2830 $blocks = int(($blocks + 1) / 2);
2831 }
2832 else {
2833 $blocks = int(($sizemm + 1023) / 1024);
2834 }
2835
2836 if (-f _) { $perms = '-'; }
2837 elsif (-d _) { $perms = 'd'; }
2838 elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; }
2839 elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; }
2840 elsif (-p _) { $perms = 'p'; }
2841 elsif (-S _) { $perms = 's'; }
2842 else { $perms = 'l'; $pname .= ' -> ' . readlink($_); }
2843
2844 my(@rwx) = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx');
2845 my(@moname) = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
2846 my $tmpmode = $mode;
2847 my $tmp = $rwx[$tmpmode & 7];
2848 $tmpmode >>= 3;
2849 $tmp = $rwx[$tmpmode & 7] . $tmp;
2850 $tmpmode >>= 3;
2851 $tmp = $rwx[$tmpmode & 7] . $tmp;
2852 substr($tmp,2,1) =~ tr/-x/Ss/ if -u _;
2853 substr($tmp,5,1) =~ tr/-x/Ss/ if -g _;
2854 substr($tmp,8,1) =~ tr/-x/Tt/ if -k _;
2855 $perms .= $tmp;
2856
2857 my $user = $user{$uid} || $uid; # too lazy to implement lookup
2858 my $group = $group{$gid} || $gid;
2859
2860 my($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime);
2861 my($timeyear);
2862 my($moname) = $moname[$mon];
2863 if (-M _ > 365.25 / 2) {
2864 $timeyear = $year + 1900;
2865 }
2866 else {
2867 $timeyear = sprintf("%02d:%02d", $hour, $min);
2868 }
2869
2870 sprintf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n",
2871 $ino,
2872 $blocks,
2873 $perms,
2874 $nlink,
2875 $user,
2876 $group,
2877 $sizemm,
2878 $moname,
2879 $mday,
2880 $timeyear,
2881 $pname;
2882}
2883
05454584
A
2884package CPAN::FTP::netrc;
2885
2886sub new {
2887 my($class) = @_;
5de3f0da 2888 my $file = File::Spec->catfile($ENV{HOME},".netrc");
05454584
A
2889
2890 my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
2891 $atime,$mtime,$ctime,$blksize,$blocks)
2892 = stat($file);
2893 $mode ||= 0;
2894 my $protected = 0;
2895
42d3b621
A
2896 my($fh,@machines,$hasdefault);
2897 $hasdefault = 0;
da199366
A
2898 $fh = FileHandle->new or die "Could not create a filehandle";
2899
2900 if($fh->open($file)){
2901 $protected = ($mode & 077) == 0;
10b2abe6 2902 local($/) = "";
42d3b621 2903 NETRC: while (<$fh>) {
da199366 2904 my(@tokens) = split " ", $_;
42d3b621
A
2905 TOKEN: while (@tokens) {
2906 my($t) = shift @tokens;
da199366
A
2907 if ($t eq "default"){
2908 $hasdefault++;
da199366
A
2909 last NETRC;
2910 }
42d3b621
A
2911 last TOKEN if $t eq "macdef";
2912 if ($t eq "machine") {
2913 push @machines, shift @tokens;
2914 }
2915 }
10b2abe6
CS
2916 }
2917 } else {
da199366 2918 $file = $hasdefault = $protected = "";
10b2abe6 2919 }
da199366 2920
10b2abe6 2921 bless {
42d3b621
A
2922 'mach' => [@machines],
2923 'netrc' => $file,
2924 'hasdefault' => $hasdefault,
da199366 2925 'protected' => $protected,
10b2abe6
CS
2926 }, $class;
2927}
2928
9d61fa1d 2929# CPAN::FTP::hasdefault;
42d3b621 2930sub hasdefault { shift->{'hasdefault'} }
da199366
A
2931sub netrc { shift->{'netrc'} }
2932sub protected { shift->{'protected'} }
10b2abe6
CS
2933sub contains {
2934 my($self,$mach) = @_;
da199366
A
2935 for ( @{$self->{'mach'}} ) {
2936 return 1 if $_ eq $mach;
2937 }
2938 return 0;
10b2abe6
CS
2939}
2940
5f05dabc 2941package CPAN::Complete;
5f05dabc 2942
36263cb3
GS
2943sub gnu_cpl {
2944 my($text, $line, $start, $end) = @_;
2945 my(@perlret) = cpl($text, $line, $start);
2946 # find longest common match. Can anybody show me how to peruse
2947 # T::R::Gnu to have this done automatically? Seems expensive.
2948 return () unless @perlret;
2949 my($newtext) = $text;
2950 for (my $i = length($text)+1;;$i++) {
2951 last unless length($perlret[0]) && length($perlret[0]) >= $i;
2952 my $try = substr($perlret[0],0,$i);
2953 my @tries = grep {substr($_,0,$i) eq $try} @perlret;
2954 # warn "try[$try]tries[@tries]";
2955 if (@tries == @perlret) {
2956 $newtext = $try;
2957 } else {
2958 last;
2959 }
2960 }
2961 ($newtext,@perlret);
2962}
2963
55e314ee
A
2964#-> sub CPAN::Complete::cpl ;
2965sub cpl {
5f05dabc 2966 my($word,$line,$pos) = @_;
2967 $word ||= "";
2968 $line ||= "";
2969 $pos ||= 0;
2970 CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
2971 $line =~ s/^\s*//;
da199366
A
2972 if ($line =~ s/^(force\s*)//) {
2973 $pos -= length($1);
2974 }
5f05dabc 2975 my @return;
2976 if ($pos == 0) {
9d61fa1d 2977 @return = grep /^$word/, @CPAN::Complete::COMMANDS;
c049f953 2978 } elsif ( $line !~ /^[\!abcdghimorutl]/ ) {
5f05dabc 2979 @return = ();
8d97e4a1
JH
2980 } elsif ($line =~ /^(a|ls)\s/) {
2981 @return = cplx('CPAN::Author',uc($word));
5f05dabc 2982 } elsif ($line =~ /^b\s/) {
8d97e4a1 2983 CPAN::Shell->local_bundles;
55e314ee 2984 @return = cplx('CPAN::Bundle',$word);
5f05dabc 2985 } elsif ($line =~ /^d\s/) {
55e314ee 2986 @return = cplx('CPAN::Distribution',$word);
6d29edf5 2987 } elsif ($line =~ m/^(
c049f953 2988 [mru]|make|clean|dump|get|test|install|readme|look|cvs_import
6d29edf5 2989 )\s/x ) {
d8773709
JH
2990 if ($word =~ /^Bundle::/) {
2991 CPAN::Shell->local_bundles;
2992 }
55e314ee 2993 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word));
5f05dabc 2994 } elsif ($line =~ /^i\s/) {
55e314ee 2995 @return = cpl_any($word);
5f05dabc 2996 } elsif ($line =~ /^reload\s/) {
55e314ee 2997 @return = cpl_reload($word,$line,$pos);
5f05dabc 2998 } elsif ($line =~ /^o\s/) {
55e314ee 2999 @return = cpl_option($word,$line,$pos);
9d61fa1d
A
3000 } elsif ($line =~ m/^\S+\s/ ) {
3001 # fallback for future commands and what we have forgotten above
3002 @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word));
5f05dabc 3003 } else {
3004 @return = ();
3005 }
3006 return @return;
3007}
3008
55e314ee
A
3009#-> sub CPAN::Complete::cplx ;
3010sub cplx {
5f05dabc 3011 my($class, $word) = @_;
de34a54b
JH
3012 # I believed for many years that this was sorted, today I
3013 # realized, it wasn't sorted anymore. Now (rev 1.301 / v 1.55) I
3014 # make it sorted again. Maybe sort was dropped when GNU-readline
3015 # support came in? The RCS file is difficult to read on that:-(
3016 sort grep /^\Q$word\E/, map { $_->id } $CPAN::META->all_objects($class);
5f05dabc 3017}
3018
55e314ee
A
3019#-> sub CPAN::Complete::cpl_any ;
3020sub cpl_any {
5f05dabc 3021 my($word) = shift;
3022 return (
55e314ee
A
3023 cplx('CPAN::Author',$word),
3024 cplx('CPAN::Bundle',$word),
3025 cplx('CPAN::Distribution',$word),
3026 cplx('CPAN::Module',$word),
5f05dabc 3027 );
3028}
3029
55e314ee
A
3030#-> sub CPAN::Complete::cpl_reload ;
3031sub cpl_reload {
5f05dabc 3032 my($word,$line,$pos) = @_;
3033 $word ||= "";
3034 my(@words) = split " ", $line;
3035 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
3036 my(@ok) = qw(cpan index);
e50380aa
A
3037 return @ok if @words == 1;
3038 return grep /^\Q$word\E/, @ok if @words == 2 && $word;
5f05dabc 3039}
3040
55e314ee
A
3041#-> sub CPAN::Complete::cpl_option ;
3042sub cpl_option {
5f05dabc 3043 my($word,$line,$pos) = @_;
3044 $word ||= "";
3045 my(@words) = split " ", $line;
3046 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
3047 my(@ok) = qw(conf debug);
e50380aa 3048 return @ok if @words == 1;
c356248b 3049 return grep /^\Q$word\E/, @ok if @words == 2 && length($word);
5f05dabc 3050 if (0) {
3051 } elsif ($words[1] eq 'index') {
3052 return ();
3053 } elsif ($words[1] eq 'conf') {
55e314ee 3054 return CPAN::Config::cpl(@_);
5f05dabc 3055 } elsif ($words[1] eq 'debug') {
3056 return sort grep /^\Q$word\E/, sort keys %CPAN::DEBUG, 'all';
3057 }
3058}
3059
3060package CPAN::Index;
5f05dabc 3061
10b2abe6 3062#-> sub CPAN::Index::force_reload ;
5f05dabc 3063sub force_reload {
3064 my($class) = @_;
c049f953 3065 $CPAN::Index::LAST_TIME = 0;
5f05dabc 3066 $class->reload(1);
3067}
3068
10b2abe6 3069#-> sub CPAN::Index::reload ;
5f05dabc 3070sub reload {
3071 my($cl,$force) = @_;
3072 my $time = time;
3073
c356248b
A
3074 # XXX check if a newer one is available. (We currently read it
3075 # from time to time)
e50380aa 3076 for ($CPAN::Config->{index_expire}) {
36263cb3 3077 $_ = 0.001 unless $_ && $_ > 0.001;
e50380aa 3078 }
9d61fa1d
A
3079 unless (1 || $CPAN::Have_warned->{readmetadatacache}++) {
3080 # debug here when CPAN doesn't seem to read the Metadata
3081 require Carp;
3082 Carp::cluck("META-PROTOCOL[$CPAN::META->{PROTOCOL}]");
3083 }
3084 unless ($CPAN::META->{PROTOCOL}) {
3085 $cl->read_metadata_cache;
3086 $CPAN::META->{PROTOCOL} ||= "1.0";
3087 }
6d29edf5
JH
3088 if ( $CPAN::META->{PROTOCOL} < PROTOCOL ) {
3089 # warn "Setting last_time to 0";
c049f953 3090 $LAST_TIME = 0; # No warning necessary
6d29edf5 3091 }
c049f953 3092 return if $LAST_TIME + $CPAN::Config->{index_expire}*86400 > $time
c356248b 3093 and ! $force;
6d29edf5
JH
3094 if (0) {
3095 # IFF we are developing, it helps to wipe out the memory
3096 # between reloads, otherwise it is not what a user expects.
3097 undef $CPAN::META; # Neue Gruendlichkeit since v1.52(r1.274)
3098 $CPAN::META = CPAN->new;
3099 }
3100 {
3101 my($debug,$t2);
c049f953 3102 local $LAST_TIME = $time;
6d29edf5
JH
3103 local $CPAN::META->{PROTOCOL} = PROTOCOL;
3104
3105 my $needshort = $^O eq "dos";
3106
3107 $cl->rd_authindex($cl
3108 ->reload_x(
3109 "authors/01mailrc.txt.gz",
3110 $needshort ?
3111 File::Spec->catfile('authors', '01mailrc.gz') :
3112 File::Spec->catfile('authors', '01mailrc.txt.gz'),
3113 $force));
3114 $t2 = time;
3115 $debug = "timing reading 01[".($t2 - $time)."]";
3116 $time = $t2;
3117 return if $CPAN::Signal; # this is sometimes lengthy
3118 $cl->rd_modpacks($cl
3119 ->reload_x(
3120 "modules/02packages.details.txt.gz",
3121 $needshort ?
3122 File::Spec->catfile('modules', '02packag.gz') :
3123 File::Spec->catfile('modules', '02packages.details.txt.gz'),
3124 $force));
3125 $t2 = time;
3126 $debug .= "02[".($t2 - $time)."]";
3127 $time = $t2;
3128 return if $CPAN::Signal; # this is sometimes lengthy
3129 $cl->rd_modlist($cl
3130 ->reload_x(
3131 "modules/03modlist.data.gz",
3132 $needshort ?
3133 File::Spec->catfile('modules', '03mlist.gz') :
3134 File::Spec->catfile('modules', '03modlist.data.gz'),
3135 $force));
3136 $cl->write_metadata_cache;
3137 $t2 = time;
3138 $debug .= "03[".($t2 - $time)."]";
3139 $time = $t2;
3140 CPAN->debug($debug) if $CPAN::DEBUG;
3141 }
c049f953 3142 $LAST_TIME = $time;
6d29edf5 3143 $CPAN::META->{PROTOCOL} = PROTOCOL;
5f05dabc 3144}
3145
10b2abe6 3146#-> sub CPAN::Index::reload_x ;
5f05dabc 3147sub reload_x {
3148 my($cl,$wanted,$localname,$force) = @_;
c356248b 3149 $force |= 2; # means we're dealing with an index here
55e314ee
A
3150 CPAN::Config->load; # we should guarantee loading wherever we rely
3151 # on Config XXX
c356248b 3152 $localname ||= $wanted;
5de3f0da
DR
3153 my $abs_wanted = File::Spec->catfile($CPAN::Config->{'keep_source_where'},
3154 $localname);
e50380aa
A
3155 if (
3156 -f $abs_wanted &&
05454584 3157 -M $abs_wanted < $CPAN::Config->{'index_expire'} &&
c356248b 3158 !($force & 1)
e50380aa
A
3159 ) {
3160 my $s = $CPAN::Config->{'index_expire'} == 1 ? "" : "s";
05454584 3161 $cl->debug(qq{$abs_wanted younger than $CPAN::Config->{'index_expire'} }.
e50380aa 3162 qq{day$s. I\'ll use that.});
5f05dabc 3163 return $abs_wanted;
3164 } else {
c356248b 3165 $force |= 1; # means we're quite serious about it.
5f05dabc 3166 }
3167 return CPAN::FTP->localize($wanted,$abs_wanted,$force);
3168}
3169
55e314ee
A
3170#-> sub CPAN::Index::rd_authindex ;
3171sub rd_authindex {
f14b5cec
JH
3172 my($cl, $index_target) = @_;
3173 my @lines;
c356248b 3174 return unless defined $index_target;
c356248b 3175 $CPAN::Frontend->myprint("Going to read $index_target\n");
09d9d230
A
3176 local(*FH);
3177 tie *FH, CPAN::Tarzip, $index_target;
52128c7b 3178 local($/) = "\n";
f14b5cec
JH
3179 push @lines, split /\012/ while <FH>;
3180 foreach (@lines) {
c356248b 3181 my($userid,$fullname,$email) =
f610777f 3182 m/alias\s+(\S+)\s+\"([^\"\<]+)\s+\<([^\>]+)\>\"/;
5f05dabc 3183 next unless $userid && $fullname && $email;
3184
3185 # instantiate an author object
3186 my $userobj = $CPAN::META->instance('CPAN::Author',$userid);
3187 $userobj->set('FULLNAME' => $fullname, 'EMAIL' => $email);
3188 return if $CPAN::Signal;
3189 }
09d9d230
A
3190}
3191
3192sub userid {
3193 my($self,$dist) = @_;
3194 $dist = $self->{'id'} unless defined $dist;
3195 my($ret) = $dist =~ m|(?:\w/\w\w/)?([^/]+)/|;
3196 $ret;
5f05dabc 3197}
3198
55e314ee
A
3199#-> sub CPAN::Index::rd_modpacks ;
3200sub rd_modpacks {
05d2a450 3201 my($self, $index_target) = @_;
f14b5cec 3202 my @lines;
c356248b 3203 return unless defined $index_target;
c356248b 3204 $CPAN::Frontend->myprint("Going to read $index_target\n");
09d9d230 3205 my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
52128c7b 3206 local($/) = "\n";
09d9d230 3207 while ($_ = $fh->READLINE) {
f14b5cec
JH
3208 s/\012/\n/g;
3209 my @ls = map {"$_\n"} split /\n/, $_;
3210 unshift @ls, "\n" x length($1) if /^(\n+)/;
3211 push @lines, @ls;
e50380aa 3212 }
de34a54b 3213 # read header
c049f953 3214 my($line_count,$last_updated);
f14b5cec
JH
3215 while (@lines) {
3216 my $shift = shift(@lines);
3217 last if $shift =~ /^\s*$/;
c049f953
JH
3218 $shift =~ /^Line-Count:\s+(\d+)/ and $line_count = $1;
3219 $shift =~ /^Last-Updated:\s+(.+)/ and $last_updated = $1;
f14b5cec 3220 }
de34a54b 3221 if (not defined $line_count) {
05d2a450 3222
de34a54b 3223 warn qq{Warning: Your $index_target does not contain a Line-Count header.
05d2a450
A
3224Please check the validity of the index file by comparing it to more
3225than one CPAN mirror. I'll continue but problems seem likely to
3226happen.\a
de34a54b 3227};
05d2a450 3228
de34a54b
JH
3229 sleep 5;
3230 } elsif ($line_count != scalar @lines) {
3231
3232 warn sprintf qq{Warning: Your %s
3233contains a Line-Count header of %d but I see %d lines there. Please
3234check the validity of the index file by comparing it to more than one
3235CPAN mirror. I'll continue but problems seem likely to happen.\a\n},
3236$index_target, $line_count, scalar(@lines);
3237
3238 }
c049f953
JH
3239 if (not defined $last_updated) {
3240
3241 warn qq{Warning: Your $index_target does not contain a Last-Updated header.
3242Please check the validity of the index file by comparing it to more
3243than one CPAN mirror. I'll continue but problems seem likely to
3244happen.\a
3245};
3246
3247 sleep 5;
3248 } else {
3249
3250 $CPAN::Frontend
3251 ->myprint(sprintf qq{ Database was generated on %s\n},
3252 $last_updated);
3253 $DATE_OF_02 = $last_updated;
3254
3255 if ($CPAN::META->has_inst(HTTP::Date)) {
3256 require HTTP::Date;
3257 my($age) = (time - HTTP::Date::str2time($last_updated))/3600/24;
3258 if ($age > 30) {
3259
3260 $CPAN::Frontend
3261 ->mywarn(sprintf
3262 qq{Warning: This index file is %d days old.
3263 Please check the host you chose as your CPAN mirror for staleness.
3264 I'll continue but problems seem likely to happen.\a\n},
3265 $age);
3266
3267 }
3268 } else {
3269 $CPAN::Frontend->myprint(" HTTP::Date not available\n");
3270 }
3271 }
3272
3273
c4d24d4c
A
3274 # A necessity since we have metadata_cache: delete what isn't
3275 # there anymore
3276 my $secondtime = $CPAN::META->exists("CPAN::Module","CPAN");
3277 CPAN->debug("secondtime[$secondtime]") if $CPAN::DEBUG;
3278 my(%exists);
f14b5cec 3279 foreach (@lines) {
5f05dabc 3280 chomp;
05d2a450
A
3281 # before 1.56 we split into 3 and discarded the rest. From
3282 # 1.57 we assign remaining text to $comment thus allowing to
3283 # influence isa_perl
3284 my($mod,$version,$dist,$comment) = split " ", $_, 4;
e50380aa 3285 my($bundle,$id,$userid);
f610777f 3286
09d9d230
A
3287 if ($mod eq 'CPAN' &&
3288 ! (
f610777f
A
3289 CPAN::Queue->exists('Bundle::CPAN') ||
3290 CPAN::Queue->exists('CPAN')
09d9d230
A
3291 )
3292 ) {
c4d24d4c
A
3293 local($^W)= 0;
3294 if ($version > $CPAN::VERSION){
3295 $CPAN::Frontend->myprint(qq{
3296 There's a new CPAN.pm version (v$version) available!
911a92db 3297 [Current version is v$CPAN::VERSION]
e50380aa 3298 You might want to try
09d9d230 3299 install Bundle::CPAN
5f05dabc 3300 reload cpan
c356248b 3301 without quitting the current session. It should be a seamless upgrade
05454584 3302 while we are running...
c4d24d4c
A
3303}); #});
3304 sleep 2;
c356248b 3305 $CPAN::Frontend->myprint(qq{\n});
5f05dabc 3306 }
05454584 3307 last if $CPAN::Signal;
e50380aa
A
3308 } elsif ($mod =~ /^Bundle::(.*)/) {
3309 $bundle = $1;
5f05dabc 3310 }
05454584 3311
05454584
A
3312 if ($bundle){
3313 $id = $CPAN::META->instance('CPAN::Bundle',$mod);
c356248b 3314 # Let's make it a module too, because bundles have so much
6d29edf5
JH
3315 # in common with modules.
3316
3317 # Changed in 1.57_63: seems like memory bloat now without
3318 # any value, so commented out
3319
3320 # $CPAN::META->instance('CPAN::Module',$mod);
c356248b 3321
c4d24d4c 3322 } else {
c356248b 3323
05454584
A
3324 # instantiate a module object
3325 $id = $CPAN::META->instance('CPAN::Module',$mod);
c4d24d4c 3326
5f05dabc 3327 }
5f05dabc 3328
5e05dca5
A
3329 if ($id->cpan_file ne $dist){ # update only if file is
3330 # different. CPAN prohibits same
3331 # name with different version
35576f8c 3332 $userid = $id->userid || $self->userid($dist);
e50380aa
A
3333 $id->set(
3334 'CPAN_USERID' => $userid,
6d29edf5 3335 'CPAN_VERSION' => $version,
05d2a450 3336 'CPAN_FILE' => $dist,
e50380aa
A
3337 );
3338 }
05454584
A
3339
3340 # instantiate a distribution object
911a92db
GS
3341 if ($CPAN::META->exists('CPAN::Distribution',$dist)) {
3342 # we do not need CONTAINSMODS unless we do something with
3343 # this dist, so we better produce it on demand.
3344
3345 ## my $obj = $CPAN::META->instance(
3346 ## 'CPAN::Distribution' => $dist
3347 ## );
3348 ## $obj->{CONTAINSMODS}{$mod} = undef; # experimental
3349 } else {
3350 $CPAN::META->instance(
3351 'CPAN::Distribution' => $dist
3352 )->set(
6d29edf5
JH
3353 'CPAN_USERID' => $userid,
3354 'CPAN_COMMENT' => $comment,
911a92db 3355 );
5f05dabc 3356 }
c4d24d4c
A
3357 if ($secondtime) {
3358 for my $name ($mod,$dist) {
6d29edf5 3359 CPAN->debug("exists name[$name]") if $CPAN::DEBUG;
c4d24d4c
A
3360 $exists{$name} = undef;
3361 }
3362 }
05454584 3363 return if $CPAN::Signal;
5f05dabc 3364 }
09d9d230 3365 undef $fh;
c4d24d4c
A
3366 if ($secondtime) {
3367 for my $class (qw(CPAN::Module CPAN::Bundle CPAN::Distribution)) {
3368 for my $o ($CPAN::META->all_objects($class)) {
3369 next if exists $exists{$o->{ID}};
3370 $CPAN::META->delete($class,$o->{ID});
6d29edf5
JH
3371 CPAN->debug("deleting ID[$o->{ID}] in class[$class]")
3372 if $CPAN::DEBUG;
c4d24d4c
A
3373 }
3374 }
3375 }
5f05dabc 3376}
3377
55e314ee
A
3378#-> sub CPAN::Index::rd_modlist ;
3379sub rd_modlist {
05454584 3380 my($cl,$index_target) = @_;
c356248b 3381 return unless defined $index_target;
c356248b 3382 $CPAN::Frontend->myprint("Going to read $index_target\n");
09d9d230
A
3383 my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
3384 my @eval;
52128c7b 3385 local($/) = "\n";
09d9d230 3386 while ($_ = $fh->READLINE) {
f14b5cec
JH
3387 s/\012/\n/g;
3388 my @ls = map {"$_\n"} split /\n/, $_;
3389 unshift @ls, "\n" x length($1) if /^(\n+)/;
3390 push @eval, @ls;
3391 }
3392 while (@eval) {
3393 my $shift = shift(@eval);
3394 if ($shift =~ /^Date:\s+(.*)/){
c049f953
JH
3395 return if $DATE_OF_03 eq $1;
3396 ($DATE_OF_03) = $1;
e50380aa 3397 }
f14b5cec 3398 last if $shift =~ /^\s*$/;
05454584 3399 }
09d9d230
A
3400 undef $fh;
3401 push @eval, q{CPAN::Modulelist->data;};
05454584
A
3402 local($^W) = 0;
3403 my($comp) = Safe->new("CPAN::Safe1");
09d9d230 3404 my($eval) = join("", @eval);
05454584
A
3405 my $ret = $comp->reval($eval);
3406 Carp::confess($@) if $@;
3407 return if $CPAN::Signal;
3408 for (keys %$ret) {
9d61fa1d 3409 my $obj = $CPAN::META->instance("CPAN::Module",$_);
6d29edf5 3410 delete $ret->{$_}{modid}; # not needed here, maybe elsewhere
05454584
A
3411 $obj->set(%{$ret->{$_}});
3412 return if $CPAN::Signal;
3413 }
3414}
5f05dabc 3415
5e05dca5
A
3416#-> sub CPAN::Index::write_metadata_cache ;
3417sub write_metadata_cache {
3418 my($self) = @_;
3419 return unless $CPAN::Config->{'cache_metadata'};
3420 return unless $CPAN::META->has_usable("Storable");
3421 my $cache;
3422 foreach my $k (qw(CPAN::Bundle CPAN::Author CPAN::Module
3423 CPAN::Distribution)) {
6d29edf5 3424 $cache->{$k} = $CPAN::META->{readonly}{$k}; # unsafe meta access, ok
5e05dca5 3425 }
5de3f0da 3426 my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata");
c049f953
JH
3427 $cache->{last_time} = $LAST_TIME;
3428 $cache->{DATE_OF_02} = $DATE_OF_02;
6d29edf5
JH
3429 $cache->{PROTOCOL} = PROTOCOL;
3430 $CPAN::Frontend->myprint("Going to write $metadata_file\n");
c4d24d4c 3431 eval { Storable::nstore($cache, $metadata_file) };
5fc0f0f6 3432 $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
5e05dca5
A
3433}
3434
3435#-> sub CPAN::Index::read_metadata_cache ;
3436sub read_metadata_cache {
3437 my($self) = @_;
3438 return unless $CPAN::Config->{'cache_metadata'};
3439 return unless $CPAN::META->has_usable("Storable");
5de3f0da 3440 my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata");
5e05dca5
A
3441 return unless -r $metadata_file and -f $metadata_file;
3442 $CPAN::Frontend->myprint("Going to read $metadata_file\n");
3443 my $cache;
3444 eval { $cache = Storable::retrieve($metadata_file) };
5fc0f0f6 3445 $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
6d29edf5 3446 if (!$cache || ref $cache ne 'HASH'){
c049f953 3447 $LAST_TIME = 0;
6d29edf5
JH
3448 return;
3449 }
3450 if (exists $cache->{PROTOCOL}) {
3451 if (PROTOCOL > $cache->{PROTOCOL}) {
3452 $CPAN::Frontend->mywarn(sprintf("Ignoring Metadata cache written ".
5fc0f0f6 3453 "with protocol v%s, requiring v%s\n",
6d29edf5
JH
3454 $cache->{PROTOCOL},
3455 PROTOCOL)
3456 );
3457 return;
3458 }
3459 } else {
3460 $CPAN::Frontend->mywarn("Ignoring Metadata cache written ".
5fc0f0f6 3461 "with protocol v1.0\n");
6d29edf5
JH
3462 return;
3463 }
3464 my $clcnt = 0;
3465 my $idcnt = 0;
3466 while(my($class,$v) = each %$cache) {
3467 next unless $class =~ /^CPAN::/;
3468 $CPAN::META->{readonly}{$class} = $v; # unsafe meta access, ok
3469 while (my($id,$ro) = each %$v) {
3470 $CPAN::META->{readwrite}{$class}{$id} ||=
3471 $class->new(ID=>$id, RO=>$ro);
3472 $idcnt++;
c4d24d4c 3473 }
6d29edf5 3474 $clcnt++;
5e05dca5 3475 }
6d29edf5
JH
3476 unless ($clcnt) { # sanity check
3477 $CPAN::Frontend->myprint("Warning: Found no data in $metadata_file\n");
3478 return;
3479 }
3480 if ($idcnt < 1000) {
3481 $CPAN::Frontend->myprint("Warning: Found only $idcnt objects ".
3482 "in $metadata_file\n");
3483 return;
3484 }
3485 $CPAN::META->{PROTOCOL} ||=
3486 $cache->{PROTOCOL}; # reading does not up or downgrade, but it
3487 # does initialize to some protocol
c049f953
JH
3488 $LAST_TIME = $cache->{last_time};
3489 $DATE_OF_02 = $cache->{DATE_OF_02};
d5a05a34
RB
3490 $CPAN::Frontend->myprint(" Database was generated on $DATE_OF_02\n")
3491 if defined $DATE_OF_02; # An old cache may not contain DATE_OF_02
c049f953 3492 return;
5e05dca5
A
3493}
3494
05454584 3495package CPAN::InfoObj;
5f05dabc 3496
6d29edf5 3497# Accessors
35576f8c
A
3498sub cpan_userid {
3499 my $self = shift;
3500 $self->{RO}{CPAN_USERID}
3501}
3502
c049f953 3503sub id { shift->{ID}; }
6d29edf5 3504
05454584 3505#-> sub CPAN::InfoObj::new ;
6d29edf5
JH
3506sub new {
3507 my $this = bless {}, shift;
3508 %$this = @_;
3509 $this
3510}
3511
3512# The set method may only be used by code that reads index data or
3513# otherwise "objective" data from the outside world. All session
3514# related material may do anything else with instance variables but
3515# must not touch the hash under the RO attribute. The reason is that
3516# the RO hash gets written to Metadata file and is thus persistent.
5f05dabc 3517
05454584
A
3518#-> sub CPAN::InfoObj::set ;
3519sub set {
3520 my($self,%att) = @_;
6d29edf5
JH
3521 my $class = ref $self;
3522
3523 # This must be ||=, not ||, because only if we write an empty
3524 # reference, only then the set method will write into the readonly
3525 # area. But for Distributions that spring into existence, maybe
3526 # because of a typo, we do not like it that they are written into
3527 # the readonly area and made permanent (at least for a while) and
3528 # that is why we do not "allow" other places to call ->set.
8d97e4a1
JH
3529 unless ($self->id) {
3530 CPAN->debug("Bug? Empty ID, rejecting");
3531 return;
3532 }
6d29edf5
JH
3533 my $ro = $self->{RO} =
3534 $CPAN::META->{readonly}{$class}{$self->id} ||= {};
da199366 3535
6d29edf5
JH
3536 while (my($k,$v) = each %att) {
3537 $ro->{$k} = $v;
3538 }
3539}
5f05dabc 3540
05454584
A
3541#-> sub CPAN::InfoObj::as_glimpse ;
3542sub as_glimpse {
5f05dabc 3543 my($self) = @_;
05454584
A
3544 my(@m);
3545 my $class = ref($self);
3546 $class =~ s/^CPAN:://;
3547 push @m, sprintf "%-15s %s\n", $class, $self->{ID};
3548 join "", @m;
5f05dabc 3549}
3550
05454584
A
3551#-> sub CPAN::InfoObj::as_string ;
3552sub as_string {
3553 my($self) = @_;
3554 my(@m);
3555 my $class = ref($self);
3556 $class =~ s/^CPAN:://;
3557 push @m, $class, " id = $self->{ID}\n";
6d29edf5
JH
3558 for (sort keys %{$self->{RO}}) {
3559 # next if m/^(ID|RO)$/;
05454584 3560 my $extra = "";
09d9d230 3561 if ($_ eq "CPAN_USERID") {
9d61fa1d
A
3562 $extra .= " (".$self->author;
3563 my $email; # old perls!
3564 if ($email = $CPAN::META->instance("CPAN::Author",
3565 $self->cpan_userid
3566 )->email) {
3567 $extra .= " <$email>";
3568 } else {
3569 $extra .= " <no email>";
3570 }
3571 $extra .= ")";
3572 } elsif ($_ eq "FULLNAME") { # potential UTF-8 conversion
3573 push @m, sprintf " %-12s %s\n", $_, $self->fullname;
3574 next;
3575 }
6d29edf5
JH
3576 next unless defined $self->{RO}{$_};
3577 push @m, sprintf " %-12s %s%s\n", $_, $self->{RO}{$_}, $extra;
3578 }
3579 for (sort keys %$self) {
3580 next if m/^(ID|RO)$/;
3581 if (ref($self->{$_}) eq "ARRAY") {
3582 push @m, sprintf " %-12s %s\n", $_, "@{$self->{$_}}";
911a92db
GS
3583 } elsif (ref($self->{$_}) eq "HASH") {
3584 push @m, sprintf(
6d29edf5 3585 " %-12s %s\n",
911a92db
GS
3586 $_,
3587 join(" ",keys %{$self->{$_}}),
6d29edf5 3588 );
5f05dabc 3589 } else {
6d29edf5 3590 push @m, sprintf " %-12s %s\n", $_, $self->{$_};
05454584 3591 }
5f05dabc 3592 }
05454584 3593 join "", @m, "\n";
5f05dabc 3594}
3595
05454584
A
3596#-> sub CPAN::InfoObj::author ;
3597sub author {
3598 my($self) = @_;
9d61fa1d 3599 $CPAN::META->instance("CPAN::Author",$self->cpan_userid)->fullname;
5f05dabc 3600}
3601
6d29edf5 3602#-> sub CPAN::InfoObj::dump ;
36263cb3
GS
3603sub dump {
3604 my($self) = @_;
3605 require Data::Dumper;
6d29edf5 3606 print Data::Dumper::Dumper($self);
36263cb3
GS
3607}
3608
05454584 3609package CPAN::Author;
05454584 3610
c049f953
JH
3611#-> sub CPAN::Author::id
3612sub id {
3613 my $self = shift;
3614 my $id = $self->{ID};
3615 $CPAN::Frontend->mydie("Illegal author id[$id]") unless $id =~ /^[A-Z]/;
3616 $id;
3617}
3618
05454584
A
3619#-> sub CPAN::Author::as_glimpse ;
3620sub as_glimpse {
5f05dabc 3621 my($self) = @_;
05454584
A
3622 my(@m);
3623 my $class = ref($self);
3624 $class =~ s/^CPAN:://;
c049f953
JH
3625 push @m, sprintf(qq{%-15s %s ("%s" <%s>)\n},
3626 $class,
3627 $self->{ID},
3628 $self->fullname,
3629 $self->email);
05454584 3630 join "", @m;
5f05dabc 3631}
3632
05454584 3633#-> sub CPAN::Author::fullname ;
9d61fa1d 3634sub fullname {
8d97e4a1 3635 shift->{RO}{FULLNAME};
9d61fa1d 3636}
05454584 3637*name = \&fullname;
36263cb3 3638
05454584 3639#-> sub CPAN::Author::email ;
8d97e4a1
JH
3640sub email { shift->{RO}{EMAIL}; }
3641
d8773709 3642#-> sub CPAN::Author::ls ;
8d97e4a1
JH
3643sub ls {
3644 my $self = shift;
3645 my $id = $self->id;
3646
3647 # adapted from CPAN::Distribution::verifyMD5 ;
c049f953
JH
3648 my(@csf); # chksumfile
3649 @csf = $self->id =~ /(.)(.)(.*)/;
3650 $csf[1] = join "", @csf[0,1];
3651 $csf[2] = join "", @csf[1,2];
3652 my(@dl);
3653 @dl = $self->dir_listing([$csf[0],"CHECKSUMS"], 0);
3654 unless (grep {$_->[2] eq $csf[1]} @dl) {
3655 $CPAN::Frontend->myprint("No files in the directory of $id\n");
3656 return;
3657 }
3658 @dl = $self->dir_listing([@csf[0,1],"CHECKSUMS"], 0);
3659 unless (grep {$_->[2] eq $csf[2]} @dl) {
3660 $CPAN::Frontend->myprint("No files in the directory of $id\n");
3661 return;
3662 }
3663 @dl = $self->dir_listing([@csf,"CHECKSUMS"], 1);
3664 $CPAN::Frontend->myprint(join "", map {
d8773709 3665 sprintf("%8d %10s %s/%s\n", $_->[0], $_->[1], $id, $_->[2])
c049f953 3666 } sort { $a->[2] cmp $b->[2] } @dl);
8d97e4a1
JH
3667}
3668
c049f953 3669# returns an array of arrays, the latter contain (size,mtime,filename)
d8773709 3670#-> sub CPAN::Author::dir_listing ;
8d97e4a1
JH
3671sub dir_listing {
3672 my $self = shift;
3673 my $chksumfile = shift;
c049f953 3674 my $recursive = shift;
8d97e4a1 3675 my $lc_want =
5de3f0da
DR
3676 File::Spec->catfile($CPAN::Config->{keep_source_where},
3677 "authors", "id", @$chksumfile);
8d97e4a1 3678 local($") = "/";
c049f953
JH
3679 # connect "force" argument with "index_expire".
3680 my $force = 0;
3681 if (my @stat = stat $lc_want) {
3682 $force = $stat[9] + $CPAN::Config->{index_expire}*86400 <= time;
3683 }
8d97e4a1 3684 my $lc_file = CPAN::FTP->localize("authors/id/@$chksumfile",
c049f953 3685 $lc_want,$force);
8d97e4a1
JH
3686 unless ($lc_file) {
3687 $CPAN::Frontend->myprint("Trying $lc_want.gz\n");
3688 $chksumfile->[-1] .= ".gz";
3689 $lc_file = CPAN::FTP->localize("authors/id/@$chksumfile",
c049f953 3690 "$lc_want.gz",1);
8d97e4a1
JH
3691 if ($lc_file) {
3692 $lc_file =~ s{\.gz(?!\n)\Z}{}; #};
3693 CPAN::Tarzip->gunzip("$lc_file.gz",$lc_file);
3694 } else {
3695 return;
3696 }
3697 }
3698
3699 # adapted from CPAN::Distribution::MD5_check_file ;
1dbacee7 3700 my $fh = FileHandle->new;
8d97e4a1
JH
3701 my($cksum);
3702 if (open $fh, $lc_file){
3703 local($/);
3704 my $eval = <$fh>;
3705 $eval =~ s/\015?\012/\n/g;
3706 close $fh;
3707 my($comp) = Safe->new();
3708 $cksum = $comp->reval($eval);
3709 if ($@) {
3710 rename $lc_file, "$lc_file.bad";
3711 Carp::confess($@) if $@;
3712 }
3713 } else {
3714 Carp::carp "Could not open $lc_file for reading";
3715 }
3716 my(@result,$f);
3717 for $f (sort keys %$cksum) {
3718 if (exists $cksum->{$f}{isdir}) {
c049f953
JH
3719 if ($recursive) {
3720 my(@dir) = @$chksumfile;
3721 pop @dir;
3722 push @dir, $f, "CHECKSUMS";
3723 push @result, map {
3724 [$_->[0], $_->[1], "$f/$_->[2]"]
3725 } $self->dir_listing(\@dir,1);
3726 } else {
3727 push @result, [ 0, "-", $f ];
3728 }
8d97e4a1
JH
3729 } else {
3730 push @result, [
3731 ($cksum->{$f}{"size"}||0),
3732 $cksum->{$f}{"mtime"}||"---",
3733 $f
3734 ];
3735 }
3736 }
3737 @result;
3738}
5f05dabc 3739
05454584 3740package CPAN::Distribution;
5f05dabc 3741
6d29edf5
JH
3742# Accessors
3743sub cpan_comment { shift->{RO}{CPAN_COMMENT} }
3744
3745sub undelay {
3746 my $self = shift;
3747 delete $self->{later};
3748}
3749
d8773709 3750# CPAN::Distribution::normalize
8d97e4a1
JH
3751sub normalize {
3752 my($self,$s) = @_;
d8773709 3753 $s = $self->id unless defined $s;
c049f953
JH
3754 if (
3755 $s =~ tr|/|| == 1
3756 or
3757 $s !~ m|[A-Z]/[A-Z-]{2}/[A-Z-]{2,}/|
3758 ) {
3759 return $s if $s =~ m:^N/A|^Contact Author: ;
8d97e4a1 3760 $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4| or
5fc0f0f6 3761 $CPAN::Frontend->mywarn("Strange distribution name [$s]\n");
8d97e4a1
JH
3762 CPAN->debug("s[$s]") if $CPAN::DEBUG;
3763 }
3764 $s;
3765}
3766
6d29edf5
JH
3767#-> sub CPAN::Distribution::color_cmd_tmps ;
3768sub color_cmd_tmps {
3769 my($self) = shift;
3770 my($depth) = shift || 0;
3771 my($color) = shift || 0;
35576f8c 3772 my($ancestors) = shift || [];
6d29edf5
JH
3773 # a distribution needs to recurse into its prereq_pms
3774
3775 return if exists $self->{incommandcolor}
3776 && $self->{incommandcolor}==$color;
35576f8c
A
3777 if ($depth>=100){
3778 $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors));
3779 }
3780 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
6d29edf5
JH
3781 my $prereq_pm = $self->prereq_pm;
3782 if (defined $prereq_pm) {
3783 for my $pre (keys %$prereq_pm) {
3784 my $premo = CPAN::Shell->expand("Module",$pre);
35576f8c 3785 $premo->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
6d29edf5
JH
3786 }
3787 }
3788 if ($color==0) {
3789 delete $self->{sponsored_mods};
3790 delete $self->{badtestcnt};
3791 }
3792 $self->{incommandcolor} = $color;
3793}
3794
911a92db
GS
3795#-> sub CPAN::Distribution::as_string ;
3796sub as_string {
3797 my $self = shift;
3798 $self->containsmods;
3799 $self->SUPER::as_string(@_);
3800}
3801
3802#-> sub CPAN::Distribution::containsmods ;
3803sub containsmods {
3804 my $self = shift;
9d61fa1d
A
3805 return keys %{$self->{CONTAINSMODS}} if exists $self->{CONTAINSMODS};
3806 my $dist_id = $self->{ID};
911a92db 3807 for my $mod ($CPAN::META->all_objects("CPAN::Module")) {
6d29edf5 3808 my $mod_file = $mod->cpan_file or next;
911a92db 3809 my $mod_id = $mod->{ID} or next;
6d29edf5
JH
3810 # warn "mod_file[$mod_file] dist_id[$dist_id] mod_id[$mod_id]";
3811 # sleep 1;
911a92db
GS
3812 $self->{CONTAINSMODS}{$mod_id} = undef if $mod_file eq $dist_id;
3813 }
9d61fa1d 3814 keys %{$self->{CONTAINSMODS}};
911a92db
GS
3815}
3816
d8773709
JH
3817#-> sub CPAN::Distribution::uptodate ;
3818sub uptodate {
3819 my($self) = @_;
3820 my $c;
3821 foreach $c ($self->containsmods) {
3822 my $obj = CPAN::Shell->expandany($c);
3823 return 0 unless $obj->uptodate;
3824 }
3825 return 1;
3826}
3827
05454584
A
3828#-> sub CPAN::Distribution::called_for ;
3829sub called_for {
3830 my($self,$id) = @_;
6d29edf5
JH
3831 $self->{CALLED_FOR} = $id if defined $id;
3832 return $self->{CALLED_FOR};
5f05dabc 3833}
3834
c049f953 3835#-> sub CPAN::Distribution::safe_chdir ;
d8773709
JH
3836sub safe_chdir {
3837 my($self,$todir) = @_;
3838 # we die if we cannot chdir and we are debuggable
3839 Carp::confess("safe_chdir called without todir argument")
3840 unless defined $todir and length $todir;
3841 if (chdir $todir) {
3842 $self->debug(sprintf "changed directory to %s", CPAN::anycwd())
3843 if $CPAN::DEBUG;
3844 } else {
3845 my $cwd = CPAN::anycwd();
3846 $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }.
3847 qq{to todir[$todir]: $!});
3848 }
3849}
3850
05454584
A
3851#-> sub CPAN::Distribution::get ;
3852sub get {
5f05dabc 3853 my($self) = @_;
da199366
A
3854 EXCUSE: {
3855 my @e;
05454584 3856 exists $self->{'build_dir'} and push @e,
c4d24d4c 3857 "Is already unwrapped into directory $self->{'build_dir'}";
c356248b 3858 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
da199366 3859 }
d8773709
JH
3860 my $sub_wd = CPAN::anycwd(); # for cleaning up as good as possible
3861
3862 #
3863 # Get the file on local disk
3864 #
3865
05454584
A
3866 my($local_file);
3867 my($local_wanted) =
5de3f0da
DR
3868 File::Spec->catfile(
3869 $CPAN::Config->{keep_source_where},
3870 "authors",
3871 "id",
5fc0f0f6 3872 split(/\//,$self->id)
5de3f0da 3873 );
05454584
A
3874
3875 $self->debug("Doing localize") if $CPAN::DEBUG;
c049f953
JH
3876 unless ($local_file =
3877 CPAN::FTP->localize("authors/id/$self->{ID}",
3878 $local_wanted)) {
3879 my $note = "";
3880 if ($CPAN::Index::DATE_OF_02) {
3881 $note = "Note: Current database in memory was generated ".
3882 "on $CPAN::Index::DATE_OF_02\n";
3883 }
3884 $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n$note");
3885 }
d8773709 3886 $self->debug("local_file[$local_file]") if $CPAN::DEBUG;
05454584 3887 $self->{localfile} = $local_file;
d8773709 3888 return if $CPAN::Signal;
05454584 3889
d8773709
JH
3890 #
3891 # Check integrity
3892 #
5b6aeab6
GA
3893 if ($CPAN::META->has_inst("Digest::MD5")) {
3894 $self->debug("Digest::MD5 is installed, verifying");
05454584 3895 $self->verifyMD5;
55e314ee 3896 } else {
5b6aeab6 3897 $self->debug("Digest::MD5 is NOT installed");
55e314ee 3898 }
d8773709
JH
3899 return if $CPAN::Signal;
3900
3901 #
3902 # Create a clean room and go there
3903 #
3904 $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); # unsafe meta access, ok
3905 my $builddir = $CPAN::META->{cachemgr}->dir; # unsafe meta access, ok
3906 $self->safe_chdir($builddir);
55e314ee
A
3907 $self->debug("Removing tmp") if $CPAN::DEBUG;
3908 File::Path::rmtree("tmp");
3909 mkdir "tmp", 0755 or Carp::croak "Couldn't mkdir tmp: $!";
d8773709
JH
3910 if ($CPAN::Signal){
3911 $self->safe_chdir($sub_wd);
3912 return;
3913 }
3914 $self->safe_chdir("tmp");
3915
3916 #
3917 # Unpack the goods
3918 #
3919 if ($local_file =~ /(\.tar\.(gz|Z)|\.tgz)(?!\n)\Z/i){
5a5fac02 3920 $self->{was_uncompressed}++ unless CPAN::Tarzip->gtest($local_file);
55e314ee 3921 $self->untar_me($local_file);
05d2a450 3922 } elsif ( $local_file =~ /\.zip(?!\n)\Z/i ) {
55e314ee 3923 $self->unzip_me($local_file);
05d2a450 3924 } elsif ( $local_file =~ /\.pm\.(gz|Z)(?!\n)\Z/) {
5a5fac02 3925 $self->{was_uncompressed}++ unless CPAN::Tarzip->gtest($local_file);
55e314ee
A
3926 $self->pm2dir_me($local_file);
3927 } else {
3928 $self->{archived} = "NO";
d8773709
JH
3929 $self->safe_chdir($sub_wd);
3930 return;
5f05dabc 3931 }
d8773709
JH
3932
3933 # we are still in the tmp directory!
3934 # Let's check if the package has its own directory.
3935 my $dh = DirHandle->new(File::Spec->curdir)
3936 or Carp::croak("Couldn't opendir .: $!");
3937 my @readdir = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh->read; ### MAC??
3938 $dh->close;
3939 my ($distdir,$packagedir);
3940 if (@readdir == 1 && -d $readdir[0]) {
05d2a450 3941 $distdir = $readdir[0];
5de3f0da 3942 $packagedir = File::Spec->catdir($builddir,$distdir);
d8773709
JH
3943 $self->debug("packagedir[$packagedir]builddir[$builddir]distdir[$distdir]")
3944 if $CPAN::DEBUG;
6d29edf5
JH
3945 -d $packagedir and $CPAN::Frontend->myprint("Removing previously used ".
3946 "$packagedir\n");
05d2a450 3947 File::Path::rmtree($packagedir);
6d29edf5
JH
3948 rename($distdir,$packagedir) or
3949 Carp::confess("Couldn't rename $distdir to $packagedir: $!");
d8773709
JH
3950 $self->debug(sprintf("renamed distdir[%s] to packagedir[%s] -e[%s]-d[%s]",
3951 $distdir,
3952 $packagedir,
3953 -e $packagedir,
3954 -d $packagedir,
3955 )) if $CPAN::DEBUG;
3956 } else {
3957 my $userid = $self->cpan_userid;
3958 unless ($userid) {
3959 CPAN->debug("no userid? self[$self]");
3960 $userid = "anon";
3961 }
3962 my $pragmatic_dir = $userid . '000';
3963 $pragmatic_dir =~ s/\W_//g;
3964 $pragmatic_dir++ while -d "../$pragmatic_dir";
5de3f0da 3965 $packagedir = File::Spec->catdir($builddir,$pragmatic_dir);
d8773709
JH
3966 $self->debug("packagedir[$packagedir]") if $CPAN::DEBUG;
3967 File::Path::mkpath($packagedir);
3968 my($f);
3969 for $f (@readdir) { # is already without "." and ".."
5de3f0da 3970 my $to = File::Spec->catdir($packagedir,$f);
d8773709 3971 rename($f,$to) or Carp::confess("Couldn't rename $f to $to: $!");
9d61fa1d 3972 }
d8773709
JH
3973 }
3974 if ($CPAN::Signal){
3975 $self->safe_chdir($sub_wd);
3976 return;
3977 }
05d2a450 3978
d8773709 3979 $self->{'build_dir'} = $packagedir;
6f14f089 3980 $self->safe_chdir($builddir);
d8773709
JH
3981 File::Path::rmtree("tmp");
3982
5de3f0da 3983 my($mpl) = File::Spec->catfile($packagedir,"Makefile.PL");
d8773709
JH
3984 my($mpl_exists) = -f $mpl;
3985 unless ($mpl_exists) {
c049f953
JH
3986 # NFS has been reported to have racing problems after the
3987 # renaming of a directory in some environments.
3988 # This trick helps.
3989 sleep 1;
3990 my $mpldh = DirHandle->new($packagedir)
d8773709 3991 or Carp::croak("Couldn't opendir $packagedir: $!");
c049f953
JH
3992 $mpl_exists = grep /^Makefile\.PL$/, $mpldh->read;
3993 $mpldh->close;
d8773709
JH
3994 }
3995 unless ($mpl_exists) {
3996 $self->debug(sprintf("makefilepl[%s]anycwd[%s]",
3997 $mpl,
3998 CPAN::anycwd(),
3999 )) if $CPAN::DEBUG;
5de3f0da 4000 my($configure) = File::Spec->catfile($packagedir,"Configure");
05d2a450 4001 if (-f $configure) {
d8773709
JH
4002 # do we have anything to do?
4003 $self->{'configure'} = $configure;
5de3f0da 4004 } elsif (-f File::Spec->catfile($packagedir,"Makefile")) {
d8773709 4005 $CPAN::Frontend->myprint(qq{
09d9d230
A
4006Package comes with a Makefile and without a Makefile.PL.
4007We\'ll try to build it with that Makefile then.
4008});
d8773709
JH
4009 $self->{writemakefile} = "YES";
4010 sleep 2;
05d2a450 4011 } else {
d8773709
JH
4012 my $cf = $self->called_for || "unknown";
4013 if ($cf =~ m|/|) {
4014 $cf =~ s|.*/||;
4015 $cf =~ s|\W.*||;
4016 }
4017 $cf =~ s|[/\\:]||g; # risk of filesystem damage
4018 $cf = "unknown" unless length($cf);
4019 $CPAN::Frontend->myprint(qq{Package seems to come without Makefile.PL.
4020 (The test -f "$mpl" returned false.)
4021 Writing one on our own (setting NAME to $cf)\a\n});
4022 $self->{had_no_makefile_pl}++;
4023 sleep 3;
4024
4025 # Writing our own Makefile.PL
4026
4027 my $fh = FileHandle->new;
4028 $fh->open(">$mpl")
4029 or Carp::croak("Could not open >$mpl: $!");
4030 $fh->print(
55e314ee
A
4031qq{# This Makefile.PL has been autogenerated by the module CPAN.pm
4032# because there was no Makefile.PL supplied.
05454584 4033# Autogenerated on: }.scalar localtime().qq{
55e314ee 4034
09d9d230
A
4035use ExtUtils::MakeMaker;
4036WriteMakefile(NAME => q[$cf]);
55e314ee 4037
05454584 4038});
d8773709 4039 $fh->close;
05d2a450 4040 }
5f05dabc 4041 }
d8773709 4042
05454584 4043 return $self;
5f05dabc 4044}
4045
6d29edf5 4046# CPAN::Distribution::untar_me ;
55e314ee
A
4047sub untar_me {
4048 my($self,$local_file) = @_;
4049 $self->{archived} = "tar";
09d9d230 4050 if (CPAN::Tarzip->untar($local_file)) {
55e314ee
A
4051 $self->{unwrapped} = "YES";
4052 } else {
4053 $self->{unwrapped} = "NO";
4054 }
4055}
4056
6d29edf5 4057# CPAN::Distribution::unzip_me ;
55e314ee
A
4058sub unzip_me {
4059 my($self,$local_file) = @_;
05d2a450 4060 $self->{archived} = "zip";
c4d24d4c 4061 if (CPAN::Tarzip->unzip($local_file)) {
55e314ee
A
4062 $self->{unwrapped} = "YES";
4063 } else {
4064 $self->{unwrapped} = "NO";
4065 }
c4d24d4c 4066 return;
55e314ee
A
4067}
4068
4069sub pm2dir_me {
4070 my($self,$local_file) = @_;
4071 $self->{archived} = "pm";
4072 my $to = File::Basename::basename($local_file);
05d2a450 4073 $to =~ s/\.(gz|Z)(?!\n)\Z//;
09d9d230 4074 if (CPAN::Tarzip->gunzip($local_file,$to)) {
55e314ee
A
4075 $self->{unwrapped} = "YES";
4076 } else {
4077 $self->{unwrapped} = "NO";
4078 }
4079}
4080
05454584
A
4081#-> sub CPAN::Distribution::new ;
4082sub new {
4083 my($class,%att) = @_;
5f05dabc 4084
5e05dca5 4085 # $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new();
5f05dabc 4086
05454584
A
4087 my $this = { %att };
4088 return bless $this, $class;
5f05dabc 4089}
4090
05454584
A
4091#-> sub CPAN::Distribution::look ;
4092sub look {
5f05dabc 4093 my($self) = @_;
36263cb3
GS
4094
4095 if ($^O eq 'MacOS') {
be708cc0 4096 $self->Mac::BuildTools::look;
36263cb3
GS
4097 return;
4098 }
4099
05454584 4100 if ( $CPAN::Config->{'shell'} ) {
c356248b 4101 $CPAN::Frontend->myprint(qq{
05454584 4102Trying to open a subshell in the build directory...
c356248b 4103});
05454584 4104 } else {
c356248b 4105 $CPAN::Frontend->myprint(qq{
05454584
A
4106Your configuration does not define a value for subshells.
4107Please define it with "o conf shell <your shell>"
c356248b 4108});
05454584 4109 return;
5f05dabc 4110 }
05454584 4111 my $dist = $self->id;
c049f953
JH
4112 my $dir;
4113 unless ($dir = $self->dir) {
4114 $self->get;
4115 }
4116 unless ($dir ||= $self->dir) {
4117 $CPAN::Frontend->mywarn(qq{
4118Could not determine which directory to use for looking at $dist.
4119});
4120 return;
4121 }
9d61fa1d 4122 my $pwd = CPAN::anycwd();
c049f953 4123 $self->safe_chdir($dir);
c356248b 4124 $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
35576f8c
A
4125 unless (system($CPAN::Config->{'shell'}) == 0) {
4126 my $code = $? >> 8;
4127 $CPAN::Frontend->mywarn("Subprocess shell exit code $code\n");
4128 }
c049f953 4129 $self->safe_chdir($pwd);
5f05dabc 4130}
4131
6d29edf5 4132# CPAN::Distribution::cvs_import ;
911a92db
GS
4133sub cvs_import {
4134 my($self) = @_;
4135 $self->get;
4136 my $dir = $self->dir;
4137
4138 my $package = $self->called_for;
4139 my $module = $CPAN::META->instance('CPAN::Module', $package);
6d29edf5 4140 my $version = $module->cpan_version;
911a92db 4141
6d29edf5 4142 my $userid = $self->cpan_userid;
911a92db 4143
5fc0f0f6 4144 my $cvs_dir = (split /\//, $dir)[-1];
05d2a450 4145 $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//;
911a92db
GS
4146 my $cvs_root =
4147 $CPAN::Config->{cvsroot} || $ENV{CVSROOT};
4148 my $cvs_site_perl =
4149 $CPAN::Config->{cvs_site_perl} || $ENV{CVS_SITE_PERL};
4150 if ($cvs_site_perl) {
4151 $cvs_dir = "$cvs_site_perl/$cvs_dir";
4152 }
4153 my $cvs_log = qq{"imported $package $version sources"};
4154 $version =~ s/\./_/g;
4155 my @cmd = ('cvs', '-d', $cvs_root, 'import', '-m', $cvs_log,
4156 "$cvs_dir", $userid, "v$version");
4157
9d61fa1d 4158 my $pwd = CPAN::anycwd();
05d2a450 4159 chdir($dir) or $CPAN::Frontend->mydie(qq{Could not chdir to "$dir": $!});
911a92db
GS
4160
4161 $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
4162
4163 $CPAN::Frontend->myprint(qq{@cmd\n});
de34a54b 4164 system(@cmd) == 0 or
911a92db 4165 $CPAN::Frontend->mydie("cvs import failed");
05d2a450 4166 chdir($pwd) or $CPAN::Frontend->mydie(qq{Could not chdir to "$pwd": $!});
911a92db
GS
4167}
4168
05454584
A
4169#-> sub CPAN::Distribution::readme ;
4170sub readme {
5f05dabc 4171 my($self) = @_;
05454584
A
4172 my($dist) = $self->id;
4173 my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/;
4174 $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG;
4175 my($local_file);
4176 my($local_wanted) =
5de3f0da
DR
4177 File::Spec->catfile(
4178 $CPAN::Config->{keep_source_where},
4179 "authors",
4180 "id",
5fc0f0f6 4181 split(/\//,"$sans.readme"),
5de3f0da 4182 );
05454584 4183 $self->debug("Doing localize") if $CPAN::DEBUG;
c356248b
A
4184 $local_file = CPAN::FTP->localize("authors/id/$sans.readme",
4185 $local_wanted)
4186 or $CPAN::Frontend->mydie(qq{No $sans.readme found});;
f14b5cec
JH
4187
4188 if ($^O eq 'MacOS') {
be708cc0 4189 Mac::BuildTools::launch_file($local_file);
f14b5cec
JH
4190 return;
4191 }
4192
05454584 4193 my $fh_pager = FileHandle->new;
c356248b 4194 local($SIG{PIPE}) = "IGNORE";
05454584
A
4195 $fh_pager->open("|$CPAN::Config->{'pager'}")
4196 or die "Could not open pager $CPAN::Config->{'pager'}: $!";
4197 my $fh_readme = FileHandle->new;
c356248b
A
4198 $fh_readme->open($local_file)
4199 or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!});
4200 $CPAN::Frontend->myprint(qq{
4201Displaying file
4202 $local_file
4203with pager "$CPAN::Config->{'pager'}"
4204});
4205 sleep 2;
05454584 4206 $fh_pager->print(<$fh_readme>);
5f05dabc 4207}
4208
05454584
A
4209#-> sub CPAN::Distribution::verifyMD5 ;
4210sub verifyMD5 {
5f05dabc 4211 my($self) = @_;
05454584
A
4212 EXCUSE: {
4213 my @e;
4214 $self->{MD5_STATUS} ||= "";
4215 $self->{MD5_STATUS} eq "OK" and push @e, "MD5 Checksum was ok";
c356248b 4216 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
05454584 4217 }
55e314ee 4218 my($lc_want,$lc_file,@local,$basename);
5fc0f0f6 4219 @local = split(/\//,$self->id);
55e314ee 4220 pop @local;
05454584 4221 push @local, "CHECKSUMS";
55e314ee 4222 $lc_want =
5de3f0da
DR
4223 File::Spec->catfile($CPAN::Config->{keep_source_where},
4224 "authors", "id", @local);
05454584
A
4225 local($") = "/";
4226 if (
c356248b 4227 -s $lc_want
05454584 4228 &&
55e314ee 4229 $self->MD5_check_file($lc_want)
05454584
A
4230 ) {
4231 return $self->{MD5_STATUS} = "OK";
4232 }
55e314ee 4233 $lc_file = CPAN::FTP->localize("authors/id/@local",
c356248b 4234 $lc_want,1);
55e314ee 4235 unless ($lc_file) {
8d97e4a1 4236 $CPAN::Frontend->myprint("Trying $lc_want.gz\n");
05454584 4237 $local[-1] .= ".gz";
55e314ee 4238 $lc_file = CPAN::FTP->localize("authors/id/@local",
c356248b
A
4239 "$lc_want.gz",1);
4240 if ($lc_file) {
05d2a450 4241 $lc_file =~ s/\.gz(?!\n)\Z//;
09d9d230 4242 CPAN::Tarzip->gunzip("$lc_file.gz",$lc_file);
c356248b
A
4243 } else {
4244 return;
4245 }
05454584 4246 }
55e314ee 4247 $self->MD5_check_file($lc_file);
5f05dabc 4248}
4249
05454584
A
4250#-> sub CPAN::Distribution::MD5_check_file ;
4251sub MD5_check_file {
55e314ee
A
4252 my($self,$chk_file) = @_;
4253 my($cksum,$file,$basename);
c356248b 4254 $file = $self->{localfile};
55e314ee
A
4255 $basename = File::Basename::basename($file);
4256 my $fh = FileHandle->new;
55e314ee 4257 if (open $fh, $chk_file){
c356248b 4258 local($/);
05454584 4259 my $eval = <$fh>;
f14b5cec 4260 $eval =~ s/\015?\012/\n/g;
05454584
A
4261 close $fh;
4262 my($comp) = Safe->new();
4263 $cksum = $comp->reval($eval);
55e314ee
A
4264 if ($@) {
4265 rename $chk_file, "$chk_file.bad";
4266 Carp::confess($@) if $@;
4267 }
4268 } else {
4269 Carp::carp "Could not open $chk_file for reading";
4270 }
09d9d230
A
4271
4272 if (exists $cksum->{$basename}{md5}) {
55e314ee 4273 $self->debug("Found checksum for $basename:" .
09d9d230
A
4274 "$cksum->{$basename}{md5}\n") if $CPAN::DEBUG;
4275
4276 open($fh, $file);
4277 binmode $fh;
4278 my $eq = $self->eq_MD5($fh,$cksum->{$basename}{'md5'});
4279 $fh->close;
4280 $fh = CPAN::Tarzip->TIEHANDLE($file);
4281
4282 unless ($eq) {
4283 # had to inline it, when I tied it, the tiedness got lost on
4284 # the call to eq_MD5. (Jan 1998)
5b6aeab6 4285 my $md5 = Digest::MD5->new;
09d9d230
A
4286 my($data,$ref);
4287 $ref = \$data;
36263cb3 4288 while ($fh->READ($ref, 4096) > 0){
09d9d230
A
4289 $md5->add($data);
4290 }
4291 my $hexdigest = $md5->hexdigest;
4292 $eq += $hexdigest eq $cksum->{$basename}{'md5-ungz'};
4293 }
4294
4295 if ($eq) {
4296 $CPAN::Frontend->myprint("Checksum for $file ok\n");
4297 return $self->{MD5_STATUS} = "OK";
05454584 4298 } else {
de34a54b 4299 $CPAN::Frontend->myprint(qq{\nChecksum mismatch for }.
c356248b
A
4300 qq{distribution file. }.
4301 qq{Please investigate.\n\n}.
4302 $self->as_string,
4303 $CPAN::META->instance(
4304 'CPAN::Author',
6d29edf5 4305 $self->cpan_userid
c356248b 4306 )->as_string);
de34a54b
JH
4307
4308 my $wrap = qq{I\'d recommend removing $file. Its MD5
c4d24d4c
A
4309checksum is incorrect. Maybe you have configured your 'urllist' with
4310a bad URL. Please check this array with 'o conf urllist', and
55e314ee 4311retry.};
de34a54b 4312
c4d24d4c
A
4313 $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap));
4314
4315 # former versions just returned here but this seems a
4316 # serious threat that deserves a die
4317
4318 # $CPAN::Frontend->myprint("\n\n");
4319 # sleep 3;
4320 # return;
5f05dabc 4321 }
09d9d230 4322 # close $fh if fileno($fh);
5f05dabc 4323 } else {
55e314ee
A
4324 $self->{MD5_STATUS} ||= "";
4325 if ($self->{MD5_STATUS} eq "NIL") {
5a5fac02
JH
4326 $CPAN::Frontend->mywarn(qq{
4327Warning: No md5 checksum for $basename in $chk_file.
4328
4329The cause for this may be that the file is very new and the checksum
4330has not yet been calculated, but it may also be that something is
4331going awry right now.
c356248b 4332});
5a5fac02
JH
4333 my $answer = ExtUtils::MakeMaker::prompt("Proceed?", "yes");
4334 $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.");
55e314ee
A
4335 }
4336 $self->{MD5_STATUS} = "NIL";
4337 return;
5f05dabc 4338 }
4339}
4340
05454584
A
4341#-> sub CPAN::Distribution::eq_MD5 ;
4342sub eq_MD5 {
4343 my($self,$fh,$expectMD5) = @_;
5b6aeab6 4344 my $md5 = Digest::MD5->new;
09d9d230
A
4345 my($data);
4346 while (read($fh, $data, 4096)){
4347 $md5->add($data);
4348 }
4349 # $md5->addfile($fh);
05454584 4350 my $hexdigest = $md5->hexdigest;
09d9d230 4351 # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]";
05454584
A
4352 $hexdigest eq $expectMD5;
4353}
5f05dabc 4354
05454584 4355#-> sub CPAN::Distribution::force ;
c4d24d4c
A
4356
4357# Both modules and distributions know if "force" is in effect by
4358# autoinspection, not by inspecting a global variable. One of the
4359# reason why this was chosen to work that way was the treatment of
4360# dependencies. They should not autpomatically inherit the force
4361# status. But this has the downside that ^C and die() will return to
4362# the prompt but will not be able to reset the force_update
4363# attributes. We try to correct for it currently in the read_metadata
4364# routine, and immediately before we check for a Signal. I hope this
4365# works out in one of v1.57_53ff
4366
5f05dabc 4367sub force {
c4d24d4c 4368 my($self, $method) = @_;
f610777f
A
4369 for my $att (qw(
4370 MD5_STATUS archived build_dir localfile make install unwrapped
36263cb3 4371 writemakefile
f610777f
A
4372 )) {
4373 delete $self->{$att};
4374 }
c4d24d4c
A
4375 if ($method && $method eq "install") {
4376 $self->{"force_update"}++; # name should probably have been force_install
4377 }
4378}
4379
4380#-> sub CPAN::Distribution::unforce ;
4381sub unforce {
4382 my($self) = @_;
4383 delete $self->{'force_update'};
5f05dabc 4384}
4385
de34a54b 4386#-> sub CPAN::Distribution::isa_perl ;
09d9d230
A
4387sub isa_perl {
4388 my($self) = @_;
4389 my $file = File::Basename::basename($self->id);
05d2a450
A
4390 if ($file =~ m{ ^ perl
4391 -?
4392 (5)
4393 ([._-])
4394 (
4395 \d{3}(_[0-4][0-9])?
4396 |
4397 \d*[24680]\.\d+
4398 )
4399 \.tar[._-]gz
4400 (?!\n)\Z
4401 }xs){
4402 return "$1.$3";
6d29edf5
JH
4403 } elsif ($self->cpan_comment
4404 &&
4405 $self->cpan_comment =~ /isa_perl\(.+?\)/){
05d2a450
A
4406 return $1;
4407 }
09d9d230
A
4408}
4409
d4fd5c69
A
4410#-> sub CPAN::Distribution::perl ;
4411sub perl {
4412 my($self) = @_;
5de3f0da 4413 my($perl) = File::Spec->file_name_is_absolute($^X) ? $^X : "";
9d61fa1d 4414 my $pwd = CPAN::anycwd();
5de3f0da 4415 my $candidate = File::Spec->catfile($pwd,$^X);
e50380aa 4416 $perl ||= $candidate if MM->maybe_command($candidate);
d4fd5c69
A
4417 unless ($perl) {
4418 my ($component,$perl_name);
911a92db 4419 DIST_PERLNAME: foreach $perl_name ($^X, 'perl', 'perl5', "perl$]") {
5de3f0da 4420 PATH_COMPONENT: foreach $component (File::Spec->path(),
c356248b 4421 $Config::Config{'binexp'}) {
d4fd5c69 4422 next unless defined($component) && $component;
5de3f0da 4423 my($abs) = File::Spec->catfile($component,$perl_name);
d4fd5c69
A
4424 if (MM->maybe_command($abs)) {
4425 $perl = $abs;
4426 last DIST_PERLNAME;
4427 }
4428 }
4429 }
4430 }
4431 $perl;
4432}
4433
05454584
A
4434#-> sub CPAN::Distribution::make ;
4435sub make {
4436 my($self) = @_;
c356248b 4437 $CPAN::Frontend->myprint(sprintf "Running make for %s\n", $self->id);
09d9d230
A
4438 # Emergency brake if they said install Pippi and get newest perl
4439 if ($self->isa_perl) {
4440 if (
c4d24d4c
A
4441 $self->called_for ne $self->id &&
4442 ! $self->{force_update}
09d9d230 4443 ) {
de34a54b
JH
4444 # if we die here, we break bundles
4445 $CPAN::Frontend->mywarn(sprintf qq{
09d9d230
A
4446The most recent version "%s" of the module "%s"
4447comes with the current version of perl (%s).
4448I\'ll build that only if you ask for something like
4449 force install %s
4450or
4451 install %s
4452},
4453 $CPAN::META->instance(
4454 'CPAN::Module',
4455 $self->called_for
6d29edf5 4456 )->cpan_version,
09d9d230
A
4457 $self->called_for,
4458 $self->isa_perl,
4459 $self->called_for,
4460 $self->id);
de34a54b 4461 sleep 5; return;
09d9d230
A
4462 }
4463 }
05454584
A
4464 $self->get;
4465 EXCUSE: {
4466 my @e;
4467 $self->{archived} eq "NO" and push @e,
4468 "Is neither a tar nor a zip archive.";
5f05dabc 4469
d4fd5c69 4470 $self->{unwrapped} eq "NO" and push @e,
05454584
A
4471 "had problems unarchiving. Please build manually";
4472
4473 exists $self->{writemakefile} &&
36263cb3
GS
4474 $self->{writemakefile} =~ m/ ^ NO\s* ( .* ) /sx and push @e,
4475 $1 || "Had some problem writing Makefile";
05454584
A
4476
4477 defined $self->{'make'} and push @e,
6d29edf5
JH
4478 "Has already been processed within this session";
4479
4480 exists $self->{later} and length($self->{later}) and
4481 push @e, $self->{later};
05454584 4482
c356248b 4483 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
5f05dabc 4484 }
c356248b 4485 $CPAN::Frontend->myprint("\n CPAN.pm: Going to build ".$self->id."\n\n");
05454584
A
4486 my $builddir = $self->dir;
4487 chdir $builddir or Carp::croak("Couldn't chdir $builddir: $!");
4488 $self->debug("Changed directory to $builddir") if $CPAN::DEBUG;
4489
f14b5cec 4490 if ($^O eq 'MacOS') {
be708cc0 4491 Mac::BuildTools::make($self);
f14b5cec
JH
4492 return;
4493 }
4494
05454584
A
4495 my $system;
4496 if ($self->{'configure'}) {
09d9d230 4497 $system = $self->{'configure'};
5f05dabc 4498 } else {
d4fd5c69
A
4499 my($perl) = $self->perl or die "Couldn\'t find executable perl\n";
4500 my $switch = "";
4501# This needs a handler that can be turned on or off:
4502# $switch = "-MExtUtils::MakeMaker ".
4503# "-Mops=:default,:filesys_read,:filesys_open,require,chdir"
4504# if $] > 5.00310;
4505 $system = "$perl $switch Makefile.PL $CPAN::Config->{makepl_arg}";
4506 }
09d9d230 4507 unless (exists $self->{writemakefile}) {
e50380aa
A
4508 local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" };
4509 my($ret,$pid);
4510 $@ = "";
4511 if ($CPAN::Config->{inactivity_timeout}) {
4512 eval {
4513 alarm $CPAN::Config->{inactivity_timeout};
f14b5cec 4514 local $SIG{CHLD}; # = sub { wait };
e50380aa
A
4515 if (defined($pid = fork)) {
4516 if ($pid) { #parent
f14b5cec
JH
4517 # wait;
4518 waitpid $pid, 0;
e50380aa 4519 } else { #child
09d9d230
A
4520 # note, this exec isn't necessary if
4521 # inactivity_timeout is 0. On the Mac I'd
4522 # suggest, we set it always to 0.
4523 exec $system;
e50380aa
A
4524 }
4525 } else {
c356248b 4526 $CPAN::Frontend->myprint("Cannot fork: $!");
e50380aa 4527 return;
05454584 4528 }
e50380aa
A
4529 };
4530 alarm 0;
4531 if ($@){
4532 kill 9, $pid;
4533 waitpid $pid, 0;
c356248b 4534 $CPAN::Frontend->myprint($@);
36263cb3 4535 $self->{writemakefile} = "NO $@";
e50380aa 4536 $@ = "";
05454584
A
4537 return;
4538 }
e50380aa 4539 } else {
2e2b7522
GS
4540 $ret = system($system);
4541 if ($ret != 0) {
36263cb3 4542 $self->{writemakefile} = "NO Makefile.PL returned status $ret";
2e2b7522 4543 return;
09d9d230 4544 }
e50380aa 4545 }
36263cb3
GS
4546 if (-f "Makefile") {
4547 $self->{writemakefile} = "YES";
c4d24d4c 4548 delete $self->{make_clean}; # if cleaned before, enable next
36263cb3
GS
4549 } else {
4550 $self->{writemakefile} =
4551 qq{NO Makefile.PL refused to write a Makefile.};
29ca949e 4552 # It's probably worth it to record the reason, so let's retry
36263cb3
GS
4553 # local $/;
4554 # my $fh = IO::File->new("$system |"); # STDERR? STDIN?
4555 # $self->{writemakefile} .= <$fh>;
4556 }
05454584 4557 }
c4d24d4c
A
4558 if ($CPAN::Signal){
4559 delete $self->{force_update};
4560 return;
4561 }
6d29edf5
JH
4562 if (my @prereq = $self->unsat_prereq){
4563 return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner
4564 }
4565 $system = join " ", $CPAN::Config->{'make'}, $CPAN::Config->{make_arg};
4566 if (system($system) == 0) {
4567 $CPAN::Frontend->myprint(" $system -- OK\n");
4568 $self->{'make'} = "YES";
4569 } else {
4570 $self->{writemakefile} ||= "YES";
4571 $self->{'make'} = "NO";
4572 $CPAN::Frontend->myprint(" $system -- NOT OK\n");
4573 }
4574}
f610777f 4575
6d29edf5
JH
4576sub follow_prereqs {
4577 my($self) = shift;
4578 my(@prereq) = @_;
4579 my $id = $self->id;
4580 $CPAN::Frontend->myprint("---- Unsatisfied dependencies detected ".
4581 "during [$id] -----\n");
4582
4583 for my $p (@prereq) {
f610777f 4584 $CPAN::Frontend->myprint(" $p\n");
6d29edf5
JH
4585 }
4586 my $follow = 0;
4587 if ($CPAN::Config->{prerequisites_policy} eq "follow") {
f610777f 4588 $follow = 1;
6d29edf5 4589 } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") {
f610777f
A
4590 require ExtUtils::MakeMaker;
4591 my $answer = ExtUtils::MakeMaker::prompt(
4592"Shall I follow them and prepend them to the queue
4593of modules we are processing right now?", "yes");
4594 $follow = $answer =~ /^\s*y/i;
6d29edf5 4595 } else {
f14b5cec 4596 local($") = ", ";
de34a54b
JH
4597 $CPAN::Frontend->
4598 myprint(" Ignoring dependencies on modules @prereq\n");
f610777f 4599 }
6d29edf5
JH
4600 if ($follow) {
4601 # color them as dirty
4602 for my $p (@prereq) {
35576f8c 4603 # warn "calling color_cmd_tmps(0,1)";
6d29edf5
JH
4604 CPAN::Shell->expandany($p)->color_cmd_tmps(0,1);
4605 }
4606 CPAN::Queue->jumpqueue(@prereq,$id); # queue them and requeue yourself
4607 $self->{later} = "Delayed until after prerequisites";
4608 return 1; # signal success to the queuerunner
4609 }
4610}
4611
4612#-> sub CPAN::Distribution::unsat_prereq ;
4613sub unsat_prereq {
4614 my($self) = @_;
4615 my $prereq_pm = $self->prereq_pm or return;
4616 my(@need);
4617 NEED: while (my($need_module, $need_version) = each %$prereq_pm) {
4618 my $nmo = $CPAN::META->instance("CPAN::Module",$need_module);
4619 # we were too demanding:
4620 next if $nmo->uptodate;
4621
4622 # if they have not specified a version, we accept any installed one
4623 if (not defined $need_version or
4624 $need_version == 0 or
4625 $need_version eq "undef") {
4626 next if defined $nmo->inst_file;
4627 }
4628
4629 # We only want to install prereqs if either they're not installed
4630 # or if the installed version is too old. We cannot omit this
4631 # check, because if 'force' is in effect, nobody else will check.
4632 {
4633 local($^W) = 0;
4634 if (
4635 defined $nmo->inst_file &&
4636 ! CPAN::Version->vgt($need_version, $nmo->inst_version)
4637 ){
4638 CPAN->debug(sprintf "id[%s]inst_file[%s]inst_version[%s]need_version[%s]",
4639 $nmo->id,
4640 $nmo->inst_file,
4641 $nmo->inst_version,
4642 CPAN::Version->readable($need_version)
4643 );
4644 next NEED;
4645 }
4646 }
4647
4648 if ($self->{sponsored_mods}{$need_module}++){
4649 # We have already sponsored it and for some reason it's still
4650 # not available. So we do nothing. Or what should we do?
4651 # if we push it again, we have a potential infinite loop
4652 next;
4653 }
4654 push @need, $need_module;
5f05dabc 4655 }
6d29edf5 4656 @need;
5f05dabc 4657}
4658
6d29edf5
JH
4659#-> sub CPAN::Distribution::prereq_pm ;
4660sub prereq_pm {
f610777f 4661 my($self) = @_;
6d29edf5
JH
4662 return $self->{prereq_pm} if
4663 exists $self->{prereq_pm_detected} && $self->{prereq_pm_detected};
4664 return unless $self->{writemakefile}; # no need to have succeeded
4665 # but we must have run it
4666 my $build_dir = $self->{build_dir} or die "Panic: no build_dir?";
4667 my $makefile = File::Spec->catfile($build_dir,"Makefile");
4668 my(%p) = ();
4669 my $fh;
4670 if (-f $makefile
4671 and
4672 $fh = FileHandle->new("<$makefile\0")) {
4673
4674 local($/) = "\n";
4675
4676 # A.Speer @p -> %p, where %p is $p{Module::Name}=Required_Version
4677 while (<$fh>) {
4678 last if /MakeMaker post_initialize section/;
4679 my($p) = m{^[\#]
f610777f
A
4680 \s+PREREQ_PM\s+=>\s+(.+)
4681 }x;
6d29edf5
JH
4682 next unless $p;
4683 # warn "Found prereq expr[$p]";
4684
4685 # Regexp modified by A.Speer to remember actual version of file
4686 # PREREQ_PM hash key wants, then add to
4687 while ( $p =~ m/(?:\s)([\w\:]+)=>q\[(.*?)\],?/g ){
4688 # In case a prereq is mentioned twice, complain.
4689 if ( defined $p{$1} ) {
4690 warn "Warning: PREREQ_PM mentions $1 more than once, last mention wins";
4691 }
4692 $p{$1} = $2;
4693 }
4694 last;
de34a54b 4695 }
f610777f 4696 }
6d29edf5
JH
4697 $self->{prereq_pm_detected}++;
4698 return $self->{prereq_pm} = \%p;
f610777f
A
4699}
4700
05454584
A
4701#-> sub CPAN::Distribution::test ;
4702sub test {
5f05dabc 4703 my($self) = @_;
05454584 4704 $self->make;
c4d24d4c
A
4705 if ($CPAN::Signal){
4706 delete $self->{force_update};
4707 return;
4708 }
c356248b 4709 $CPAN::Frontend->myprint("Running make test\n");
6d29edf5
JH
4710 if (my @prereq = $self->unsat_prereq){
4711 return 1 if $self->follow_prereqs(@prereq); # signal success to the queuerunner
4712 }
05454584
A
4713 EXCUSE: {
4714 my @e;
6d29edf5 4715 exists $self->{make} or exists $self->{later} or push @e,
05454584
A
4716 "Make had some problems, maybe interrupted? Won't test";
4717
4718 exists $self->{'make'} and
4719 $self->{'make'} eq 'NO' and
c4d24d4c 4720 push @e, "Can't test without successful make";
05454584 4721
6d29edf5
JH
4722 exists $self->{build_dir} or push @e, "Has no own directory";
4723 $self->{badtestcnt} ||= 0;
4724 $self->{badtestcnt} > 0 and
4725 push @e, "Won't repeat unsuccessful test during this command";
4726
4727 exists $self->{later} and length($self->{later}) and
4728 push @e, $self->{later};
4729
c356248b 4730 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
05454584 4731 }
c356248b
A
4732 chdir $self->{'build_dir'} or
4733 Carp::croak("Couldn't chdir to $self->{'build_dir'}");
4734 $self->debug("Changed directory to $self->{'build_dir'}")
4735 if $CPAN::DEBUG;
f14b5cec
JH
4736
4737 if ($^O eq 'MacOS') {
be708cc0 4738 Mac::BuildTools::make_test($self);
f14b5cec
JH
4739 return;
4740 }
4741
0362b508 4742 local $ENV{PERL5LIB} = $ENV{PERL5LIB} || "";
4c070e31 4743 $CPAN::META->set_perl5lib;
05454584 4744 my $system = join " ", $CPAN::Config->{'make'}, "test";
e50380aa 4745 if (system($system) == 0) {
c356248b 4746 $CPAN::Frontend->myprint(" $system -- OK\n");
4c070e31 4747 $CPAN::META->is_tested($self->{'build_dir'});
6d29edf5 4748 $self->{make_test} = "YES";
05454584 4749 } else {
6d29edf5
JH
4750 $self->{make_test} = "NO";
4751 $self->{badtestcnt}++;
c356248b 4752 $CPAN::Frontend->myprint(" $system -- NOT OK\n");
5f05dabc 4753 }
4754}
4755
05454584
A
4756#-> sub CPAN::Distribution::clean ;
4757sub clean {
5f05dabc 4758 my($self) = @_;
c356248b 4759 $CPAN::Frontend->myprint("Running make clean\n");
05454584
A
4760 EXCUSE: {
4761 my @e;
c4d24d4c
A
4762 exists $self->{make_clean} and $self->{make_clean} eq "YES" and
4763 push @e, "make clean already called once";
4764 exists $self->{build_dir} or push @e, "Has no own directory";
c356248b 4765 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
05454584 4766 }
c356248b
A
4767 chdir $self->{'build_dir'} or
4768 Carp::croak("Couldn't chdir to $self->{'build_dir'}");
05454584 4769 $self->debug("Changed directory to $self->{'build_dir'}") if $CPAN::DEBUG;
f14b5cec
JH
4770
4771 if ($^O eq 'MacOS') {
be708cc0 4772 Mac::BuildTools::make_clean($self);
f14b5cec
JH
4773 return;
4774 }
4775
05454584 4776 my $system = join " ", $CPAN::Config->{'make'}, "clean";
e50380aa 4777 if (system($system) == 0) {
c4d24d4c
A
4778 $CPAN::Frontend->myprint(" $system -- OK\n");
4779
4780 # $self->force;
4781
4782 # Jost Krieger pointed out that this "force" was wrong because
4783 # it has the effect that the next "install" on this distribution
4784 # will untar everything again. Instead we should bring the
4785 # object's state back to where it is after untarring.
4786
4787 delete $self->{force_update};
4788 delete $self->{install};
4789 delete $self->{writemakefile};
4790 delete $self->{make};
4791 delete $self->{make_test}; # no matter if yes or no, tests must be redone
4792 $self->{make_clean} = "YES";
4793
05454584 4794 } else {
c4d24d4c
A
4795 # Hmmm, what to do if make clean failed?
4796
4797 $CPAN::Frontend->myprint(qq{ $system -- NOT OK
4798
4799make clean did not succeed, marking directory as unusable for further work.
4800});
4801 $self->force("make"); # so that this directory won't be used again
4802
5f05dabc 4803 }
4804}
4805
05454584
A
4806#-> sub CPAN::Distribution::install ;
4807sub install {
5f05dabc 4808 my($self) = @_;
05454584 4809 $self->test;
c4d24d4c
A
4810 if ($CPAN::Signal){
4811 delete $self->{force_update};
4812 return;
4813 }
c356248b 4814 $CPAN::Frontend->myprint("Running make install\n");
05454584
A
4815 EXCUSE: {
4816 my @e;
6d29edf5 4817 exists $self->{build_dir} or push @e, "Has no own directory";
5f05dabc 4818
6d29edf5 4819 exists $self->{make} or exists $self->{later} or push @e,
05454584 4820 "Make had some problems, maybe interrupted? Won't install";
5f05dabc 4821
05454584
A
4822 exists $self->{'make'} and
4823 $self->{'make'} eq 'NO' and
6d29edf5 4824 push @e, "make had returned bad status, install seems impossible";
05454584 4825
c356248b
A
4826 push @e, "make test had returned bad status, ".
4827 "won't install without force"
d4fd5c69
A
4828 if exists $self->{'make_test'} and
4829 $self->{'make_test'} eq 'NO' and
4830 ! $self->{'force_update'};
4831
05454584
A
4832 exists $self->{'install'} and push @e,
4833 $self->{'install'} eq "YES" ?
4834 "Already done" : "Already tried without success";
4835
6d29edf5
JH
4836 exists $self->{later} and length($self->{later}) and
4837 push @e, $self->{later};
4838
c356248b 4839 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
05454584 4840 }
c356248b
A
4841 chdir $self->{'build_dir'} or
4842 Carp::croak("Couldn't chdir to $self->{'build_dir'}");
4843 $self->debug("Changed directory to $self->{'build_dir'}")
4844 if $CPAN::DEBUG;
f14b5cec
JH
4845
4846 if ($^O eq 'MacOS') {
be708cc0 4847 Mac::BuildTools::make_install($self);
f14b5cec
JH
4848 return;
4849 }
4850
c356248b
A
4851 my $system = join(" ", $CPAN::Config->{'make'},
4852 "install", $CPAN::Config->{make_install_arg});
f610777f
A
4853 my($stderr) = $^O =~ /Win/i ? "" : " 2>&1 ";
4854 my($pipe) = FileHandle->new("$system $stderr |");
05454584
A
4855 my($makeout) = "";
4856 while (<$pipe>){
c356248b 4857 $CPAN::Frontend->myprint($_);
05454584
A
4858 $makeout .= $_;
4859 }
4860 $pipe->close;
4861 if ($?==0) {
c356248b 4862 $CPAN::Frontend->myprint(" $system -- OK\n");
4c070e31 4863 $CPAN::META->is_installed($self->{'build_dir'});
f610777f 4864 return $self->{'install'} = "YES";
5f05dabc 4865 } else {
05454584 4866 $self->{'install'} = "NO";
c356248b 4867 $CPAN::Frontend->myprint(" $system -- NOT OK\n");
05454584 4868 if ($makeout =~ /permission/s && $> > 0) {
c356248b
A
4869 $CPAN::Frontend->myprint(qq{ You may have to su }.
4870 qq{to root to install the package\n});
05454584 4871 }
5f05dabc 4872 }
c4d24d4c 4873 delete $self->{force_update};
5f05dabc 4874}
4875
05454584
A
4876#-> sub CPAN::Distribution::dir ;
4877sub dir {
4878 shift->{'build_dir'};
5f05dabc 4879}
4880
05454584 4881package CPAN::Bundle;
5f05dabc 4882
e662ec5f
A
4883sub look {
4884 my $self = shift;
35576f8c 4885 $CPAN::Frontend->myprint($self->as_string);
e662ec5f
A
4886}
4887
6d29edf5
JH
4888sub undelay {
4889 my $self = shift;
4890 delete $self->{later};
4891 for my $c ( $self->contains ) {
4892 my $obj = CPAN::Shell->expandany($c) or next;
4893 $obj->undelay;
4894 }
4895}
4896
4897#-> sub CPAN::Bundle::color_cmd_tmps ;
4898sub color_cmd_tmps {
4899 my($self) = shift;
4900 my($depth) = shift || 0;
4901 my($color) = shift || 0;
35576f8c 4902 my($ancestors) = shift || [];
6d29edf5
JH
4903 # a module needs to recurse to its cpan_file, a distribution needs
4904 # to recurse into its prereq_pms, a bundle needs to recurse into its modules
4905
4906 return if exists $self->{incommandcolor}
4907 && $self->{incommandcolor}==$color;
35576f8c
A
4908 if ($depth>=100){
4909 $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors));
4910 }
4911 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
6d29edf5
JH
4912
4913 for my $c ( $self->contains ) {
4914 my $obj = CPAN::Shell->expandany($c) or next;
4915 CPAN->debug("c[$c]obj[$obj]") if $CPAN::DEBUG;
35576f8c 4916 $obj->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
6d29edf5
JH
4917 }
4918 if ($color==0) {
4919 delete $self->{badtestcnt};
4920 }
4921 $self->{incommandcolor} = $color;
4922}
4923
05454584
A
4924#-> sub CPAN::Bundle::as_string ;
4925sub as_string {
4926 my($self) = @_;
4927 $self->contains;
5e05dca5 4928 # following line must be "=", not "||=" because we have a moving target
6d29edf5 4929 $self->{INST_VERSION} = $self->inst_version;
05454584
A
4930 return $self->SUPER::as_string;
4931}
4932
4933#-> sub CPAN::Bundle::contains ;
4934sub contains {
c049f953
JH
4935 my($self) = @_;
4936 my($inst_file) = $self->inst_file || "";
4937 my($id) = $self->id;
4938 $self->debug("inst_file[$inst_file]id[$id]") if $CPAN::DEBUG;
4939 unless ($inst_file) {
4940 # Try to get at it in the cpan directory
4941 $self->debug("no inst_file") if $CPAN::DEBUG;
4942 my $cpan_file;
4943 $CPAN::Frontend->mydie("I don't know a bundle with ID $id\n") unless
4944 $cpan_file = $self->cpan_file;
4945 if ($cpan_file eq "N/A") {
4946 $CPAN::Frontend->mydie("Bundle $id not found on disk and not on CPAN.
4947 Maybe stale symlink? Maybe removed during session? Giving up.\n");
4948 }
4949 my $dist = $CPAN::META->instance('CPAN::Distribution',
4950 $self->cpan_file);
4951 $dist->get;
4952 $self->debug($dist->as_string) if $CPAN::DEBUG;
4953 my($todir) = $CPAN::Config->{'cpan_home'};
4954 my(@me,$from,$to,$me);
4955 @me = split /::/, $self->id;
4956 $me[-1] .= ".pm";
5de3f0da 4957 $me = File::Spec->catfile(@me);
c049f953 4958 $from = $self->find_bundle_file($dist->{'build_dir'},$me);
5de3f0da 4959 $to = File::Spec->catfile($todir,$me);
c049f953
JH
4960 File::Path::mkpath(File::Basename::dirname($to));
4961 File::Copy::copy($from, $to)
4962 or Carp::confess("Couldn't copy $from to $to: $!");
4963 $inst_file = $to;
4964 }
4965 my @result;
4966 my $fh = FileHandle->new;
4967 local $/ = "\n";
4968 open($fh,$inst_file) or die "Could not open '$inst_file': $!";
4969 my $in_cont = 0;
4970 $self->debug("inst_file[$inst_file]") if $CPAN::DEBUG;
4971 while (<$fh>) {
4972 $in_cont = m/^=(?!head1\s+CONTENTS)/ ? 0 :
4973 m/^=head1\s+CONTENTS/ ? 1 : $in_cont;
4974 next unless $in_cont;
4975 next if /^=/;
4976 s/\#.*//;
4977 next if /^\s+$/;
4978 chomp;
4979 push @result, (split " ", $_, 2)[0];
4980 }
4981 close $fh;
4982 delete $self->{STATUS};
4983 $self->{CONTAINS} = \@result;
4984 $self->debug("CONTAINS[@result]") if $CPAN::DEBUG;
4985 unless (@result) {
4986 $CPAN::Frontend->mywarn(qq{
4987The bundle file "$inst_file" may be a broken
2e2b7522
GS
4988bundlefile. It seems not to contain any bundle definition.
4989Please check the file and if it is bogus, please delete it.
4990Sorry for the inconvenience.
4991});
c049f953
JH
4992 }
4993 @result;
5f05dabc 4994}
4995
e50380aa
A
4996#-> sub CPAN::Bundle::find_bundle_file
4997sub find_bundle_file {
4998 my($self,$where,$what) = @_;
c356248b 4999 $self->debug("where[$where]what[$what]") if $CPAN::DEBUG;
2e2b7522 5000### The following two lines let CPAN.pm become Bundle/CPAN.pm :-(
5de3f0da 5001### my $bu = File::Spec->catfile($where,$what);
2e2b7522 5002### return $bu if -f $bu;
5de3f0da 5003 my $manifest = File::Spec->catfile($where,"MANIFEST");
e50380aa
A
5004 unless (-f $manifest) {
5005 require ExtUtils::Manifest;
9d61fa1d 5006 my $cwd = CPAN::anycwd();
05d2a450 5007 chdir $where or $CPAN::Frontend->mydie(qq{Could not chdir to "$where": $!});
e50380aa 5008 ExtUtils::Manifest::mkmanifest();
05d2a450 5009 chdir $cwd or $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd": $!});
e50380aa 5010 }
c356248b
A
5011 my $fh = FileHandle->new($manifest)
5012 or Carp::croak("Couldn't open $manifest: $!");
e50380aa 5013 local($/) = "\n";
f610777f 5014 my $what2 = $what;
f14b5cec
JH
5015 if ($^O eq 'MacOS') {
5016 $what =~ s/^://;
be708cc0 5017 $what =~ tr|:|/|;
f14b5cec
JH
5018 $what2 =~ s/:Bundle://;
5019 $what2 =~ tr|:|/|;
5020 } else {
911a92db 5021 $what2 =~ s|Bundle[/\\]||;
f14b5cec 5022 }
f610777f 5023 my $bu;
e50380aa
A
5024 while (<$fh>) {
5025 next if /^\s*\#/;
5026 my($file) = /(\S+)/;
c356248b 5027 if ($file =~ m|\Q$what\E$|) {
e50380aa 5028 $bu = $file;
5de3f0da 5029 # return File::Spec->catfile($where,$bu); # bad
f610777f 5030 last;
e50380aa 5031 }
f610777f
A
5032 # retry if she managed to
5033 # have no Bundle directory
5034 $bu = $file if $file =~ m|\Q$what2\E$|;
e50380aa 5035 }
f14b5cec 5036 $bu =~ tr|/|:| if $^O eq 'MacOS';
5de3f0da 5037 return File::Spec->catfile($where, $bu) if $bu;
c356248b 5038 Carp::croak("Couldn't find a Bundle file in $where");
e50380aa
A
5039}
5040
d8773709
JH
5041# needs to work quite differently from Module::inst_file because of
5042# cpan_home/Bundle/ directory and the possibility that we have
5043# shadowing effect. As it makes no sense to take the first in @INC for
5044# Bundles, we parse them all for $VERSION and take the newest.
6d29edf5 5045
05454584
A
5046#-> sub CPAN::Bundle::inst_file ;
5047sub inst_file {
5048 my($self) = @_;
6d29edf5
JH
5049 my($inst_file);
5050 my(@me);
5051 @me = split /::/, $self->id;
5052 $me[-1] .= ".pm";
d8773709
JH
5053 my($incdir,$bestv);
5054 foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) {
5de3f0da 5055 my $bfile = File::Spec->catfile($incdir, @me);
d8773709
JH
5056 CPAN->debug("bfile[$bfile]") if $CPAN::DEBUG;
5057 next unless -f $bfile;
5058 my $foundv = MM->parse_version($bfile);
5059 if (!$bestv || CPAN::Version->vgt($foundv,$bestv)) {
5060 $self->{INST_FILE} = $bfile;
5061 $self->{INST_VERSION} = $bestv = $foundv;
5062 }
5063 }
5064 $self->{INST_FILE};
5065}
5066
5067#-> sub CPAN::Bundle::inst_version ;
5068sub inst_version {
5069 my($self) = @_;
5070 $self->inst_file; # finds INST_VERSION as side effect
5071 $self->{INST_VERSION};
5f05dabc 5072}
5073
05454584
A
5074#-> sub CPAN::Bundle::rematein ;
5075sub rematein {
5076 my($self,$meth) = @_;
5077 $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG;
c356248b
A
5078 my($id) = $self->id;
5079 Carp::croak "Can't $meth $id, don't have an associated bundle file. :-(\n"
6d29edf5 5080 unless $self->inst_file || $self->cpan_file;
f610777f 5081 my($s,%fail);
05454584
A
5082 for $s ($self->contains) {
5083 my($type) = $s =~ m|/| ? 'CPAN::Distribution' :
5084 $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module';
5085 if ($type eq 'CPAN::Distribution') {
c356248b 5086 $CPAN::Frontend->mywarn(qq{
05454584
A
5087The Bundle }.$self->id.qq{ contains
5088explicitly a file $s.
c356248b 5089});
05454584 5090 sleep 3;
5f05dabc 5091 }
f610777f 5092 # possibly noisy action:
de34a54b 5093 $self->debug("type[$type] s[$s]") if $CPAN::DEBUG;
f610777f
A
5094 my $obj = $CPAN::META->instance($type,$s);
5095 $obj->$meth();
de34a54b
JH
5096 if ($obj->isa(CPAN::Bundle)
5097 &&
5098 exists $obj->{install_failed}
5099 &&
5100 ref($obj->{install_failed}) eq "HASH"
5101 ) {
5102 for (keys %{$obj->{install_failed}}) {
5103 $self->{install_failed}{$_} = undef; # propagate faiure up
5104 # to me in a
5105 # recursive call
5106 $fail{$s} = 1; # the bundle itself may have succeeded but
5107 # not all children
5108 }
5109 } else {
5110 my $success;
5111 $success = $obj->can("uptodate") ? $obj->uptodate : 0;
5112 $success ||= $obj->{'install'} && $obj->{'install'} eq "YES";
5113 if ($success) {
5114 delete $self->{install_failed}{$s};
5115 } else {
5116 $fail{$s} = 1;
5117 }
5118 }
f610777f 5119 }
de34a54b 5120
f610777f 5121 # recap with less noise
de34a54b 5122 if ( $meth eq "install" ) {
f610777f 5123 if (%fail) {
911a92db
GS
5124 require Text::Wrap;
5125 my $raw = sprintf(qq{Bundle summary:
5126The following items in bundle %s had installation problems:},
5127 $self->id
5128 );
5129 $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw));
5130 $CPAN::Frontend->myprint("\n");
5131 my $paragraph = "";
de34a54b 5132 my %reported;
f610777f 5133 for $s ($self->contains) {
de34a54b
JH
5134 if ($fail{$s}){
5135 $paragraph .= "$s ";
5136 $self->{install_failed}{$s} = undef;
5137 $reported{$s} = undef;
5138 }
f610777f 5139 }
de34a54b
JH
5140 my $report_propagated;
5141 for $s (sort keys %{$self->{install_failed}}) {
5142 next if exists $reported{$s};
5143 $paragraph .= "and the following items had problems
5144during recursive bundle calls: " unless $report_propagated++;
5145 $paragraph .= "$s ";
5146 }
911a92db
GS
5147 $CPAN::Frontend->myprint(Text::Wrap::fill(" "," ",$paragraph));
5148 $CPAN::Frontend->myprint("\n");
f610777f
A
5149 } else {
5150 $self->{'install'} = 'YES';
5151 }
5f05dabc 5152 }
5f05dabc 5153}
5154
e50380aa
A
5155#sub CPAN::Bundle::xs_file
5156sub xs_file {
5157 # If a bundle contains another that contains an xs_file we have
5158 # here, we just don't bother I suppose
5159 return 0;
5160}
5161
05454584
A
5162#-> sub CPAN::Bundle::force ;
5163sub force { shift->rematein('force',@_); }
5164#-> sub CPAN::Bundle::get ;
5165sub get { shift->rematein('get',@_); }
5166#-> sub CPAN::Bundle::make ;
5167sub make { shift->rematein('make',@_); }
5168#-> sub CPAN::Bundle::test ;
6d29edf5
JH
5169sub test {
5170 my $self = shift;
5171 $self->{badtestcnt} ||= 0;
5172 $self->rematein('test',@_);
5173}
05454584 5174#-> sub CPAN::Bundle::install ;
09d9d230
A
5175sub install {
5176 my $self = shift;
5177 $self->rematein('install',@_);
09d9d230 5178}
05454584
A
5179#-> sub CPAN::Bundle::clean ;
5180sub clean { shift->rematein('clean',@_); }
5f05dabc 5181
d8773709
JH
5182#-> sub CPAN::Bundle::uptodate ;
5183sub uptodate {
5184 my($self) = @_;
5185 return 0 unless $self->SUPER::uptodate; # we mut have the current Bundle def
5186 my $c;
5187 foreach $c ($self->contains) {
5188 my $obj = CPAN::Shell->expandany($c);
5189 return 0 unless $obj->uptodate;
5190 }
5191 return 1;
5192}
5193
05454584
A
5194#-> sub CPAN::Bundle::readme ;
5195sub readme {
5196 my($self) = @_;
c356248b
A
5197 my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{
5198No File found for bundle } . $self->id . qq{\n}), return;
05454584
A
5199 $self->debug("self[$self] file[$file]") if $CPAN::DEBUG;
5200 $CPAN::META->instance('CPAN::Distribution',$file)->readme;
5f05dabc 5201}
5202
05454584 5203package CPAN::Module;
5f05dabc 5204
6d29edf5 5205# Accessors
35576f8c 5206# sub CPAN::Module::userid
6d29edf5
JH
5207sub userid {
5208 my $self = shift;
8d97e4a1 5209 return unless exists $self->{RO}; # should never happen
35576f8c 5210 return $self->{RO}{userid} || $self->{RO}{CPAN_USERID};
6d29edf5 5211}
35576f8c 5212# sub CPAN::Module::description
6d29edf5
JH
5213sub description { shift->{RO}{description} }
5214
5215sub undelay {
5216 my $self = shift;
5217 delete $self->{later};
5218 if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) {
5219 $dist->undelay;
5220 }
5221}
5222
5223#-> sub CPAN::Module::color_cmd_tmps ;
5224sub color_cmd_tmps {
5225 my($self) = shift;
5226 my($depth) = shift || 0;
5227 my($color) = shift || 0;
35576f8c 5228 my($ancestors) = shift || [];
6d29edf5
JH
5229 # a module needs to recurse to its cpan_file
5230
5231 return if exists $self->{incommandcolor}
5232 && $self->{incommandcolor}==$color;
35576f8c
A
5233 if ($depth>=100){
5234 $CPAN::Frontend->mydie(CPAN::Exception::RecursiveDependency->new($ancestors));
5235 }
5236 # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
6d29edf5
JH
5237
5238 if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) {
35576f8c 5239 $dist->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
6d29edf5
JH
5240 }
5241 if ($color==0) {
5242 delete $self->{badtestcnt};
5243 }
5244 $self->{incommandcolor} = $color;
5245}
5246
05454584
A
5247#-> sub CPAN::Module::as_glimpse ;
5248sub as_glimpse {
5249 my($self) = @_;
5250 my(@m);
5251 my $class = ref($self);
5252 $class =~ s/^CPAN:://;
9d61fa1d
A
5253 my $color_on = "";
5254 my $color_off = "";
5255 if (
5256 $CPAN::Shell::COLOR_REGISTERED
5257 &&
5258 $CPAN::META->has_inst("Term::ANSIColor")
5259 &&
5260 $self->{RO}{description}
5261 ) {
5262 $color_on = Term::ANSIColor::color("green");
5263 $color_off = Term::ANSIColor::color("reset");
5264 }
5265 push @m, sprintf("%-15s %s%-15s%s (%s)\n",
5266 $class,
5267 $color_on,
5268 $self->id,
5269 $color_off,
c356248b 5270 $self->cpan_file);
05454584
A
5271 join "", @m;
5272}
5f05dabc 5273
05454584
A
5274#-> sub CPAN::Module::as_string ;
5275sub as_string {
5276 my($self) = @_;
5277 my(@m);
35576f8c 5278 CPAN->debug("$self entering as_string") if $CPAN::DEBUG;
05454584
A
5279 my $class = ref($self);
5280 $class =~ s/^CPAN:://;
5281 local($^W) = 0;
5282 push @m, $class, " id = $self->{ID}\n";
5283 my $sprintf = " %-12s %s\n";
6d29edf5
JH
5284 push @m, sprintf($sprintf, 'DESCRIPTION', $self->description)
5285 if $self->description;
05454584
A
5286 my $sprintf2 = " %-12s %s (%s)\n";
5287 my($userid);
35576f8c
A
5288 $userid = $self->userid;
5289 if ( $userid ){
c356248b
A
5290 my $author;
5291 if ($author = CPAN::Shell->expand('Author',$userid)) {
09d9d230
A
5292 my $email = "";
5293 my $m; # old perls
5294 if ($m = $author->email) {
5295 $email = " <$m>";
5296 }
5297 push @m, sprintf(
5298 $sprintf2,
5299 'CPAN_USERID',
5300 $userid,
5301 $author->fullname . $email
5302 );
c356248b
A
5303 }
5304 }
6d29edf5
JH
5305 push @m, sprintf($sprintf, 'CPAN_VERSION', $self->cpan_version)
5306 if $self->cpan_version;
5307 push @m, sprintf($sprintf, 'CPAN_FILE', $self->cpan_file)
5308 if $self->cpan_file;
05454584
A
5309 my $sprintf3 = " %-12s %1s%1s%1s%1s (%s,%s,%s,%s)\n";
5310 my(%statd,%stats,%statl,%stati);
c356248b
A
5311 @statd{qw,? i c a b R M S,} = qw,unknown idea
5312 pre-alpha alpha beta released mature standard,;
35576f8c
A
5313 @stats{qw,? m d u n a,} = qw,unknown mailing-list
5314 developer comp.lang.perl.* none abandoned,;
2e2b7522
GS
5315 @statl{qw,? p c + o h,} = qw,unknown perl C C++ other hybrid,;
5316 @stati{qw,? f r O h,} = qw,unknown functions
5317 references+ties object-oriented hybrid,;
05454584
A
5318 $statd{' '} = 'unknown';
5319 $stats{' '} = 'unknown';
5320 $statl{' '} = 'unknown';
5321 $stati{' '} = 'unknown';
5322 push @m, sprintf(
5323 $sprintf3,
5324 'DSLI_STATUS',
6d29edf5
JH
5325 $self->{RO}{statd},
5326 $self->{RO}{stats},
5327 $self->{RO}{statl},
5328 $self->{RO}{stati},
5329 $statd{$self->{RO}{statd}},
5330 $stats{$self->{RO}{stats}},
5331 $statl{$self->{RO}{statl}},
5332 $stati{$self->{RO}{stati}}
5333 ) if $self->{RO}{statd};
05454584 5334 my $local_file = $self->inst_file;
9d61fa1d
A
5335 unless ($self->{MANPAGE}) {
5336 if ($local_file) {
5337 $self->{MANPAGE} = $self->manpage_headline($local_file);
5338 } else {
5339 # If we have already untarred it, we should look there
5340 my $dist = $CPAN::META->instance('CPAN::Distribution',
5341 $self->cpan_file);
5342 # warn "dist[$dist]";
5343 # mff=manifest file; mfh=manifest handle
5344 my($mff,$mfh);
c049f953
JH
5345 if (
5346 $dist->{build_dir}
5347 and
5de3f0da 5348 (-f ($mff = File::Spec->catfile($dist->{build_dir}, "MANIFEST")))
c049f953 5349 and
9d61fa1d
A
5350 $mfh = FileHandle->new($mff)
5351 ) {
8d97e4a1 5352 CPAN->debug("mff[$mff]") if $CPAN::DEBUG;
9d61fa1d
A
5353 my $lfre = $self->id; # local file RE
5354 $lfre =~ s/::/./g;
5355 $lfre .= "\\.pm\$";
5356 my($lfl); # local file file
5357 local $/ = "\n";
5358 my(@mflines) = <$mfh>;
8d97e4a1
JH
5359 for (@mflines) {
5360 s/^\s+//;
5361 s/\s.*//s;
5362 }
9d61fa1d
A
5363 while (length($lfre)>5 and !$lfl) {
5364 ($lfl) = grep /$lfre/, @mflines;
8d97e4a1 5365 CPAN->debug("lfl[$lfl]lfre[$lfre]") if $CPAN::DEBUG;
9d61fa1d 5366 $lfre =~ s/.+?\.//;
9d61fa1d
A
5367 }
5368 $lfl =~ s/\s.*//; # remove comments
5369 $lfl =~ s/\s+//g; # chomp would maybe be too system-specific
5de3f0da 5370 my $lfl_abs = File::Spec->catfile($dist->{build_dir},$lfl);
9d61fa1d
A
5371 # warn "lfl_abs[$lfl_abs]";
5372 if (-f $lfl_abs) {
5373 $self->{MANPAGE} = $self->manpage_headline($lfl_abs);
5374 }
5375 }
5376 }
5f05dabc 5377 }
d4fd5c69 5378 my($item);
6d29edf5 5379 for $item (qw/MANPAGE/) {
c356248b
A
5380 push @m, sprintf($sprintf, $item, $self->{$item})
5381 if exists $self->{$item};
d4fd5c69 5382 }
6d29edf5
JH
5383 for $item (qw/CONTAINS/) {
5384 push @m, sprintf($sprintf, $item, join(" ",@{$self->{$item}}))
5385 if exists $self->{$item} && @{$self->{$item}};
5386 }
c356248b
A
5387 push @m, sprintf($sprintf, 'INST_FILE',
5388 $local_file || "(not installed)");
5389 push @m, sprintf($sprintf, 'INST_VERSION',
6d29edf5 5390 $self->inst_version) if $local_file;
05454584 5391 join "", @m, "\n";
5f05dabc 5392}
5393
09d9d230
A
5394sub manpage_headline {
5395 my($self,$local_file) = @_;
5396 my(@local_file) = $local_file;
05d2a450 5397 $local_file =~ s/\.pm(?!\n)\Z/.pod/;
09d9d230
A
5398 push @local_file, $local_file;
5399 my(@result,$locf);
5400 for $locf (@local_file) {
5401 next unless -f $locf;
5402 my $fh = FileHandle->new($locf)
5403 or $Carp::Frontend->mydie("Couldn't open $locf: $!");
5404 my $inpod = 0;
5405 local $/ = "\n";
5406 while (<$fh>) {
e662ec5f
A
5407 $inpod = m/^=(?!head1\s+NAME\s*$)/ ? 0 :
5408 m/^=head1\s+NAME\s*$/ ? 1 : $inpod;
09d9d230
A
5409 next unless $inpod;
5410 next if /^=/;
5411 next if /^\s+$/;
5412 chomp;
5413 push @result, $_;
5414 }
5415 close $fh;
5416 last if @result;
5417 }
5418 join " ", @result;
5419}
5420
05454584 5421#-> sub CPAN::Module::cpan_file ;
c049f953
JH
5422# Note: also inherited by CPAN::Bundle
5423sub cpan_file {
05454584 5424 my $self = shift;
6d29edf5
JH
5425 CPAN->debug(sprintf "id[%s]", $self->id) if $CPAN::DEBUG;
5426 unless (defined $self->{RO}{CPAN_FILE}) {
05454584
A
5427 CPAN::Index->reload;
5428 }
6d29edf5
JH
5429 if (exists $self->{RO}{CPAN_FILE} && defined $self->{RO}{CPAN_FILE}){
5430 return $self->{RO}{CPAN_FILE};
10b2abe6 5431 } else {
8d97e4a1
JH
5432 my $userid = $self->userid;
5433 if ( $userid ) {
5434 if ($CPAN::META->exists("CPAN::Author",$userid)) {
5435 my $author = $CPAN::META->instance("CPAN::Author",
5436 $userid);
5437 my $fullname = $author->fullname;
5438 my $email = $author->email;
5439 unless (defined $fullname && defined $email) {
5440 return sprintf("Contact Author %s",
5441 $userid,
5442 );
5443 }
5444 return "Contact Author $fullname <$email>";
5445 } else {
1426a145 5446 return "Contact Author $userid (Email address not available)";
8d97e4a1
JH
5447 }
5448 } else {
5449 return "N/A";
5450 }
5f05dabc 5451 }
5452}
5453
05454584 5454#-> sub CPAN::Module::cpan_version ;
c356248b
A
5455sub cpan_version {
5456 my $self = shift;
6d29edf5
JH
5457
5458 $self->{RO}{CPAN_VERSION} = 'undef'
5459 unless defined $self->{RO}{CPAN_VERSION};
5460 # I believe this is always a bug in the index and should be reported
5461 # as such, but usually I find out such an error and do not want to
5462 # provoke too many bugreports
5463
5464 $self->{RO}{CPAN_VERSION};
c356248b 5465}
5f05dabc 5466
05454584
A
5467#-> sub CPAN::Module::force ;
5468sub force {
5469 my($self) = @_;
5470 $self->{'force_update'}++;
5f05dabc 5471}
5472
05454584
A
5473#-> sub CPAN::Module::rematein ;
5474sub rematein {
5475 my($self,$meth) = @_;
6d29edf5
JH
5476 $CPAN::Frontend->myprint(sprintf("Running %s for module %s\n",
5477 $meth,
5478 $self->id));
05454584 5479 my $cpan_file = $self->cpan_file;
09d9d230
A
5480 if ($cpan_file eq "N/A" || $cpan_file =~ /^Contact Author/){
5481 $CPAN::Frontend->mywarn(sprintf qq{
5482 The module %s isn\'t available on CPAN.
5483
5484 Either the module has not yet been uploaded to CPAN, or it is
5485 temporary unavailable. Please contact the author to find out
c4d24d4c 5486 more about the status. Try 'i %s'.
09d9d230
A
5487},
5488 $self->id,
5489 $self->id,
5490 );
5491 return;
5492 }
05454584
A
5493 my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
5494 $pack->called_for($self->id);
c4d24d4c 5495 $pack->force($meth) if exists $self->{'force_update'};
05454584 5496 $pack->$meth();
c4d24d4c 5497 $pack->unforce if $pack->can("unforce") && exists $self->{'force_update'};
05454584 5498 delete $self->{'force_update'};
5f05dabc 5499}
5500
05454584
A
5501#-> sub CPAN::Module::readme ;
5502sub readme { shift->rematein('readme') }
5503#-> sub CPAN::Module::look ;
5504sub look { shift->rematein('look') }
911a92db
GS
5505#-> sub CPAN::Module::cvs_import ;
5506sub cvs_import { shift->rematein('cvs_import') }
05454584
A
5507#-> sub CPAN::Module::get ;
5508sub get { shift->rematein('get',@_); }
5509#-> sub CPAN::Module::make ;
6d29edf5
JH
5510sub make {
5511 my $self = shift;
5512 $self->rematein('make');
5513}
05454584 5514#-> sub CPAN::Module::test ;
6d29edf5
JH
5515sub test {
5516 my $self = shift;
5517 $self->{badtestcnt} ||= 0;
5518 $self->rematein('test',@_);
5519}
f610777f
A
5520#-> sub CPAN::Module::uptodate ;
5521sub uptodate {
5f05dabc 5522 my($self) = @_;
6d29edf5 5523 my($latest) = $self->cpan_version;
05454584
A
5524 $latest ||= 0;
5525 my($inst_file) = $self->inst_file;
5526 my($have) = 0;
5527 if (defined $inst_file) {
6d29edf5 5528 $have = $self->inst_version;
05454584 5529 }
f14b5cec
JH
5530 local($^W)=0;
5531 if ($inst_file
5532 &&
5e05dca5 5533 ! CPAN::Version->vgt($latest, $have)
f14b5cec 5534 ) {
6d29edf5
JH
5535 CPAN->debug("returning uptodate. inst_file[$inst_file] ".
5536 "latest[$latest] have[$have]") if $CPAN::DEBUG;
5537 return 1;
5f05dabc 5538 }
f610777f
A
5539 return;
5540}
5541#-> sub CPAN::Module::install ;
5542sub install {
5543 my($self) = @_;
5544 my($doit) = 0;
5545 if ($self->uptodate
5546 &&
5547 not exists $self->{'force_update'}
5548 ) {
5549 $CPAN::Frontend->myprint( $self->id. " is up to date.\n");
5550 } else {
5551 $doit = 1;
5552 }
35576f8c
A
5553 if ($self->{RO}{stats} && $self->{RO}{stats} eq "a") {
5554 $CPAN::Frontend->mywarn(qq{
5555\n\n\n ***WARNING***
5556 The module $self->{ID} has no active maintainer.\n\n\n
5557});
5558 sleep 5;
5559 }
05454584 5560 $self->rematein('install') if $doit;
5f05dabc 5561}
05454584
A
5562#-> sub CPAN::Module::clean ;
5563sub clean { shift->rematein('clean') }
5f05dabc 5564
05454584
A
5565#-> sub CPAN::Module::inst_file ;
5566sub inst_file {
5567 my($self) = @_;
5568 my($dir,@packpath);
5569 @packpath = split /::/, $self->{ID};
5570 $packpath[-1] .= ".pm";
5571 foreach $dir (@INC) {
5de3f0da 5572 my $pmfile = File::Spec->catfile($dir,@packpath);
05454584
A
5573 if (-f $pmfile){
5574 return $pmfile;
da199366 5575 }
5f05dabc 5576 }
d4fd5c69 5577 return;
5f05dabc 5578}
5579
05454584
A
5580#-> sub CPAN::Module::xs_file ;
5581sub xs_file {
5582 my($self) = @_;
5583 my($dir,@packpath);
5584 @packpath = split /::/, $self->{ID};
5585 push @packpath, $packpath[-1];
5586 $packpath[-1] .= "." . $Config::Config{'dlext'};
5587 foreach $dir (@INC) {
5de3f0da 5588 my $xsfile = File::Spec->catfile($dir,'auto',@packpath);
05454584
A
5589 if (-f $xsfile){
5590 return $xsfile;
5591 }
5592 }
d4fd5c69 5593 return;
5f05dabc 5594}
5595
05454584
A
5596#-> sub CPAN::Module::inst_version ;
5597sub inst_version {
5598 my($self) = @_;
c356248b 5599 my $parsefile = $self->inst_file or return;
05454584 5600 local($^W) = 0 if $] < 5.00303 && $ExtUtils::MakeMaker::VERSION < 5.38;
de34a54b 5601 my $have;
de34a54b
JH
5602
5603 # there was a bug in 5.6.0 that let lots of unini warnings out of
5604 # parse_version. Fixed shortly after 5.6.0 by PMQS. We can remove
c4d24d4c 5605 # the following workaround after 5.6.1 is out.
de34a54b
JH
5606 local($SIG{__WARN__}) = sub { my $w = shift;
5607 return if $w =~ /uninitialized/i;
5608 warn $w;
5609 };
c4d24d4c 5610
de34a54b 5611 $have = MM->parse_version($parsefile) || "undef";
05d2a450
A
5612 $have =~ s/^ //; # since the %vd hack these two lines here are needed
5613 $have =~ s/ $//; # trailing whitespace happens all the time
5614
c4d24d4c 5615 # My thoughts about why %vd processing should happen here
5e05dca5 5616
c4d24d4c 5617 # Alt1 maintain it as string with leading v:
5e05dca5
A
5618 # read index files do nothing
5619 # compare it use utility for compare
5620 # print it do nothing
5621
d1be9408 5622 # Alt2 maintain it as what it is
5e05dca5
A
5623 # read index files convert
5624 # compare it use utility because there's still a ">" vs "gt" issue
5625 # print it use CPAN::Version for print
5626
5627 # Seems cleaner to hold it in memory as a string starting with a "v"
5628
c4d24d4c
A
5629 # If the author of this module made a mistake and wrote a quoted
5630 # "v1.13" instead of v1.13, we simply leave it at that with the
5631 # effect that *we* will treat it like a v-tring while the rest of
5632 # perl won't. Seems sensible when we consider that any action we
5633 # could take now would just add complexity.
5634
5e05dca5 5635 $have = CPAN::Version->readable($have);
c4d24d4c 5636
911a92db 5637 $have =~ s/\s*//g; # stringify to float around floating point issues
de34a54b 5638 $have; # no stringify needed, \s* above matches always
5f05dabc 5639}
5640
09d9d230
A
5641package CPAN::Tarzip;
5642
de34a54b 5643# CPAN::Tarzip::gzip
09d9d230
A
5644sub gzip {
5645 my($class,$read,$write) = @_;
5646 if ($CPAN::META->has_inst("Compress::Zlib")) {
5647 my($buffer,$fhw);
5648 $fhw = FileHandle->new($read)
5649 or $CPAN::Frontend->mydie("Could not open $read: $!");
5650 my $gz = Compress::Zlib::gzopen($write, "wb")
5651 or $CPAN::Frontend->mydie("Cannot gzopen $write: $!\n");
5652 $gz->gzwrite($buffer)
5653 while read($fhw,$buffer,4096) > 0 ;
5654 $gz->gzclose() ;
5655 $fhw->close;
5656 return 1;
5657 } else {
5a5fac02 5658 system("$CPAN::Config->{gzip} -c $read > $write")==0;
09d9d230
A
5659 }
5660}
5661
de34a54b
JH
5662
5663# CPAN::Tarzip::gunzip
09d9d230
A
5664sub gunzip {
5665 my($class,$read,$write) = @_;
5666 if ($CPAN::META->has_inst("Compress::Zlib")) {
5667 my($buffer,$fhw);
5668 $fhw = FileHandle->new(">$write")
5669 or $CPAN::Frontend->mydie("Could not open >$write: $!");
5670 my $gz = Compress::Zlib::gzopen($read, "rb")
5671 or $CPAN::Frontend->mydie("Cannot gzopen $read: $!\n");
5672 $fhw->print($buffer)
5673 while $gz->gzread($buffer) > 0 ;
5674 $CPAN::Frontend->mydie("Error reading from $read: $!\n")
5675 if $gz->gzerror != Compress::Zlib::Z_STREAM_END();
5676 $gz->gzclose() ;
5677 $fhw->close;
5678 return 1;
5679 } else {
5a5fac02 5680 system("$CPAN::Config->{gzip} -dc $read > $write")==0;
09d9d230
A
5681 }
5682}
5683
de34a54b
JH
5684
5685# CPAN::Tarzip::gtest
09d9d230
A
5686sub gtest {
5687 my($class,$read) = @_;
5a5fac02
JH
5688 # After I had reread the documentation in zlib.h, I discovered that
5689 # uncompressed files do not lead to an gzerror (anymore?).
5690 if ( $CPAN::META->has_inst("Compress::Zlib") ) {
5691 my($buffer,$len);
5692 $len = 0;
09d9d230 5693 my $gz = Compress::Zlib::gzopen($read, "rb")
5a5fac02
JH
5694 or $CPAN::Frontend->mydie(sprintf("Cannot gzopen %s: %s\n",
5695 $read,
5696 $Compress::Zlib::gzerrno));
5697 while ($gz->gzread($buffer) > 0 ){
5698 $len += length($buffer);
5699 $buffer = "";
5700 }
de34a54b
JH
5701 my $err = $gz->gzerror;
5702 my $success = ! $err || $err == Compress::Zlib::Z_STREAM_END();
5a5fac02
JH
5703 if ($len == -s $read){
5704 $success = 0;
5705 CPAN->debug("hit an uncompressed file") if $CPAN::DEBUG;
5706 }
de34a54b 5707 $gz->gzclose();
5a5fac02 5708 CPAN->debug("err[$err]success[$success]") if $CPAN::DEBUG;
de34a54b 5709 return $success;
09d9d230 5710 } else {
5a5fac02 5711 return system("$CPAN::Config->{gzip} -dt $read")==0;
09d9d230
A
5712 }
5713}
5714
de34a54b
JH
5715
5716# CPAN::Tarzip::TIEHANDLE
09d9d230
A
5717sub TIEHANDLE {
5718 my($class,$file) = @_;
5719 my $ret;
5720 $class->debug("file[$file]");
5721 if ($CPAN::META->has_inst("Compress::Zlib")) {
5722 my $gz = Compress::Zlib::gzopen($file,"rb") or
5723 die "Could not gzopen $file";
5724 $ret = bless {GZ => $gz}, $class;
5725 } else {
5a5fac02 5726 my $pipe = "$CPAN::Config->{gzip} --decompress --stdout $file |";
e8427fc1 5727 my $fh = FileHandle->new($pipe) or die "Could not pipe[$pipe]: $!";
09d9d230
A
5728 binmode $fh;
5729 $ret = bless {FH => $fh}, $class;
5730 }
5731 $ret;
5732}
5733
de34a54b
JH
5734
5735# CPAN::Tarzip::READLINE
09d9d230
A
5736sub READLINE {
5737 my($self) = @_;
5738 if (exists $self->{GZ}) {
5739 my $gz = $self->{GZ};
5740 my($line,$bytesread);
5741 $bytesread = $gz->gzreadline($line);
36263cb3 5742 return undef if $bytesread <= 0;
09d9d230
A
5743 return $line;
5744 } else {
5745 my $fh = $self->{FH};
5746 return scalar <$fh>;
5747 }
5748}
5749
de34a54b
JH
5750
5751# CPAN::Tarzip::READ
09d9d230
A
5752sub READ {
5753 my($self,$ref,$length,$offset) = @_;
5754 die "read with offset not implemented" if defined $offset;
5755 if (exists $self->{GZ}) {
5756 my $gz = $self->{GZ};
5757 my $byteread = $gz->gzread($$ref,$length);# 30eaf79e8b446ef52464b5422da328a8
5758 return $byteread;
5759 } else {
5760 my $fh = $self->{FH};
5761 return read($fh,$$ref,$length);
5762 }
5763}
5764
de34a54b
JH
5765
5766# CPAN::Tarzip::DESTROY
09d9d230 5767sub DESTROY {
5a5fac02
JH
5768 my($self) = @_;
5769 if (exists $self->{GZ}) {
5770 my $gz = $self->{GZ};
5771 $gz->gzclose() if defined $gz; # hard to say if it is allowed
5772 # to be undef ever. AK, 2000-09
5773 } else {
5774 my $fh = $self->{FH};
5775 $fh->close if defined $fh;
5776 }
5777 undef $self;
09d9d230
A
5778}
5779
de34a54b
JH
5780
5781# CPAN::Tarzip::untar
09d9d230
A
5782sub untar {
5783 my($class,$file) = @_;
8d97e4a1
JH
5784 my($prefer) = 0;
5785
c4d24d4c 5786 if (0) { # makes changing order easier
8d97e4a1
JH
5787 } elsif ($BUGHUNTING){
5788 $prefer=2;
5a5fac02 5789 } elsif (MM->maybe_command($CPAN::Config->{gzip})
8d97e4a1
JH
5790 &&
5791 MM->maybe_command($CPAN::Config->{'tar'})) {
5792 # should be default until Archive::Tar is fixed
5793 $prefer = 1;
5794 } elsif (
5795 $CPAN::META->has_inst("Archive::Tar")
5796 &&
5797 $CPAN::META->has_inst("Compress::Zlib") ) {
5798 $prefer = 2;
5799 } else {
5800 $CPAN::Frontend->mydie(qq{
5801CPAN.pm needs either both external programs tar and gzip installed or
5802both the modules Archive::Tar and Compress::Zlib. Neither prerequisite
5803is available. Can\'t continue.
5804});
5805 }
5806 if ($prefer==1) { # 1 => external gzip+tar
5a5fac02
JH
5807 my($system);
5808 my $is_compressed = $class->gtest($file);
5809 if ($is_compressed) {
5810 $system = "$CPAN::Config->{gzip} --decompress --stdout " .
5811 "< $file | $CPAN::Config->{tar} xvf -";
5812 } else {
5813 $system = "$CPAN::Config->{tar} xvf $file";
5814 }
911a92db 5815 if (system($system) != 0) {
5a5fac02
JH
5816 # people find the most curious tar binaries that cannot handle
5817 # pipes
5818 if ($is_compressed) {
5819 (my $ungzf = $file) =~ s/\.gz(?!\n)\Z//;
5820 if (CPAN::Tarzip->gunzip($file, $ungzf)) {
5821 $CPAN::Frontend->myprint(qq{Uncompressed $file successfully\n});
5822 } else {
5823 $CPAN::Frontend->mydie(qq{Couldn\'t uncompress $file\n});
5824 }
5825 $file = $ungzf;
5826 }
5827 $system = "$CPAN::Config->{tar} xvf $file";
5828 $CPAN::Frontend->myprint(qq{Using Tar:$system:\n});
5829 if (system($system)==0) {
5830 $CPAN::Frontend->myprint(qq{Untarred $file successfully\n});
5831 } else {
5832 $CPAN::Frontend->mydie(qq{Couldn\'t untar $file\n});
5833 }
5834 return 1;
f610777f 5835 } else {
5a5fac02 5836 return 1;
f610777f 5837 }
8d97e4a1 5838 } elsif ($prefer==2) { # 2 => modules
6d29edf5
JH
5839 my $tar = Archive::Tar->new($file,1);
5840 my $af; # archive file
5a5fac02 5841 my @af;
8d97e4a1
JH
5842 if ($BUGHUNTING) {
5843 # RCS 1.337 had this code, it turned out unacceptable slow but
5844 # it revealed a bug in Archive::Tar. Code is only here to hunt
5845 # the bug again. It should never be enabled in published code.
5846 # GDGraph3d-0.53 was an interesting case according to Larry
5847 # Virden.
5848 warn(">>>Bughunting code enabled<<< " x 20);
5849 for $af ($tar->list_files) {
5850 if ($af =~ m!^(/|\.\./)!) {
5851 $CPAN::Frontend->mydie("ALERT: Archive contains ".
5852 "illegal member [$af]");
5853 }
5854 $CPAN::Frontend->myprint("$af\n");
5855 $tar->extract($af); # slow but effective for finding the bug
5856 return if $CPAN::Signal;
6d29edf5 5857 }
8d97e4a1
JH
5858 } else {
5859 for $af ($tar->list_files) {
5860 if ($af =~ m!^(/|\.\./)!) {
5861 $CPAN::Frontend->mydie("ALERT: Archive contains ".
5862 "illegal member [$af]");
5863 }
5864 $CPAN::Frontend->myprint("$af\n");
5865 push @af, $af;
5866 return if $CPAN::Signal;
5867 }
5868 $tar->extract(@af);
6d29edf5
JH
5869 }
5870
be708cc0 5871 Mac::BuildTools::convert_files([$tar->list_files], 1)
6d29edf5
JH
5872 if ($^O eq 'MacOS');
5873
5874 return 1;
09d9d230
A
5875 }
5876}
5877
05d2a450 5878sub unzip {
c4d24d4c
A
5879 my($class,$file) = @_;
5880 if ($CPAN::META->has_inst("Archive::Zip")) {
5881 # blueprint of the code from Archive::Zip::Tree::extractTree();
5882 my $zip = Archive::Zip->new();
5883 my $status;
5884 $status = $zip->read($file);
5885 die "Read of file[$file] failed\n" if $status != Archive::Zip::AZ_OK();
5886 $CPAN::META->debug("Successfully read file[$file]") if $CPAN::DEBUG;
5887 my @members = $zip->members();
5888 for my $member ( @members ) {
5889 my $af = $member->fileName();
5890 if ($af =~ m!^(/|\.\./)!) {
6d29edf5
JH
5891 $CPAN::Frontend->mydie("ALERT: Archive contains ".
5892 "illegal member [$af]");
c4d24d4c
A
5893 }
5894 my $status = $member->extractToFileNamed( $af );
5895 $CPAN::META->debug("af[$af]status[$status]") if $CPAN::DEBUG;
5896 die "Extracting of file[$af] from zipfile[$file] failed\n" if
5897 $status != Archive::Zip::AZ_OK();
5898 return if $CPAN::Signal;
5899 }
5900 return 1;
5901 } else {
5902 my $unzip = $CPAN::Config->{unzip} or
5903 $CPAN::Frontend->mydie("Cannot unzip, no unzip program available");
5904 my @system = ($unzip, $file);
5905 return system(@system) == 0;
5906 }
05d2a450
A
5907}
5908
5e05dca5 5909
c4d24d4c
A
5910package CPAN::Version;
5911# CPAN::Version::vcmp courtesy Jost Krieger
5912sub vcmp {
5e05dca5
A
5913 my($self,$l,$r) = @_;
5914 local($^W) = 0;
5915 CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG;
c4d24d4c
A
5916
5917 return 0 if $l eq $r; # short circuit for quicker success
5918
5919 if ($l=~/^v/ <=> $r=~/^v/) {
5920 for ($l,$r) {
5921 next if /^v/;
5922 $_ = $self->float2vv($_);
5923 }
5924 }
5925
5926 return
5927 ($l ne "undef") <=> ($r ne "undef") ||
5928 ($] >= 5.006 &&
5929 $l =~ /^v/ &&
5930 $r =~ /^v/ &&
5931 $self->vstring($l) cmp $self->vstring($r)) ||
5932 $l <=> $r ||
5933 $l cmp $r;
5934}
5935
5936sub vgt {
5937 my($self,$l,$r) = @_;
5938 $self->vcmp($l,$r) > 0;
5e05dca5
A
5939}
5940
5941sub vstring {
5942 my($self,$n) = @_;
6d29edf5 5943 $n =~ s/^v// or die "CPAN::Version::vstring() called with invalid arg [$n]";
5e05dca5
A
5944 pack "U*", split /\./, $n;
5945}
5946
c4d24d4c
A
5947# vv => visible vstring
5948sub float2vv {
5949 my($self,$n) = @_;
5950 my($rev) = int($n);
5951 $rev ||= 0;
8d97e4a1
JH
5952 my($mantissa) = $n =~ /\.(\d{1,12})/; # limit to 12 digits to limit
5953 # architecture influence
c4d24d4c
A
5954 $mantissa ||= 0;
5955 $mantissa .= "0" while length($mantissa)%3;
5956 my $ret = "v" . $rev;
5957 while ($mantissa) {
5958 $mantissa =~ s/(\d{1,3})// or
5959 die "Panic: length>0 but not a digit? mantissa[$mantissa]";
5960 $ret .= ".".int($1);
5961 }
5962 # warn "n[$n]ret[$ret]";
5963 $ret;
5964}
5965
5e05dca5
A
5966sub readable {
5967 my($self,$n) = @_;
99c3d640 5968 $n =~ /^([\w\-\+\.]+)/;
c4d24d4c
A
5969
5970 return $1 if defined $1 && length($1)>0;
5971 # if the first user reaches version v43, he will be treated as "+".
5972 # We'll have to decide about a new rule here then, depending on what
5973 # will be the prevailing versioning behavior then.
5974
5e05dca5
A
5975 if ($] < 5.006) { # or whenever v-strings were introduced
5976 # we get them wrong anyway, whatever we do, because 5.005 will
5977 # have already interpreted 0.2.4 to be "0.24". So even if he
5978 # indexer sends us something like "v0.2.4" we compare wrongly.
5979
5980 # And if they say v1.2, then the old perl takes it as "v12"
5981
5fc0f0f6 5982 $CPAN::Frontend->mywarn("Suspicious version string seen [$n]\n");
5e05dca5
A
5983 return $n;
5984 }
5985 my $better = sprintf "v%vd", $n;
5986 CPAN->debug("n[$n] better[$better]") if $CPAN::DEBUG;
5987 return $better;
5988}
5989
55e314ee 5990package CPAN;
d4fd5c69 5991
5f05dabc 59921;
55e314ee 5993
e50380aa 5994__END__
5f05dabc 5995
5996=head1 NAME
5997
5998CPAN - query, download and build perl modules from CPAN sites
5999
6000=head1 SYNOPSIS
6001
6002Interactive mode:
6003
6004 perl -MCPAN -e shell;
6005
6006Batch mode:
6007
6008 use CPAN;
6009
10b2abe6 6010 autobundle, clean, install, make, recompile, test
5f05dabc 6011
5fc0f0f6
JH
6012=head1 STATUS
6013
6014This module will eventually be replaced by CPANPLUS. CPANPLUS is kind
6015of a modern rewrite from ground up with greater extensibility and more
6016features but no full compatibility. If you're new to CPAN.pm, you
6017probably should investigate if CPANPLUS is the better choice for you.
6018If you're already used to CPAN.pm you're welcome to continue using it,
6019if you accept that its development is mostly (though not completely)
6020stalled.
6021
5f05dabc 6022=head1 DESCRIPTION
6023
10b2abe6 6024The CPAN module is designed to automate the make and install of perl
35576f8c 6025modules and extensions. It includes some primitive searching capabilities and
42d3b621
A
6026knows how to use Net::FTP or LWP (or lynx or an external ftp client)
6027to fetch the raw data from the net.
5f05dabc 6028
6029Modules are fetched from one or more of the mirrored CPAN
6030(Comprehensive Perl Archive Network) sites and unpacked in a dedicated
6031directory.
6032
6033The CPAN module also supports the concept of named and versioned
911a92db
GS
6034I<bundles> of modules. Bundles simplify the handling of sets of
6035related modules. See Bundles below.
5f05dabc 6036
6037The package contains a session manager and a cache manager. There is
6038no status retained between sessions. The session manager keeps track
6039of what has been fetched, built and installed in the current
6040session. The cache manager keeps track of the disk space occupied by
42d3b621
A
6041the make processes and deletes excess space according to a simple FIFO
6042mechanism.
5f05dabc 6043
2e2b7522 6044For extended searching capabilities there's a plugin for CPAN available,
8b3ad137
JL
6045L<C<CPAN::WAIT>|CPAN::WAIT>. C<CPAN::WAIT> is a full-text search engine
6046that indexes all documents available in CPAN authors directories. If
d8773709
JH
6047C<CPAN::WAIT> is installed on your system, the interactive shell of
6048CPAN.pm will enable the C<wq>, C<wr>, C<wd>, C<wl>, and C<wh> commands
6049which send queries to the WAIT server that has been configured for your
6050installation.
2e2b7522
GS
6051
6052All other methods provided are accessible in a programmer style and in an
10b2abe6
CS
6053interactive shell style.
6054
5f05dabc 6055=head2 Interactive Mode
6056
6057The interactive mode is entered by running
6058
6059 perl -MCPAN -e shell
6060
09d9d230 6061which puts you into a readline interface. You will have the most fun if
5f05dabc 6062you install Term::ReadKey and Term::ReadLine to enjoy both history and
09d9d230 6063command completion.
5f05dabc 6064
6065Once you are on the command line, type 'h' and the rest should be
6066self-explanatory.
6067
9d61fa1d
A
6068The function call C<shell> takes two optional arguments, one is the
6069prompt, the second is the default initial command line (the latter
6070only works if a real ReadLine interface module is installed).
6071
10b2abe6
CS
6072The most common uses of the interactive modes are
6073
6074=over 2
6075
6076=item Searching for authors, bundles, distribution files and modules
6077
6078There are corresponding one-letter commands C<a>, C<b>, C<d>, and C<m>
42d3b621
A
6079for each of the four categories and another, C<i> for any of the
6080mentioned four. Each of the four entities is implemented as a class
6081with slightly differing methods for displaying an object.
10b2abe6 6082
09d9d230 6083Arguments you pass to these commands are either strings exactly matching
10b2abe6
CS
6084the identification string of an object or regular expressions that are
6085then matched case-insensitively against various attributes of the
09d9d230 6086objects. The parser recognizes a regular expression only if you
10b2abe6
CS
6087enclose it between two slashes.
6088
6089The principle is that the number of found objects influences how an
911a92db
GS
6090item is displayed. If the search finds one item, the result is
6091displayed with the rather verbose method C<as_string>, but if we find
6092more than one, we display each object with the terse method
6093<as_glimpse>.
10b2abe6 6094
da199366 6095=item make, test, install, clean modules or distributions
10b2abe6 6096
911a92db 6097These commands take any number of arguments and investigate what is
09d9d230 6098necessary to perform the action. If the argument is a distribution
f14b5cec
JH
6099file name (recognized by embedded slashes), it is processed. If it is
6100a module, CPAN determines the distribution file in which this module
6101is included and processes that, following any dependencies named in
6102the module's Makefile.PL (this behavior is controlled by
6103I<prerequisites_policy>.)
10b2abe6 6104
09d9d230 6105Any C<make> or C<test> are run unconditionally. An
42d3b621 6106
05454584 6107 install <distribution_file>
42d3b621 6108
09d9d230 6109also is run unconditionally. But for
42d3b621 6110
05454584 6111 install <module>
42d3b621
A
6112
6113CPAN checks if an install is actually needed for it and prints
09d9d230 6114I<module up to date> in the case that the distribution file containing
de34a54b 6115the module doesn't need to be updated.
10b2abe6
CS
6116
6117CPAN also keeps track of what it has done within the current session
de34a54b 6118and doesn't try to build a package a second time regardless if it
09d9d230
A
6119succeeded or not. The C<force> command takes as a first argument the
6120method to invoke (currently: C<make>, C<test>, or C<install>) and executes the
10b2abe6
CS
6121command from scratch.
6122
6123Example:
6124
6125 cpan> install OpenGL
6126 OpenGL is up to date.
6127 cpan> force install OpenGL
6128 Running make
6129 OpenGL-0.4/
6130 OpenGL-0.4/COPYRIGHT
6131 [...]
6132
f610777f 6133A C<clean> command results in a
09d9d230
A
6134
6135 make clean
6136
6137being executed within the distribution file's working directory.
6138
911a92db 6139=item get, readme, look module or distribution
da199366 6140
911a92db
GS
6141C<get> downloads a distribution file without further action. C<readme>
6142displays the README file of the associated distribution. C<Look> gets
6143and untars (if not yet done) the distribution file, changes to the
09d9d230
A
6144appropriate directory and opens a subshell process in that directory.
6145
c049f953
JH
6146=item ls author
6147
6148C<ls> lists all distribution files in and below an author's CPAN
6149directory. Only those files that contain modules are listed and if
6150there is more than one for any given module, only the most recent one
6151is listed.
6152
09d9d230
A
6153=item Signals
6154
6155CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are
6156in the cpan-shell it is intended that you can press C<^C> anytime and
6157return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell
6158to clean up and leave the shell loop. You can emulate the effect of a
6159SIGTERM by sending two consecutive SIGINTs, which usually means by
6160pressing C<^C> twice.
6161
6162CPAN.pm ignores a SIGPIPE. If the user sets inactivity_timeout, a
6163SIGALRM is used during the run of the C<perl Makefile.PL> subprocess.
da199366 6164
10b2abe6
CS
6165=back
6166
5f05dabc 6167=head2 CPAN::Shell
6168
6169The commands that are available in the shell interface are methods in
6170the package CPAN::Shell. If you enter the shell command, all your
10b2abe6
CS
6171input is split by the Text::ParseWords::shellwords() routine which
6172acts like most shells do. The first word is being interpreted as the
6173method to be called and the rest of the words are treated as arguments
c356248b
A
6174to this method. Continuation lines are supported if a line ends with a
6175literal backslash.
10b2abe6 6176
da199366
A
6177=head2 autobundle
6178
6179C<autobundle> writes a bundle file into the
6180C<$CPAN::Config-E<gt>{cpan_home}/Bundle> directory. The file contains
6181a list of all modules that are both available from CPAN and currently
6182installed within @INC. The name of the bundle file is based on the
6183current date and a counter.
6184
6185=head2 recompile
6186
6187recompile() is a very special command in that it takes no argument and
6188runs the make/test/install cycle with brute force over all installed
6189dynamically loadable extensions (aka XS modules) with 'force' in
09d9d230 6190effect. The primary purpose of this command is to finish a network
da199366
A
6191installation. Imagine, you have a common source tree for two different
6192architectures. You decide to do a completely independent fresh
6193installation. You start on one architecture with the help of a Bundle
6194file produced earlier. CPAN installs the whole Bundle for you, but
6195when you try to repeat the job on the second architecture, CPAN
6196responds with a C<"Foo up to date"> message for all modules. So you
de34a54b 6197invoke CPAN's recompile on the second architecture and you're done.
da199366
A
6198
6199Another popular use for C<recompile> is to act as a rescue in case your
6200perl breaks binary compatibility. If one of the modules that CPAN uses
6201is in turn depending on binary compatibility (so you cannot run CPAN
6202commands), then you should try the CPAN::Nox module for recovery.
6203
c356248b 6204=head2 The four C<CPAN::*> Classes: Author, Bundle, Module, Distribution
e50380aa 6205
09d9d230
A
6206Although it may be considered internal, the class hierarchy does matter
6207for both users and programmer. CPAN.pm deals with above mentioned four
6208classes, and all those classes share a set of methods. A classical
6209single polymorphism is in effect. A metaclass object registers all
6210objects of all kinds and indexes them with a string. The strings
6211referencing objects have a separated namespace (well, not completely
6212separated):
e50380aa
A
6213
6214 Namespace Class
6215
6216 words containing a "/" (slash) Distribution
6217 words starting with Bundle:: Bundle
6218 everything else Module or Author
6219
6220Modules know their associated Distribution objects. They always refer
09d9d230
A
6221to the most recent official release. Developers may mark their releases
6222as unstable development versions (by inserting an underbar into the
16703a00
EHA
6223module version number which will also be reflected in the distribution
6224name when you run 'make dist'), so the really hottest and newest
6225distribution is not always the default. If a module Foo circulates
6226on CPAN in both version 1.23 and 1.23_90, CPAN.pm offers a convenient
6227way to install version 1.23 by saying
e50380aa
A
6228
6229 install Foo
6230
6231This would install the complete distribution file (say
09d9d230
A
6232BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would
6233like to install version 1.23_90, you need to know where the
e50380aa 6234distribution file resides on CPAN relative to the authors/id/
09d9d230 6235directory. If the author is BAR, this might be BAR/Foo-1.23_90.tar.gz;
c356248b 6236so you would have to say
e50380aa
A
6237
6238 install BAR/Foo-1.23_90.tar.gz
6239
6240The first example will be driven by an object of the class
c356248b 6241CPAN::Module, the second by an object of class CPAN::Distribution.
e50380aa 6242
de34a54b 6243=head2 Programmer's interface
5f05dabc 6244
10b2abe6
CS
6245If you do not enter the shell, the available shell commands are both
6246available as methods (C<CPAN::Shell-E<gt>install(...)>) and as
e50380aa
A
6247functions in the calling package (C<install(...)>).
6248
09d9d230 6249There's currently only one class that has a stable interface -
e50380aa 6250CPAN::Shell. All commands that are available in the CPAN shell are
55e314ee 6251methods of the class CPAN::Shell. Each of the commands that produce
36263cb3
GS
6252listings of modules (C<r>, C<autobundle>, C<u>) also return a list of
6253the IDs of all modules within the list.
e50380aa
A
6254
6255=over 2
6256
6257=item expand($type,@things)
6258
6259The IDs of all objects available within a program are strings that can
6260be expanded to the corresponding real objects with the
55e314ee
A
6261C<CPAN::Shell-E<gt>expand("Module",@things)> method. Expand returns a
6262list of CPAN::Module objects according to the C<@things> arguments
6263given. In scalar context it only returns the first element of the
6264list.
e50380aa 6265
d8773709
JH
6266=item expandany(@things)
6267
6268Like expand, but returns objects of the appropriate type, i.e.
6269CPAN::Bundle objects for bundles, CPAN::Module objects for modules and
6270CPAN::Distribution objects fro distributions.
6271
e50380aa
A
6272=item Programming Examples
6273
55e314ee
A
6274This enables the programmer to do operations that combine
6275functionalities that are available in the shell.
e50380aa
A
6276
6277 # install everything that is outdated on my disk:
6278 perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'
6279
6280 # install my favorite programs if necessary:
5b6aeab6 6281 for $mod (qw(Net::FTP Digest::MD5 Data::Dumper)){
e50380aa
A
6282 my $obj = CPAN::Shell->expand('Module',$mod);
6283 $obj->install;
6284 }
6285
55e314ee
A
6286 # list all modules on my disk that have no VERSION number
6287 for $mod (CPAN::Shell->expand("Module","/./")){
6288 next unless $mod->inst_file;
c356248b
A
6289 # MakeMaker convention for undefined $VERSION:
6290 next unless $mod->inst_version eq "undef";
55e314ee
A
6291 print "No VERSION in ", $mod->id, "\n";
6292 }
6293
de34a54b
JH
6294 # find out which distribution on CPAN contains a module:
6295 print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file
6296
36263cb3 6297Or if you want to write a cronjob to watch The CPAN, you could list
de34a54b 6298all modules that need updating. First a quick and dirty way:
36263cb3
GS
6299
6300 perl -e 'use CPAN; CPAN::Shell->r;'
6301
9d61fa1d
A
6302If you don't want to get any output in the case that all modules are
6303up to date, you can parse the output of above command for the regular
6304expression //modules are up to date// and decide to mail the output
6305only if it doesn't match. Ick?
36263cb3
GS
6306
6307If you prefer to do it more in a programmer style in one single
8b3ad137 6308process, maybe something like this suits you better:
36263cb3
GS
6309
6310 # list all modules on my disk that have newer versions on CPAN
6311 for $mod (CPAN::Shell->expand("Module","/./")){
6312 next unless $mod->inst_file;
6313 next if $mod->uptodate;
6314 printf "Module %s is installed as %s, could be updated to %s from CPAN\n",
6315 $mod->id, $mod->inst_version, $mod->cpan_version;
6316 }
6317
6318If that gives you too much output every day, you maybe only want to
6319watch for three modules. You can write
6320
6321 for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")){
6322
6323as the first line instead. Or you can combine some of the above
6324tricks:
6325
6326 # watch only for a new mod_perl module
6327 $mod = CPAN::Shell->expand("Module","mod_perl");
6328 exit if $mod->uptodate;
6329 # new mod_perl arrived, let me know all update recommendations
6330 CPAN::Shell->r;
6331
e50380aa 6332=back
5f05dabc 6333
d8773709
JH
6334=head2 Methods in the other Classes
6335
6336The programming interface for the classes CPAN::Module,
6337CPAN::Distribution, CPAN::Bundle, and CPAN::Author is still considered
6338beta and partially even alpha. In the following paragraphs only those
6339methods are documented that have proven useful over a longer time and
6340thus are unlikely to change.
6341
bbc7dcd2 6342=over 4
d8773709
JH
6343
6344=item CPAN::Author::as_glimpse()
6345
6346Returns a one-line description of the author
6347
6348=item CPAN::Author::as_string()
6349
6350Returns a multi-line description of the author
6351
6352=item CPAN::Author::email()
6353
6354Returns the author's email address
6355
6356=item CPAN::Author::fullname()
6357
6358Returns the author's name
6359
6360=item CPAN::Author::name()
6361
6362An alias for fullname
6363
6364=item CPAN::Bundle::as_glimpse()
6365
6366Returns a one-line description of the bundle
6367
6368=item CPAN::Bundle::as_string()
6369
6370Returns a multi-line description of the bundle
6371
6372=item CPAN::Bundle::clean()
6373
6374Recursively runs the C<clean> method on all items contained in the bundle.
6375
6376=item CPAN::Bundle::contains()
6377
6378Returns a list of objects' IDs contained in a bundle. The associated
6379objects may be bundles, modules or distributions.
6380
6381=item CPAN::Bundle::force($method,@args)
6382
6383Forces CPAN to perform a task that normally would have failed. Force
6384takes as arguments a method name to be called and any number of
6385additional arguments that should be passed to the called method. The
6386internals of the object get the needed changes so that CPAN.pm does
6387not refuse to take the action. The C<force> is passed recursively to
6388all contained objects.
6389
6390=item CPAN::Bundle::get()
6391
6392Recursively runs the C<get> method on all items contained in the bundle
6393
6394=item CPAN::Bundle::inst_file()
6395
6396Returns the highest installed version of the bundle in either @INC or
6397C<$CPAN::Config->{cpan_home}>. Note that this is different from
6398CPAN::Module::inst_file.
6399
6400=item CPAN::Bundle::inst_version()
6401
6402Like CPAN::Bundle::inst_file, but returns the $VERSION
6403
6404=item CPAN::Bundle::uptodate()
6405
6406Returns 1 if the bundle itself and all its members are uptodate.
6407
6408=item CPAN::Bundle::install()
6409
6410Recursively runs the C<install> method on all items contained in the bundle
6411
6412=item CPAN::Bundle::make()
6413
6414Recursively runs the C<make> method on all items contained in the bundle
6415
6416=item CPAN::Bundle::readme()
6417
6418Recursively runs the C<readme> method on all items contained in the bundle
6419
6420=item CPAN::Bundle::test()
6421
6422Recursively runs the C<test> method on all items contained in the bundle
6423
6424=item CPAN::Distribution::as_glimpse()
6425
6426Returns a one-line description of the distribution
6427
6428=item CPAN::Distribution::as_string()
6429
6430Returns a multi-line description of the distribution
6431
6432=item CPAN::Distribution::clean()
6433
6434Changes to the directory where the distribution has been unpacked and
6435runs C<make clean> there.
6436
6437=item CPAN::Distribution::containsmods()
6438
6439Returns a list of IDs of modules contained in a distribution file.
6440Only works for distributions listed in the 02packages.details.txt.gz
6441file. This typically means that only the most recent version of a
6442distribution is covered.
6443
6444=item CPAN::Distribution::cvs_import()
6445
6446Changes to the directory where the distribution has been unpacked and
6447runs something like
6448
6449 cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version
6450
6451there.
6452
6453=item CPAN::Distribution::dir()
6454
6455Returns the directory into which this distribution has been unpacked.
6456
6457=item CPAN::Distribution::force($method,@args)
6458
6459Forces CPAN to perform a task that normally would have failed. Force
6460takes as arguments a method name to be called and any number of
6461additional arguments that should be passed to the called method. The
6462internals of the object get the needed changes so that CPAN.pm does
6463not refuse to take the action.
6464
6465=item CPAN::Distribution::get()
6466
6467Downloads the distribution from CPAN and unpacks it. Does nothing if
6468the distribution has already been downloaded and unpacked within the
6469current session.
6470
6471=item CPAN::Distribution::install()
6472
6473Changes to the directory where the distribution has been unpacked and
6474runs the external command C<make install> there. If C<make> has not
6475yet been run, it will be run first. A C<make test> will be issued in
d1be9408 6476any case and if this fails, the install will be canceled. The
d8773709
JH
6477cancellation can be avoided by letting C<force> run the C<install> for
6478you.
6479
6480=item CPAN::Distribution::isa_perl()
6481
6482Returns 1 if this distribution file seems to be a perl distribution.
6483Normally this is derived from the file name only, but the index from
6484CPAN can contain a hint to achieve a return value of true for other
6485filenames too.
6486
6487=item CPAN::Distribution::look()
6488
6489Changes to the directory where the distribution has been unpacked and
6490opens a subshell there. Exiting the subshell returns.
6491
6492=item CPAN::Distribution::make()
6493
6494First runs the C<get> method to make sure the distribution is
6495downloaded and unpacked. Changes to the directory where the
6496distribution has been unpacked and runs the external commands C<perl
6497Makefile.PL> and C<make> there.
6498
6499=item CPAN::Distribution::prereq_pm()
6500
6501Returns the hash reference that has been announced by a distribution
6502as the PREREQ_PM hash in the Makefile.PL. Note: works only after an
6503attempt has been made to C<make> the distribution. Returns undef
6504otherwise.
6505
6506=item CPAN::Distribution::readme()
6507
6508Downloads the README file associated with a distribution and runs it
6509through the pager specified in C<$CPAN::Config->{pager}>.
6510
6511=item CPAN::Distribution::test()
6512
6513Changes to the directory where the distribution has been unpacked and
6514runs C<make test> there.
6515
6516=item CPAN::Distribution::uptodate()
6517
6518Returns 1 if all the modules contained in the distribution are
6519uptodate. Relies on containsmods.
6520
6521=item CPAN::Index::force_reload()
6522
6523Forces a reload of all indices.
6524
6525=item CPAN::Index::reload()
6526
6527Reloads all indices if they have been read more than
6528C<$CPAN::Config->{index_expire}> days.
6529
6530=item CPAN::InfoObj::dump()
6531
6532CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution
6533inherit this method. It prints the data structure associated with an
6534object. Useful for debugging. Note: the data structure is considered
6535internal and thus subject to change without notice.
6536
6537=item CPAN::Module::as_glimpse()
6538
6539Returns a one-line description of the module
6540
6541=item CPAN::Module::as_string()
6542
6543Returns a multi-line description of the module
6544
6545=item CPAN::Module::clean()
6546
6547Runs a clean on the distribution associated with this module.
6548
6549=item CPAN::Module::cpan_file()
6550
6551Returns the filename on CPAN that is associated with the module.
6552
6553=item CPAN::Module::cpan_version()
6554
6555Returns the latest version of this module available on CPAN.
6556
6557=item CPAN::Module::cvs_import()
6558
6559Runs a cvs_import on the distribution associated with this module.
6560
6561=item CPAN::Module::description()
6562
d1be9408 6563Returns a 44 character description of this module. Only available for
d8773709
JH
6564modules listed in The Module List (CPAN/modules/00modlist.long.html
6565or 00modlist.long.txt.gz)
6566
6567=item CPAN::Module::force($method,@args)
6568
6569Forces CPAN to perform a task that normally would have failed. Force
6570takes as arguments a method name to be called and any number of
6571additional arguments that should be passed to the called method. The
6572internals of the object get the needed changes so that CPAN.pm does
6573not refuse to take the action.
6574
6575=item CPAN::Module::get()
6576
6577Runs a get on the distribution associated with this module.
6578
6579=item CPAN::Module::inst_file()
6580
6581Returns the filename of the module found in @INC. The first file found
6582is reported just like perl itself stops searching @INC when it finds a
6583module.
6584
6585=item CPAN::Module::inst_version()
6586
6587Returns the version number of the module in readable format.
6588
6589=item CPAN::Module::install()
6590
6591Runs an C<install> on the distribution associated with this module.
6592
6593=item CPAN::Module::look()
6594
d1be9408 6595Changes to the directory where the distribution associated with this
d8773709
JH
6596module has been unpacked and opens a subshell there. Exiting the
6597subshell returns.
6598
6599=item CPAN::Module::make()
6600
6601Runs a C<make> on the distribution associated with this module.
6602
6603=item CPAN::Module::manpage_headline()
6604
6605If module is installed, peeks into the module's manpage, reads the
6606headline and returns it. Moreover, if the module has been downloaded
6607within this session, does the equivalent on the downloaded module even
6608if it is not installed.
6609
6610=item CPAN::Module::readme()
6611
6612Runs a C<readme> on the distribution associated with this module.
6613
6614=item CPAN::Module::test()
6615
6616Runs a C<test> on the distribution associated with this module.
6617
6618=item CPAN::Module::uptodate()
6619
6620Returns 1 if the module is installed and up-to-date.
6621
6622=item CPAN::Module::userid()
6623
6624Returns the author's ID of the module.
6625
d8773709 6626=back
55e314ee 6627
5f05dabc 6628=head2 Cache Manager
6629
6630Currently the cache manager only keeps track of the build directory
6631($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that
42d3b621 6632deletes complete directories below C<build_dir> as soon as the size of
5f05dabc 6633all directories there gets bigger than $CPAN::Config->{build_cache}
6634(in MB). The contents of this cache may be used for later
6635re-installations that you intend to do manually, but will never be
10b2abe6
CS
6636trusted by CPAN itself. This is due to the fact that the user might
6637use these directories for building modules on different architectures.
5f05dabc 6638
6639There is another directory ($CPAN::Config->{keep_source_where}) where
6640the original distribution files are kept. This directory is not
6641covered by the cache manager and must be controlled by the user. If
6642you choose to have the same directory as build_dir and as
6643keep_source_where directory, then your sources will be deleted with
6644the same fifo mechanism.
6645
6646=head2 Bundles
6647
6648A bundle is just a perl module in the namespace Bundle:: that does not
6649define any functions or methods. It usually only contains documentation.
6650
6651It starts like a perl module with a package declaration and a $VERSION
6652variable. After that the pod section looks like any other pod with the
09d9d230 6653only difference being that I<one special pod section> exists starting with
10b2abe6 6654(verbatim):
5f05dabc 6655
6656 =head1 CONTENTS
6657
6658In this pod section each line obeys the format
6659
6660 Module_Name [Version_String] [- optional text]
6661
6662The only required part is the first field, the name of a module
09d9d230 6663(e.g. Foo::Bar, ie. I<not> the name of the distribution file). The rest
5f05dabc 6664of the line is optional. The comment part is delimited by a dash just
6665as in the man page header.
6666
6667The distribution of a bundle should follow the same convention as
42d3b621 6668other distributions.
5f05dabc 6669
6670Bundles are treated specially in the CPAN package. If you say 'install
6671Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all
09d9d230 6672the modules in the CONTENTS section of the pod. You can install your
5f05dabc 6673own Bundles locally by placing a conformant Bundle file somewhere into
6674your @INC path. The autobundle() command which is available in the
6675shell interface does that for you by including all currently installed
6676modules in a snapshot bundle file.
6677
da199366 6678=head2 Prerequisites
5f05dabc 6679
da199366
A
6680If you have a local mirror of CPAN and can access all files with
6681"file:" URLs, then you only need a perl better than perl5.003 to run
6682this module. Otherwise Net::FTP is strongly recommended. LWP may be
6683required for non-UNIX systems or if your nearest CPAN site is
d1be9408 6684associated with a URL that is not C<ftp:>.
5f05dabc 6685
da199366
A
6686If you have neither Net::FTP nor LWP, there is a fallback mechanism
6687implemented for an external ftp command or for an external lynx
6688command.
5f05dabc 6689
09d9d230
A
6690=head2 Finding packages and VERSION
6691
da199366 6692This module presumes that all packages on CPAN
5f05dabc 6693
da199366
A
6694=over 2
6695
6696=item *
6697
6698declare their $VERSION variable in an easy to parse manner. This
09d9d230 6699prerequisite can hardly be relaxed because it consumes far too much
da199366 6700memory to load all packages into the running program just to determine
09d9d230 6701the $VERSION variable. Currently all programs that are dealing with
da199366
A
6702version use something like this
6703
6704 perl -MExtUtils::MakeMaker -le \
2e2b7522 6705 'print MM->parse_version(shift)' filename
da199366
A
6706
6707If you are author of a package and wonder if your $VERSION can be
6708parsed, please try the above method.
6709
6710=item *
6711
6712come as compressed or gzipped tarfiles or as zip files and contain a
09d9d230 6713Makefile.PL (well, we try to handle a bit more, but without much
da199366
A
6714enthusiasm).
6715
6716=back
6717
6718=head2 Debugging
6719
6d29edf5 6720The debugging of this module is a bit complex, because we have
da199366
A
6721interferences of the software producing the indices on CPAN, of the
6722mirroring process on CPAN, of packaging, of configuration, of
6723synchronicity, and of bugs within CPAN.pm.
6724
6d29edf5
JH
6725For code debugging in interactive mode you can try "o debug" which
6726will list options for debugging the various parts of the code. You
6727should know that "o debug" has built-in completion support.
6728
6729For data debugging there is the C<dump> command which takes the same
6730arguments as make/test/install and outputs the object's Data::Dumper
6731dump.
da199366 6732
f610777f 6733=head2 Floppy, Zip, Offline Mode
da199366
A
6734
6735CPAN.pm works nicely without network too. If you maintain machines
6736that are not networked at all, you should consider working with file:
6737URLs. Of course, you have to collect your modules somewhere first. So
6738you might use CPAN.pm to put together all you need on a networked
6739machine. Then copy the $CPAN::Config->{keep_source_where} (but not
6740$CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind
6741of a personal CPAN. CPAN.pm on the non-networked machines works nicely
36263cb3 6742with this floppy. See also below the paragraph about CD-ROM support.
10b2abe6 6743
5f05dabc 6744=head1 CONFIGURATION
6745
35576f8c
A
6746When the CPAN module is used for the first time, a configuration
6747dialog tries to determine a couple of site specific options. The
6748result of the dialog is stored in a hash reference C< $CPAN::Config >
6749in a file CPAN/Config.pm.
6750
6751The default values defined in the CPAN/Config.pm file can be
6752overridden in a user specific file: CPAN/MyConfig.pm. Such a file is
6753best placed in $HOME/.cpan/CPAN/MyConfig.pm, because $HOME/.cpan is
6754added to the search path of the CPAN module before the use() or
6755require() statements.
6756
6757The configuration dialog can be started any time later again by
6758issueing the command C< o conf init > in the CPAN shell.
5f05dabc 6759
6760Currently the following keys in the hash reference $CPAN::Config are
6761defined:
6762
42d3b621
A
6763 build_cache size of cache for directories to build modules
6764 build_dir locally accessible directory to build modules
09d9d230 6765 index_expire after this many days refetch index files
5e05dca5 6766 cache_metadata use serializer to cache metadata
42d3b621 6767 cpan_home local directory reserved for this package
de34a54b
JH
6768 dontload_hash anonymous hash: modules in the keys will not be
6769 loaded by the CPAN::has_inst() routine
42d3b621 6770 gzip location of external program gzip
5fc0f0f6
JH
6771 histfile file to maintain history between sessions
6772 histsize maximum number of lines to keep in histfile
09d9d230 6773 inactivity_timeout breaks interactive Makefile.PLs after this
42d3b621 6774 many seconds inactivity. Set to 0 to never break.
5f05dabc 6775 inhibit_startup_message
42d3b621 6776 if true, does not print the startup message
09d9d230
A
6777 keep_source_where directory in which to keep the source (if we do)
6778 make location of external make program
42d3b621
A
6779 make_arg arguments that should always be passed to 'make'
6780 make_install_arg same as make_arg for 'make install'
6781 makepl_arg arguments passed to 'perl Makefile.PL'
6782 pager location of external program more (or any pager)
f14b5cec
JH
6783 prerequisites_policy
6784 what to do if you are missing module prerequisites
6785 ('follow' automatically, 'ask' me, or 'ignore')
c049f953
JH
6786 proxy_user username for accessing an authenticating proxy
6787 proxy_pass password for accessing an authenticating proxy
f610777f 6788 scan_cache controls scanning of cache ('atstart' or 'never')
42d3b621 6789 tar location of external program tar
9d61fa1d
A
6790 term_is_latin if true internal UTF-8 is translated to ISO-8859-1
6791 (and nonsense for characters outside latin range)
42d3b621
A
6792 unzip location of external program unzip
6793 urllist arrayref to nearby CPAN sites (or equivalent locations)
09d9d230 6794 wait_list arrayref to a wait server to try (See CPAN::WAIT)
f610777f
A
6795 ftp_proxy, } the three usual variables for configuring
6796 http_proxy, } proxy requests. Both as CPAN::Config variables
6797 no_proxy } and as environment variables configurable.
5f05dabc 6798
6799You can set and query each of these options interactively in the cpan
6800shell with the command set defined within the C<o conf> command:
6801
6802=over 2
6803
911a92db 6804=item C<o conf E<lt>scalar optionE<gt>>
5f05dabc 6805
6806prints the current value of the I<scalar option>
6807
911a92db 6808=item C<o conf E<lt>scalar optionE<gt> E<lt>valueE<gt>>
5f05dabc 6809
6810Sets the value of the I<scalar option> to I<value>
6811
911a92db 6812=item C<o conf E<lt>list optionE<gt>>
5f05dabc 6813
6814prints the current value of the I<list option> in MakeMaker's
6815neatvalue format.
6816
911a92db 6817=item C<o conf E<lt>list optionE<gt> [shift|pop]>
5f05dabc 6818
6819shifts or pops the array in the I<list option> variable
6820
911a92db 6821=item C<o conf E<lt>list optionE<gt> [unshift|push|splice] E<lt>listE<gt>>
5f05dabc 6822
42d3b621 6823works like the corresponding perl commands.
5f05dabc 6824
6825=back
6826
36263cb3
GS
6827=head2 Note on urllist parameter's format
6828
6829urllist parameters are URLs according to RFC 1738. We do a little
05d2a450
A
6830guessing if your URL is not compliant, but if you have problems with
6831file URLs, please try the correct format. Either:
36263cb3
GS
6832
6833 file://localhost/whatever/ftp/pub/CPAN/
6834
6835or
6836
6837 file:///home/ftp/pub/CPAN/
6838
2e2b7522 6839=head2 urllist parameter has CD-ROM support
c356248b
A
6840
6841The C<urllist> parameter of the configuration table contains a list of
6842URLs that are to be used for downloading. If the list contains any
6843C<file> URLs, CPAN always tries to get files from there first. This
6844feature is disabled for index files. So the recommendation for the
6845owner of a CD-ROM with CPAN contents is: include your local, possibly
6846outdated CD-ROM as a C<file> URL at the end of urllist, e.g.
6847
6848 o conf urllist push file://localhost/CDROM/CPAN
6849
6850CPAN.pm will then fetch the index files from one of the CPAN sites
6851that come at the beginning of urllist. It will later check for each
6852module if there is a local copy of the most recent version.
6853
2e2b7522
GS
6854Another peculiarity of urllist is that the site that we could
6855successfully fetch the last file from automatically gets a preference
6856token and is tried as the first site for the next request. So if you
6857add a new site at runtime it may happen that the previously preferred
6858site will be tried another time. This means that if you want to disallow
6859a site for the next transfer, it must be explicitly removed from
6860urllist.
6861
5f05dabc 6862=head1 SECURITY
6863
6864There's no strong security layer in CPAN.pm. CPAN.pm helps you to
6865install foreign, unmasked, unsigned code on your machine. We compare
6866to a checksum that comes from the net just as the distribution file
6867itself. If somebody has managed to tamper with the distribution file,
6868they may have as well tampered with the CHECKSUMS file. Future
f14b5cec 6869development will go towards strong authentication.
5f05dabc 6870
6871=head1 EXPORT
6872
6873Most functions in package CPAN are exported per default. The reason
6874for this is that the primary use is intended for the cpan shell or for
d1be9408 6875one-liners.
5f05dabc 6876
f610777f
A
6877=head1 POPULATE AN INSTALLATION WITH LOTS OF MODULES
6878
d8773709 6879Populating a freshly installed perl with my favorite modules is pretty
8b3ad137 6880easy if you maintain a private bundle definition file. To get a useful
f610777f
A
6881blueprint of a bundle definition file, the command autobundle can be used
6882on the CPAN shell command line. This command writes a bundle definition
36263cb3 6883file for all modules that are installed for the currently running perl
f610777f
A
6884interpreter. It's recommended to run this command only once and from then
6885on maintain the file manually under a private name, say
6886Bundle/my_bundle.pm. With a clever bundle file you can then simply say
6887
6888 cpan> install Bundle::my_bundle
6889
36263cb3 6890then answer a few questions and then go out for a coffee.
f610777f 6891
8b3ad137 6892Maintaining a bundle definition file means keeping track of two
36263cb3
GS
6893things: dependencies and interactivity. CPAN.pm sometimes fails on
6894calculating dependencies because not all modules define all MakeMaker
6895attributes correctly, so a bundle definition file should specify
6896prerequisites as early as possible. On the other hand, it's a bit
6897annoying that many distributions need some interactive configuring. So
6898what I try to accomplish in my private bundle file is to have the
6899packages that need to be configured early in the file and the gentle
6900ones later, so I can go out after a few minutes and leave CPAN.pm
8b3ad137 6901untended.
f610777f
A
6902
6903=head1 WORKING WITH CPAN.pm BEHIND FIREWALLS
6904
36263cb3 6905Thanks to Graham Barr for contributing the following paragraphs about
de34a54b
JH
6906the interaction between perl, and various firewall configurations. For
6907further informations on firewalls, it is recommended to consult the
6908documentation that comes with the ncftp program. If you are unable to
6909go through the firewall with a simple Perl setup, it is very likely
6910that you can configure ncftp so that it works for your firewall.
6911
6912=head2 Three basic types of firewalls
f610777f
A
6913
6914Firewalls can be categorized into three basic types.
6915
bbc7dcd2 6916=over 4
f610777f
A
6917
6918=item http firewall
6919
6920This is where the firewall machine runs a web server and to access the
6921outside world you must do it via the web server. If you set environment
6922variables like http_proxy or ftp_proxy to a values beginning with http://
6923or in your web browser you have to set proxy information then you know
d1be9408 6924you are running an http firewall.
f610777f
A
6925
6926To access servers outside these types of firewalls with perl (even for
6927ftp) you will need to use LWP.
6928
6929=item ftp firewall
6930
d1be9408 6931This where the firewall machine runs an ftp server. This kind of
911a92db
GS
6932firewall will only let you access ftp servers outside the firewall.
6933This is usually done by connecting to the firewall with ftp, then
6934entering a username like "user@outside.host.com"
f610777f
A
6935
6936To access servers outside these type of firewalls with perl you
6937will need to use Net::FTP.
6938
6939=item One way visibility
6940
d1be9408 6941I say one way visibility as these firewalls try to make themselves look
f610777f
A
6942invisible to the users inside the firewall. An FTP data connection is
6943normally created by sending the remote server your IP address and then
6944listening for the connection. But the remote server will not be able to
6945connect to you because of the firewall. So for these types of firewall
6946FTP connections need to be done in a passive mode.
6947
6948There are two that I can think off.
6949
bbc7dcd2 6950=over 4
f610777f
A
6951
6952=item SOCKS
6953
6954If you are using a SOCKS firewall you will need to compile perl and link
c4d24d4c 6955it with the SOCKS library, this is what is normally called a 'socksified'
f610777f
A
6956perl. With this executable you will be able to connect to servers outside
6957the firewall as if it is not there.
6958
6959=item IP Masquerade
6960
6961This is the firewall implemented in the Linux kernel, it allows you to
6962hide a complete network behind one IP address. With this firewall no
d8773709 6963special compiling is needed as you can access hosts directly.
f610777f 6964
5fc0f0f6
JH
6965For accessing ftp servers behind such firewalls you may need to set
6966the environment variable C<FTP_PASSIVE> to a true value, e.g.
6967
6968 env FTP_PASSIVE=1 perl -MCPAN -eshell
6969
6970or
6971
6972 perl -MCPAN -e '$ENV{FTP_PASSIVE} = 1; shell'
6973
6974
f610777f
A
6975=back
6976
6977=back
6978
c4d24d4c 6979=head2 Configuring lynx or ncftp for going through a firewall
de34a54b
JH
6980
6981If you can go through your firewall with e.g. lynx, presumably with a
6982command such as
6983
6984 /usr/local/bin/lynx -pscott:tiger
6985
6986then you would configure CPAN.pm with the command
6987
6988 o conf lynx "/usr/local/bin/lynx -pscott:tiger"
6989
6990That's all. Similarly for ncftp or ftp, you would configure something
6991like
6992
6993 o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg"
6994
d1be9408 6995Your mileage may vary...
de34a54b
JH
6996
6997=head1 FAQ
6998
bbc7dcd2 6999=over 4
de34a54b 7000
551e1d92
RB
7001=item 1)
7002
7003I installed a new version of module X but CPAN keeps saying,
7004I have the old version installed
de34a54b
JH
7005
7006Most probably you B<do> have the old version installed. This can
7007happen if a module installs itself into a different directory in the
7008@INC path than it was previously installed. This is not really a
7009CPAN.pm problem, you would have the same problem when installing the
7010module manually. The easiest way to prevent this behaviour is to add
7011the argument C<UNINST=1> to the C<make install> call, and that is why
7012many people add this argument permanently by configuring
7013
7014 o conf make_install_arg UNINST=1
7015
551e1d92
RB
7016=item 2)
7017
7018So why is UNINST=1 not the default?
de34a54b
JH
7019
7020Because there are people who have their precise expectations about who
7021may install where in the @INC path and who uses which @INC array. In
7022fine tuned environments C<UNINST=1> can cause damage.
7023
551e1d92
RB
7024=item 3)
7025
7026I want to clean up my mess, and install a new perl along with
7027all modules I have. How do I go about it?
9d61fa1d
A
7028
7029Run the autobundle command for your old perl and optionally rename the
7030resulting bundle file (e.g. Bundle/mybundle.pm), install the new perl
7031with the Configure option prefix, e.g.
7032
7033 ./Configure -Dprefix=/usr/local/perl-5.6.78.9
7034
7035Install the bundle file you produced in the first step with something like
7036
7037 cpan> install Bundle::mybundle
7038
7039and you're done.
7040
551e1d92
RB
7041=item 4)
7042
7043When I install bundles or multiple modules with one command
7044there is too much output to keep track of.
de34a54b
JH
7045
7046You may want to configure something like
7047
7048 o conf make_arg "| tee -ai /root/.cpan/logs/make.out"
7049 o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out"
7050
7051so that STDOUT is captured in a file for later inspection.
7052
c4d24d4c 7053
551e1d92
RB
7054=item 5)
7055
7056I am not root, how can I install a module in a personal directory?
c4d24d4c
A
7057
7058You will most probably like something like this:
7059
7060 o conf makepl_arg "LIB=~/myperl/lib \
7061 INSTALLMAN1DIR=~/myperl/man/man1 \
7062 INSTALLMAN3DIR=~/myperl/man/man3"
7063 install Sybase::Sybperl
7064
7065You can make this setting permanent like all C<o conf> settings with
7066C<o conf commit>.
7067
7068You will have to add ~/myperl/man to the MANPATH environment variable
7069and also tell your perl programs to look into ~/myperl/lib, e.g. by
7070including
7071
7072 use lib "$ENV{HOME}/myperl/lib";
7073
7074or setting the PERL5LIB environment variable.
7075
7076Another thing you should bear in mind is that the UNINST parameter
7077should never be set if you are not root.
7078
551e1d92
RB
7079=item 6)
7080
7081How to get a package, unwrap it, and make a change before building it?
c4d24d4c
A
7082
7083 look Sybase::Sybperl
7084
551e1d92
RB
7085=item 7)
7086
7087I installed a Bundle and had a couple of fails. When I
7088retried, everything resolved nicely. Can this be fixed to work
7089on first try?
c4d24d4c
A
7090
7091The reason for this is that CPAN does not know the dependencies of all
7092modules when it starts out. To decide about the additional items to
7093install, it just uses data found in the generated Makefile. An
7094undetected missing piece breaks the process. But it may well be that
7095your Bundle installs some prerequisite later than some depending item
7096and thus your second try is able to resolve everything. Please note,
7097CPAN.pm does not know the dependency tree in advance and cannot sort
5a5fac02
JH
7098the queue of things to install in a topologically correct order. It
7099resolves perfectly well IFF all modules declare the prerequisites
7100correctly with the PREREQ_PM attribute to MakeMaker. For bundles which
7101fail and you need to install often, it is recommended sort the Bundle
7102definition file manually. It is planned to improve the metadata
7103situation for dependencies on CPAN in general, but this will still
7104take some time.
7105
551e1d92
RB
7106=item 8)
7107
7108In our intranet we have many modules for internal use. How
7109can I integrate these modules with CPAN.pm but without uploading
7110the modules to CPAN?
5a5fac02
JH
7111
7112Have a look at the CPAN::Site module.
c4d24d4c 7113
551e1d92
RB
7114=item 9)
7115
7116When I run CPAN's shell, I get error msg about line 1 to 4,
7117setting meta input/output via the /etc/inputrc file.
9d61fa1d 7118
8d97e4a1
JH
7119Some versions of readline are picky about capitalization in the
7120/etc/inputrc file and specifically RedHat 6.2 comes with a
7121/etc/inputrc that contains the word C<on> in lowercase. Change the
7122occurrences of C<on> to C<On> and the bug should disappear.
7123
551e1d92
RB
7124=item 10)
7125
7126Some authors have strange characters in their names.
8d97e4a1
JH
7127
7128Internally CPAN.pm uses the UTF-8 charset. If your terminal is
7129expecting ISO-8859-1 charset, a converter can be activated by setting
7130term_is_latin to a true value in your config file. One way of doing so
7131would be
7132
7133 cpan> ! $CPAN::Config->{term_is_latin}=1
7134
7135Extended support for converters will be made available as soon as perl
7136becomes stable with regard to charset issues.
9d61fa1d 7137
de34a54b
JH
7138=back
7139
da199366 7140=head1 BUGS
5f05dabc 7141
36263cb3 7142We should give coverage for B<all> of the CPAN and not just the PAUSE
09d9d230 7143part, right? In this discussion CPAN and PAUSE have become equal --
c049f953 7144but they are not. PAUSE is authors/, modules/ and scripts/. CPAN is
c4d24d4c 7145PAUSE plus the clpa/, doc/, misc/, ports/, and src/.
5f05dabc 7146
c356248b 7147Future development should be directed towards a better integration of
da199366 7148the other parts.
5f05dabc 7149
09d9d230
A
7150If a Makefile.PL requires special customization of libraries, prompts
7151the user for special input, etc. then you may find CPAN is not able to
7152build the distribution. In that case, you should attempt the
7153traditional method of building a Perl module package from a shell.
7154
5f05dabc 7155=head1 AUTHOR
7156
911a92db 7157Andreas Koenig E<lt>andreas.koenig@anima.deE<gt>
5f05dabc 7158
c049f953
JH
7159=head1 TRANSLATIONS
7160
7161Kawai,Takanori provides a Japanese translation of this manpage at
7162http://member.nifty.ne.jp/hippo2000/perltips/CPAN.htm
7163
5f05dabc 7164=head1 SEE ALSO
7165
7166perl(1), CPAN::Nox(3)
7167
7168=cut
7169