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