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