File Coverage

blib/lib/CPAN.pm
Criterion Covered Total %
statement 247 804 30.7
branch 51 388 13.1
condition 23 165 13.9
subroutine 63 106 59.4
pod 13 27 48.1
total 397 1490 26.6


line stmt bran cond sub pod time code
1             # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
2             # vim: ts=4 sts=4 sw=4:
3 12     12   97478 use strict;
  12         59  
  12         1086  
4             package CPAN;
5             $CPAN::VERSION = '2.20';
6             $CPAN::VERSION =~ s/_//;
7              
8             # we need to run chdir all over and we would get at wrong libraries
9             # there
10 12     12   82 use File::Spec ();
  12         28  
  12         1099  
11             BEGIN {
12 12 50   12   253 if (File::Spec->can("rel2abs")) {
13 12         52 for my $inc (@INC) {
14 135 50       1529 $inc = File::Spec->rel2abs($inc) unless ref $inc;
15             }
16             }
17 12 50       628 $SIG{WINCH} = 'IGNORE' if exists $SIG{WINCH};
18             }
19 12     12   4190 use CPAN::Author;
  12         35  
  12         392  
20 12     12   4909 use CPAN::HandleConfig;
  12         44  
  12         435  
21 12     12   4498 use CPAN::Version;
  12         29  
  12         361  
22 12     12   3790 use CPAN::Bundle;
  12         47  
  12         472  
23 12     12   8768 use CPAN::CacheMgr;
  12         41  
  12         413  
24 12     12   3929 use CPAN::Complete;
  12         40  
  12         406  
25 12     12   85 use CPAN::Debug;
  12         26  
  12         276  
26 12     12   9192 use CPAN::Distribution;
  12         49  
  12         651  
27 12     12   4980 use CPAN::Distrostatus;
  12         37  
  12         372  
28 12     12   4896 use CPAN::FTP;
  12         52  
  12         573  
29 12     12   5417 use CPAN::Index 1.93; # https://rt.cpan.org/Ticket/Display.html?id=43349
  12         345  
  12         522  
30 12     12   131 use CPAN::InfoObj;
  12         33  
  12         348  
31 12     12   89 use CPAN::Module;
  12         29  
  12         311  
32 12     12   4282 use CPAN::Prompt;
  12         36  
  12         392  
33 12     12   3344 use CPAN::URL;
  12         39  
  12         427  
34 12     12   3517 use CPAN::Queue;
  12         45  
  12         427  
35 12     12   4313 use CPAN::Tarzip;
  12         72  
  12         554  
36 12     12   4271 use CPAN::DeferredCode;
  12         31  
  12         333  
37 12     12   5539 use CPAN::Shell;
  12         46  
  12         518  
38 12     12   4779 use CPAN::LWP::UserAgent;
  12         38  
  12         410  
39 12     12   4039 use CPAN::Exception::RecursiveDependency;
  12         38  
  12         408  
40 12     12   3708 use CPAN::Exception::yaml_not_installed;
  12         34  
  12         394  
41 12     12   3693 use CPAN::Exception::yaml_process_error;
  12         38  
  12         375  
42              
43 12     12   88 use Carp ();
  12         33  
  12         242  
44 12     12   71 use Config ();
  12         29  
  12         275  
45 12     12   69 use Cwd qw(chdir);
  12         34  
  12         763  
46 12     12   80 use DirHandle ();
  12         28  
  12         196  
47 12     12   66 use Exporter ();
  12         23  
  12         290  
48 12     12   6478 use ExtUtils::MakeMaker qw(prompt); # for some unknown reason,
  12         1156772  
  12         956  
49             # 5.005_04 does not work without
50             # this
51 12     12   110 use File::Basename ();
  12         31  
  12         278  
52 12     12   3157 use File::Copy ();
  12         22654  
  12         325  
53 12     12   80 use File::Find;
  12         28  
  12         745  
54 12     12   83 use File::Path ();
  12         27  
  12         200  
55 12     12   3312 use FileHandle ();
  12         77546  
  12         433  
56 12     12   94 use Fcntl qw(:flock);
  12         25  
  12         1653  
57 12     12   4385 use Safe ();
  12         422436  
  12         751  
58 12     12   4124 use Sys::Hostname qw(hostname);
  12         11908  
  12         727  
59 12     12   3119 use Text::ParseWords ();
  12         13947  
  12         323  
60 12     12   3264 use Text::Wrap ();
  12         26568  
  12         627  
61              
62             # protect against "called too early"
63             sub find_perl ();
64             sub anycwd ();
65             sub _uniq;
66              
67 12     12   3146 no lib ".";
  12         6315  
  12         76  
68              
69             require Mac::BuildTools if $^O eq 'MacOS';
70             if ($ENV{PERL5_CPAN_IS_RUNNING} && $$ != $ENV{PERL5_CPAN_IS_RUNNING}) {
71             $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION} ||= $ENV{PERL5_CPAN_IS_RUNNING};
72             my @rec = _uniq split(/,/, $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION}), $$;
73             $ENV{PERL5_CPAN_IS_RUNNING_IN_RECURSION} = join ",", @rec;
74             # warn "# Note: Recursive call of CPAN.pm detected\n";
75             my $w = sprintf "# Note: CPAN.pm is running in process %d now", pop @rec;
76             my %sleep = (
77             5 => 30,
78             6 => 60,
79             7 => 120,
80             );
81             my $sleep = @rec > 7 ? 300 : ($sleep{scalar @rec}||0);
82             my $verbose = @rec >= 4;
83             while (@rec) {
84             $w .= sprintf " which has been called by process %d", pop @rec;
85             }
86             if ($sleep) {
87             $w .= ".\n\n# Sleeping $sleep seconds to protect other processes\n";
88             }
89             if ($verbose) {
90             warn $w;
91             }
92             local $| = 1;
93             while ($sleep > 0) {
94             printf "\r#%5d", --$sleep;
95             sleep 1;
96             }
97             print "\n";
98             }
99             $ENV{PERL5_CPAN_IS_RUNNING}=$$;
100             $ENV{PERL5_CPANPLUS_IS_RUNNING}=$$; # https://rt.cpan.org/Ticket/Display.html?id=23735
101              
102 12     12   18547 END { $CPAN::End++; &cleanup; }
  12         72  
103              
104             $CPAN::Signal ||= 0;
105             $CPAN::Frontend ||= "CPAN::Shell";
106             unless (@CPAN::Defaultsites) {
107             @CPAN::Defaultsites = map {
108             CPAN::URL->new(TEXT => $_, FROM => "DEF")
109             }
110             "http://www.perl.org/CPAN/",
111             "ftp://ftp.perl.org/pub/CPAN/";
112             }
113             # $CPAN::iCwd (i for initial)
114             $CPAN::iCwd ||= CPAN::anycwd();
115             $CPAN::Perl ||= CPAN::find_perl();
116             $CPAN::Defaultdocs ||= "http://search.cpan.org/perldoc?";
117             $CPAN::Defaultrecent ||= "http://search.cpan.org/uploads.rdf";
118             $CPAN::Defaultrecent ||= "http://cpan.uwinnipeg.ca/htdocs/cpan.xml";
119              
120             # our globals are getting a mess
121 12         16502 use vars qw(
122             $AUTOLOAD
123             $Be_Silent
124             $CONFIG_DIRTY
125             $Defaultdocs
126             $Echo_readline
127             $Frontend
128             $GOTOSHELL
129             $HAS_USABLE
130             $Have_warned
131             $MAX_RECURSION
132             $META
133             $RUN_DEGRADED
134             $Signal
135             $SQLite
136             $Suppress_readline
137             $VERSION
138             $autoload_recursion
139             $term
140             @Defaultsites
141             @EXPORT
142 12     12   4922 );
  12         35  
143              
144             $MAX_RECURSION = 32;
145              
146             @CPAN::ISA = qw(CPAN::Debug Exporter);
147              
148             # note that these functions live in CPAN::Shell and get executed via
149             # AUTOLOAD when called directly
150             @EXPORT = qw(
151             autobundle
152             bundle
153             clean
154             cvs_import
155             expand
156             force
157             fforce
158             get
159             install
160             install_tested
161             is_tested
162             make
163             mkmyconfig
164             notest
165             perldoc
166             readme
167             recent
168             recompile
169             report
170             shell
171             smoke
172             test
173             upgrade
174             );
175              
176             sub soft_chdir_with_alternatives ($);
177              
178             {
179             $autoload_recursion ||= 0;
180              
181             #-> sub CPAN::AUTOLOAD ;
182             sub AUTOLOAD { ## no critic
183 1     1   78 $autoload_recursion++;
184 1         7 my($l) = $AUTOLOAD;
185 1         102 $l =~ s/.*:://;
186 1 50       10 if ($CPAN::Signal) {
187 0         0 warn "Refusing to autoload '$l' while signal pending";
188 0         0 $autoload_recursion--;
189 0         0 return;
190             }
191 1 50       8 if ($autoload_recursion > 1) {
192 0         0 my $fullcommand = join " ", map { "'$_'" } $l, @_;
  0         0  
193 0         0 warn "Refusing to autoload $fullcommand in recursion\n";
194 0         0 $autoload_recursion--;
195 0         0 return;
196             }
197 1         4 my(%export);
198 1         83 @export{@EXPORT} = '';
199 1 50       38 CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
200 1 50       8 if (exists $export{$l}) {
201 0         0 CPAN::Shell->$l(@_);
202             } else {
203 1         16 die(qq{Unknown CPAN command "$AUTOLOAD". }.
204             qq{Type ? for help.\n});
205             }
206 0         0 $autoload_recursion--;
207             }
208             }
209              
210             {
211             my $x = *SAVEOUT; # avoid warning
212             open($x,">&STDOUT") or die "dup failed";
213             my $redir = 0;
214             sub _redirect(@) {
215             #die if $redir;
216 0     0   0 local $_;
217 0         0 push(@_,undef);
218 0         0 while(defined($_=shift)) {
219 0 0       0 if (s/^\s*>//){
    0          
220 0 0       0 my ($m) = s/^>// ? ">" : "";
221 0         0 s/\s+//;
222 0 0       0 $_=shift unless length;
223 0 0       0 die "no dest" unless defined;
224 0 0       0 open(STDOUT,">$m$_") or die "open:$_:$!\n";
225 0         0 $redir=1;
226             } elsif ( s/^\s*\|\s*// ) {
227 0         0 my $pipe="| $_";
228 0         0 while(defined($_[0])){
229 0         0 $pipe .= ' ' . shift;
230             }
231 0 0       0 open(STDOUT,$pipe) or die "open:$pipe:$!\n";
232 0         0 $redir=1;
233             } else {
234 0         0 push(@_,$_);
235             }
236             }
237 0         0 return @_;
238             }
239             sub _unredirect {
240 0 0   0   0 return unless $redir;
241 0         0 $redir = 0;
242             ## redirect: unredirect and propagate errors. explicit close to wait for pipe.
243 0         0 close(STDOUT);
244 0         0 open(STDOUT,">&SAVEOUT");
245 0 0       0 die "$@" if "$@";
246             ## redirect: done
247             }
248             }
249              
250             sub _uniq {
251 0     0   0 my(@list) = @_;
252 0         0 my %seen;
253 0         0 return grep { !$seen{$_}++ } @list;
  0         0  
254             }
255              
256             #-> sub CPAN::shell ;
257             sub shell {
258 0     0 1 0 my($self) = @_;
259 0 0       0 $Suppress_readline = ! -t STDIN unless defined $Suppress_readline;
260 0 0       0 CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
261              
262 0   0     0 my $oprompt = shift || CPAN::Prompt->new;
263 0         0 my $prompt = $oprompt;
264 0   0     0 my $commandline = shift || "";
265 0   0     0 $CPAN::CurrentCommandId ||= 1;
266              
267 0         0 local($^W) = 1;
268 0 0       0 unless ($Suppress_readline) {
269 0         0 require Term::ReadLine;
270 0 0 0     0 if (! $term
271             or
272             $term->ReadLine eq "Term::ReadLine::Stub"
273             ) {
274 0         0 $term = Term::ReadLine->new('CPAN Monitor');
275             }
276 0 0       0 if ($term->ReadLine eq "Term::ReadLine::Gnu") {
277 0         0 my $attribs = $term->Attribs;
278             $attribs->{attempted_completion_function} = sub {
279 0     0   0 &CPAN::Complete::gnu_cpl;
280             }
281 0         0 } else {
282 0         0 $readline::rl_completion_function =
283             $readline::rl_completion_function = 'CPAN::Complete::cpl';
284             }
285 0 0       0 if (my $histfile = $CPAN::Config->{'histfile'}) {{
286 0 0       0 unless ($term->can("AddHistory")) {
  0         0  
287 0         0 $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n");
288 0         0 last;
289             }
290 0         0 $META->readhist($term,$histfile);
291             }}
292 0         0 for ($CPAN::Config->{term_ornaments}) { # alias
293 0         0 local $Term::ReadLine::termcap_nowarn = 1;
294 0 0       0 $term->ornaments($_) if defined;
295             }
296             # $term->OUT is autoflushed anyway
297 0         0 my $odef = select STDERR;
298 0         0 $| = 1;
299 0         0 select STDOUT;
300 0         0 $| = 1;
301 0         0 select $odef;
302             }
303              
304 0         0 $META->checklock();
305 0 0       0 my @cwd = grep { defined $_ and length $_ }
  0 0       0  
306             CPAN::anycwd(),
307             File::Spec->can("tmpdir") ? File::Spec->tmpdir() : (),
308             File::Spec->rootdir();
309 0         0 my $try_detect_readline;
310 0 0       0 $try_detect_readline = $term->ReadLine eq "Term::ReadLine::Stub" if $term;
311 0 0       0 unless ($CPAN::Config->{inhibit_startup_message}) {
312 0 0       0 my $rl_avail = $Suppress_readline ? "suppressed" :
    0          
313             ($term->ReadLine ne "Term::ReadLine::Stub") ? "enabled" :
314             "available (maybe install Bundle::CPAN or Bundle::CPANxxl?)";
315 0         0 $CPAN::Frontend->myprint(
316             sprintf qq{
317             cpan shell -- CPAN exploration and modules installation (v%s)
318             Enter 'h' for help.
319              
320             },
321             $CPAN::VERSION,
322             )
323             }
324 0         0 my($continuation) = "";
325 0         0 my $last_term_ornaments;
326 0         0 SHELLCOMMAND: while () {
327 0 0       0 if ($Suppress_readline) {
328 0 0       0 if ($Echo_readline) {
329 0         0 $|=1;
330             }
331 0         0 print $prompt;
332 0 0       0 last SHELLCOMMAND unless defined ($_ = <> );
333 0 0       0 if ($Echo_readline) {
334             # backdoor: I could not find a way to record sessions
335 0         0 print $_;
336             }
337 0         0 chomp;
338             } else {
339             last SHELLCOMMAND unless
340 0 0       0 defined ($_ = $term->readline($prompt, $commandline));
341             }
342 0 0       0 $_ = "$continuation$_" if $continuation;
343 0         0 s/^\s+//;
344 0 0       0 next SHELLCOMMAND if /^$/;
345 0         0 s/^\s*\?\s*/help /;
346 0 0       0 if (/^(?:q(?:uit)?|bye|exit)\s*$/i) {
    0          
    0          
    0          
347 0         0 last SHELLCOMMAND;
348             } elsif (s/\\$//s) {
349 0         0 chomp;
350 0         0 $continuation = $_;
351 0         0 $prompt = " > ";
352             } elsif (/^\!/) {
353 0         0 s/^\!//;
354 0         0 my($eval) = $_;
355             package
356             CPAN::Eval; # hide from the indexer
357 12     12   107 use strict;
  12         33  
  12         375  
358 12     12   79 use vars qw($import_done);
  12         32  
  12         16461  
359 0 0       0 CPAN->import(':DEFAULT') unless $import_done++;
360 0 0       0 CPAN->debug("eval[$eval]") if $CPAN::DEBUG;
361 0         0 eval($eval);
362 0 0       0 warn $@ if $@;
363 0         0 $continuation = "";
364 0         0 $prompt = $oprompt;
365             } elsif (/./) {
366 0         0 my(@line);
367 0         0 eval { @line = Text::ParseWords::shellwords($_) };
  0         0  
368 0 0       0 warn($@), next SHELLCOMMAND if $@;
369 0 0       0 warn("Text::Parsewords could not parse the line [$_]"),
370             next SHELLCOMMAND unless @line;
371 0 0       0 $CPAN::META->debug("line[".join("|",@line)."]") if $CPAN::DEBUG;
372 0         0 my $command = shift @line;
373 0         0 eval {
374 0         0 local (*STDOUT)=*STDOUT;
375 0         0 @line = _redirect(@line);
376 0         0 CPAN::Shell->$command(@line)
377             };
378 0         0 my $command_error = $@;
379 0         0 _unredirect;
380 0         0 my $reported_error;
381 0 0       0 if ($command_error) {
382 0         0 my $err = $command_error;
383 0 0 0     0 if (ref $err and $err->isa('CPAN::Exception::blocked_urllist')) {
384 0         0 $CPAN::Frontend->mywarn("Client not fully configured, please proceed with configuring.$err");
385 0         0 $reported_error = ref $err;
386             } else {
387             # I'd prefer never to arrive here and make all errors exception objects
388 0 0       0 if ($err =~ /\S/) {
389 0         0 require Carp;
390 0         0 require Dumpvalue;
391 0         0 my $dv = Dumpvalue->new(tick => '"');
392 0         0 Carp::cluck(sprintf "Catching error: %s", $dv->stringify($err));
393             }
394             }
395             }
396 0 0       0 if ($command =~ /^(
397             # classic commands
398             make
399             |test
400             |install
401             |clean
402              
403             # pragmas for classic commands
404             |ff?orce
405             |notest
406              
407             # compounds
408             |report
409             |smoke
410             |upgrade
411             )$/x) {
412             # only commands that tell us something about failed distros
413             # eval necessary for people without an urllist
414 0         0 eval {CPAN::Shell->failed($CPAN::CurrentCommandId,1);};
  0         0  
415 0 0       0 if (my $err = $@) {
416 0 0 0     0 unless (ref $err and $reported_error eq ref $err) {
417 0         0 die $@;
418             }
419             }
420             }
421 0         0 soft_chdir_with_alternatives(\@cwd);
422 0         0 $CPAN::Frontend->myprint("\n");
423 0         0 $continuation = "";
424 0         0 $CPAN::CurrentCommandId++;
425 0         0 $prompt = $oprompt;
426             }
427             } continue {
428 0         0 $commandline = ""; # I do want to be able to pass a default to
429             # shell, but on the second command I see no
430             # use in that
431 0         0 $Signal=0;
432 0         0 CPAN::Queue->nullify_queue;
433 0 0       0 if ($try_detect_readline) {
434 0 0 0     0 if ($CPAN::META->has_inst("Term::ReadLine::Gnu")
435             ||
436             $CPAN::META->has_inst("Term::ReadLine::Perl")
437             ) {
438 0         0 delete $INC{"Term/ReadLine.pm"};
439 0         0 my $redef = 0;
440 0         0 local($SIG{__WARN__}) = CPAN::Shell::paintdots_onreload(\$redef);
441 0         0 require Term::ReadLine;
442 0         0 $CPAN::Frontend->myprint("\n$redef subroutines in ".
443             "Term::ReadLine redefined\n");
444 0         0 $GOTOSHELL = 1;
445             }
446             }
447 0 0 0     0 if ($term and $term->can("ornaments")) {
448 0         0 for ($CPAN::Config->{term_ornaments}) { # alias
449 0 0       0 if (defined $_) {
450 0 0 0     0 if (not defined $last_term_ornaments
451             or $_ != $last_term_ornaments
452             ) {
453 0         0 local $Term::ReadLine::termcap_nowarn = 1;
454 0         0 $term->ornaments($_);
455 0         0 $last_term_ornaments = $_;
456             }
457             } else {
458 0         0 undef $last_term_ornaments;
459             }
460             }
461             }
462 0         0 for my $class (qw(Module Distribution)) {
463             # again unsafe meta access?
464 0         0 for my $dm (sort keys %{$CPAN::META->{readwrite}{"CPAN::$class"}}) {
  0         0  
465 0 0       0 next unless $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor};
466 0         0 CPAN->debug("BUG: $class '$dm' was in command state, resetting");
467 0         0 delete $CPAN::META->{readwrite}{"CPAN::$class"}{$dm}{incommandcolor};
468             }
469             }
470 0 0       0 if ($GOTOSHELL) {
471 0         0 $GOTOSHELL = 0; # not too often
472 0 0 0     0 $META->savehist if $CPAN::term && $CPAN::term->can("GetHistory");
473 0         0 @_ = ($oprompt,"");
474 0         0 goto &shell;
475             }
476             }
477 0         0 soft_chdir_with_alternatives(\@cwd);
478             }
479              
480             #-> CPAN::soft_chdir_with_alternatives ;
481             sub soft_chdir_with_alternatives ($) {
482 0     0 0 0 my($cwd) = @_;
483 0 0       0 unless (@$cwd) {
484 0         0 my $root = File::Spec->rootdir();
485 0         0 $CPAN::Frontend->mywarn(qq{Warning: no good directory to chdir to!
486             Trying '$root' as temporary haven.
487             });
488 0         0 push @$cwd, $root;
489             }
490 0         0 while () {
491 0 0       0 if (chdir $cwd->[0]) {
492 0         0 return;
493             } else {
494 0 0       0 if (@$cwd>1) {
495 0         0 $CPAN::Frontend->mywarn(qq{Could not chdir to "$cwd->[0]": $!
496             Trying to chdir to "$cwd->[1]" instead.
497             });
498 0         0 shift @$cwd;
499             } else {
500 0         0 $CPAN::Frontend->mydie(qq{Could not chdir to "$cwd->[0]": $!});
501             }
502             }
503             }
504             }
505              
506             sub _flock {
507 0     0   0 my($fh,$mode) = @_;
508 0 0 0     0 if ( $Config::Config{d_flock} || $Config::Config{d_fcntl_can_lock} ) {
    0          
509 0         0 return flock $fh, $mode;
510             } elsif (!$Have_warned->{"d_flock"}++) {
511 0         0 $CPAN::Frontend->mywarn("Your OS does not seem to support locking; continuing and ignoring all locking issues\n");
512 0         0 $CPAN::Frontend->mysleep(5);
513 0         0 return 1;
514             } else {
515 0         0 return 1;
516             }
517             }
518              
519             sub _yaml_module () {
520 3   50 3   25 my $yaml_module = $CPAN::Config->{yaml_module} || "YAML";
521 3 50 33     20 if (
522             $yaml_module ne "YAML"
523             &&
524             !$CPAN::META->has_inst($yaml_module)
525             ) {
526             # $CPAN::Frontend->mywarn("'$yaml_module' not installed, falling back to 'YAML'\n");
527 0         0 $yaml_module = "YAML";
528             }
529 3 0 33     23 if ($yaml_module eq "YAML"
      33        
      33        
530             &&
531             $CPAN::META->has_inst($yaml_module)
532             &&
533             $YAML::VERSION < 0.60
534             &&
535             !$Have_warned->{"YAML"}++
536             ) {
537 0         0 $CPAN::Frontend->mywarn("Warning: YAML version '$YAML::VERSION' is too low, please upgrade!\n".
538             "I'll continue but problems are *very* likely to happen.\n"
539             );
540 0         0 $CPAN::Frontend->mysleep(5);
541             }
542 3         16 return $yaml_module;
543             }
544              
545             # CPAN::_yaml_loadfile
546             sub _yaml_loadfile {
547 0     0   0 my($self,$local_file) = @_;
548 0 0       0 return +[] unless -s $local_file;
549 0         0 my $yaml_module = _yaml_module;
550 0 0       0 if ($CPAN::META->has_inst($yaml_module)) {
551             # temporarily enable yaml code deserialisation
552 12     12   108 no strict 'refs';
  12         33  
  12         48833  
553             # 5.6.2 could not do the local() with the reference
554             # so we do it manually instead
555 0         0 my $old_loadcode = ${"$yaml_module\::LoadCode"};
  0         0  
556 0   0     0 ${ "$yaml_module\::LoadCode" } = $CPAN::Config->{yaml_load_code} || 0;
  0         0  
557              
558 0         0 my ($code, @yaml);
559 0 0       0 if ($code = UNIVERSAL::can($yaml_module, "LoadFile")) {
    0          
560 0         0 eval { @yaml = $code->($local_file); };
  0         0  
561 0 0       0 if ($@) {
562             # this shall not be done by the frontend
563 0         0 die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@);
564             }
565             } elsif ($code = UNIVERSAL::can($yaml_module, "Load")) {
566 0         0 local *FH;
567 0 0       0 unless (open FH, $local_file) {
568 0         0 $CPAN::Frontend->mywarn("Could not open '$local_file': $!");
569 0         0 return +[];
570             }
571 0         0 local $/;
572 0         0 my $ystream = ;
573 0         0 eval { @yaml = $code->($ystream); };
  0         0  
574 0 0       0 if ($@) {
575             # this shall not be done by the frontend
576 0         0 die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"parse",$@);
577             }
578             }
579 0         0 ${"$yaml_module\::LoadCode"} = $old_loadcode;
  0         0  
580 0         0 return \@yaml;
581             } else {
582             # this shall not be done by the frontend
583 0         0 die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "parse");
584             }
585 0         0 return +[];
586             }
587              
588             # CPAN::_yaml_dumpfile
589             sub _yaml_dumpfile {
590 0     0   0 my($self,$local_file,@what) = @_;
591 0         0 my $yaml_module = _yaml_module;
592 0 0       0 if ($CPAN::META->has_inst($yaml_module)) {
593 0         0 my $code;
594 0 0       0 if (UNIVERSAL::isa($local_file, "FileHandle")) {
    0          
    0          
595 0         0 $code = UNIVERSAL::can($yaml_module, "Dump");
596 0         0 eval { print $local_file $code->(@what) };
  0         0  
597             } elsif ($code = UNIVERSAL::can($yaml_module, "DumpFile")) {
598 0         0 eval { $code->($local_file,@what); };
  0         0  
599             } elsif ($code = UNIVERSAL::can($yaml_module, "Dump")) {
600 0         0 local *FH;
601 0 0       0 open FH, ">$local_file" or die "Could not open '$local_file': $!";
602 0         0 print FH $code->(@what);
603             }
604 0 0       0 if ($@) {
605 0         0 die CPAN::Exception::yaml_process_error->new($yaml_module,$local_file,"dump",$@);
606             }
607             } else {
608 0 0       0 if (UNIVERSAL::isa($local_file, "FileHandle")) {
609             # I think this case does not justify a warning at all
610             } else {
611 0         0 die CPAN::Exception::yaml_not_installed->new($yaml_module, $local_file, "dump");
612             }
613             }
614             }
615              
616             sub _init_sqlite () {
617 0 0   0   0 unless ($CPAN::META->has_inst("CPAN::SQLite")) {
618             $CPAN::Frontend->mywarn(qq{CPAN::SQLite not installed, trying to work without\n})
619 0 0       0 unless $Have_warned->{"CPAN::SQLite"}++;
620 0         0 return;
621             }
622 0         0 require CPAN::SQLite::META; # not needed since CVS version of 2006-12-17
623 0   0     0 $CPAN::SQLite ||= CPAN::SQLite::META->new($CPAN::META);
624             }
625              
626             {
627             my $negative_cache = {};
628             sub _sqlite_running {
629 130 100 66 130   565 if ($negative_cache->{time} && time < $negative_cache->{time} + 60) {
630             # need to cache the result, otherwise too slow
631 129         404 return $negative_cache->{fact};
632             } else {
633 1         5 $negative_cache = {}; # reset
634             }
635 1   33     7 my $ret = $CPAN::Config->{use_sqlite} && ($CPAN::SQLite || _init_sqlite());
636 1 50       5 return $ret if $ret; # fast anyway
637 1         7 $negative_cache->{time} = time;
638 1         6 return $negative_cache->{fact} = $ret;
639             }
640             }
641              
642             $META ||= CPAN->new; # In case we re-eval ourselves we need the ||
643              
644             # from here on only subs.
645             ################################################################################
646              
647             sub _perl_fingerprint {
648 0     0   0 my($self,$other_fingerprint) = @_;
649 0         0 my $dll = eval {OS2::DLLname()};
  0         0  
650 0         0 my $mtime_dll = 0;
651 0 0       0 if (defined $dll) {
652 0 0       0 $mtime_dll = (-f $dll ? (stat(_))[9] : '-1');
653             }
654 0 0       0 my $mtime_perl = (-f CPAN::find_perl ? (stat(_))[9] : '-1');
655             my $this_fingerprint = {
656             '$^X' => CPAN::find_perl,
657             sitearchexp => $Config::Config{sitearchexp},
658 0         0 'mtime_$^X' => $mtime_perl,
659             'mtime_dll' => $mtime_dll,
660             };
661 0 0       0 if ($other_fingerprint) {
662 0 0       0 if (exists $other_fingerprint->{'stat($^X)'}) { # repair fp from rev. 1.88_57
663 0         0 $other_fingerprint->{'mtime_$^X'} = $other_fingerprint->{'stat($^X)'}[9];
664             }
665             # mandatory keys since 1.88_57
666 0         0 for my $key (qw($^X sitearchexp mtime_dll mtime_$^X)) {
667 0 0       0 return unless $other_fingerprint->{$key} eq $this_fingerprint->{$key};
668             }
669 0         0 return 1;
670             } else {
671 0         0 return $this_fingerprint;
672             }
673             }
674              
675             sub suggest_myconfig () {
676 0 0   0 0 0 SUGGEST_MYCONFIG: if(!$INC{'CPAN/MyConfig.pm'}) {
677 0         0 $CPAN::Frontend->myprint("You don't seem to have a user ".
678             "configuration (MyConfig.pm) yet.\n");
679 0         0 my $new = CPAN::Shell::colorable_makemaker_prompt("Do you want to create a ".
680             "user configuration now? (Y/n)",
681             "yes");
682 0 0       0 if($new =~ m{^y}i) {
683 0         0 CPAN::Shell->mkmyconfig();
684 0         0 return &checklock;
685             } else {
686 0         0 $CPAN::Frontend->mydie("OK, giving up.");
687             }
688             }
689             }
690              
691             #-> sub CPAN::all_objects ;
692             sub all_objects {
693 0     0 0 0 my($mgr,$class) = @_;
694 0 0       0 CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
695 0 0       0 CPAN->debug("mgr[$mgr] class[$class]") if $CPAN::DEBUG;
696 0         0 CPAN::Index->reload;
697 0         0 values %{ $META->{readwrite}{$class} }; # unsafe meta access, ok
  0         0  
698             }
699              
700             # Called by shell, not in batch mode. In batch mode I see no risk in
701             # having many processes updating something as installations are
702             # continually checked at runtime. In shell mode I suspect it is
703             # unintentional to open more than one shell at a time
704              
705             #-> sub CPAN::checklock ;
706             sub checklock {
707 0     0 0 0 my($self) = @_;
708 0         0 my $lockfile = File::Spec->catfile($CPAN::Config->{cpan_home},".lock");
709 0 0 0     0 if (-f $lockfile && -M _ > 0) {
710 0 0       0 my $fh = FileHandle->new($lockfile) or
711             $CPAN::Frontend->mydie("Could not open lockfile '$lockfile': $!");
712 0         0 my $otherpid = <$fh>;
713 0         0 my $otherhost = <$fh>;
714 0         0 $fh->close;
715 0 0 0     0 if (defined $otherpid && length $otherpid) {
716 0         0 chomp $otherpid;
717             }
718 0 0 0     0 if (defined $otherhost && length $otherhost) {
719 0         0 chomp $otherhost;
720             }
721 0         0 my $thishost = hostname();
722 0         0 my $ask_if_degraded_wanted = 0;
723 0 0 0     0 if (defined $otherhost && defined $thishost &&
    0 0        
    0 0        
    0 0        
      0        
724             $otherhost ne '' && $thishost ne '' &&
725             $otherhost ne $thishost) {
726 0         0 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Lockfile '$lockfile'\n".
727             "reports other host $otherhost and other ".
728             "process $otherpid.\n".
729             "Cannot proceed.\n"));
730             } elsif ($RUN_DEGRADED) {
731 0         0 $CPAN::Frontend->mywarn("Running in downgraded mode (experimental)\n");
732             } elsif (defined $otherpid && $otherpid) {
733 0 0       0 return if $$ == $otherpid; # should never happen
734 0         0 $CPAN::Frontend->mywarn(
735             qq{
736             There seems to be running another CPAN process (pid $otherpid). Contacting...
737             });
738 0 0 0     0 if (kill 0, $otherpid or $!{EPERM}) {
    0          
739 0         0 $CPAN::Frontend->mywarn(qq{Other job is running.\n});
740 0         0 $ask_if_degraded_wanted = 1;
741             } elsif (-w $lockfile) {
742 0         0 my($ans) =
743             CPAN::Shell::colorable_makemaker_prompt
744             (qq{Other job not responding. Shall I overwrite }.
745             qq{the lockfile '$lockfile'? (Y/n)},"y");
746 0 0       0 $CPAN::Frontend->myexit("Ok, bye\n")
747             unless $ans =~ /^y/i;
748             } else {
749 0         0 Carp::croak(
750             qq{Lockfile '$lockfile' not writable by you. }.
751             qq{Cannot proceed.\n}.
752             qq{ On UNIX try:\n}.
753             qq{ rm '$lockfile'\n}.
754             qq{ and then rerun us.\n}
755             );
756             }
757             } elsif ($^O eq "MSWin32") {
758 0         0 $CPAN::Frontend->mywarn(
759             qq{
760             There seems to be running another CPAN process according to '$lockfile'.
761             });
762 0         0 $ask_if_degraded_wanted = 1;
763             } else {
764 0         0 $CPAN::Frontend->mydie(sprintf("CPAN.pm panic: Found invalid lockfile ".
765             "'$lockfile', please remove. Cannot proceed.\n"));
766             }
767 0 0       0 if ($ask_if_degraded_wanted) {
768 0         0 my($ans) =
769             CPAN::Shell::colorable_makemaker_prompt
770             (qq{Shall I try to run in downgraded }.
771             qq{mode? (Y/n)},"y");
772 0 0       0 if ($ans =~ /^y/i) {
773 0         0 $CPAN::Frontend->mywarn("Running in downgraded mode (experimental).
774             Please report if something unexpected happens\n");
775 0         0 $RUN_DEGRADED = 1;
776 0         0 for ($CPAN::Config) {
777             # XXX
778             # $_->{build_dir_reuse} = 0; # 2006-11-17 akoenig Why was that?
779 0         0 $_->{commandnumber_in_prompt} = 0; # visibility
780 0         0 $_->{histfile} = ""; # who should win otherwise?
781 0         0 $_->{cache_metadata} = 0; # better would be a lock?
782 0         0 $_->{use_sqlite} = 0; # better would be a write lock!
783 0         0 $_->{auto_commit} = 0; # we are violent, do not persist
784 0         0 $_->{test_report} = 0; # Oliver Paukstadt had sent wrong reports in degraded mode
785             }
786             } else {
787 0         0 my $msg = "You may want to kill the other job and delete the lockfile.";
788 0 0       0 if (defined $otherpid) {
789 0         0 $msg .= " Something like:
790             kill $otherpid
791             rm $lockfile
792             ";
793             }
794 0         0 $CPAN::Frontend->mydie("\n$msg");
795             }
796             }
797             }
798 0         0 my $dotcpan = $CPAN::Config->{cpan_home};
799 0         0 eval { File::Path::mkpath($dotcpan);};
  0         0  
800 0 0       0 if ($@) {
801             # A special case at least for Jarkko.
802 0         0 my $firsterror = $@;
803 0         0 my $seconderror;
804             my $symlinkcpan;
805 0 0       0 if (-l $dotcpan) {
806 0         0 $symlinkcpan = readlink $dotcpan;
807 0 0       0 die "readlink $dotcpan failed: $!" unless defined $symlinkcpan;
808 0         0 eval { File::Path::mkpath($symlinkcpan); };
  0         0  
809 0 0       0 if ($@) {
810 0         0 $seconderror = $@;
811             } else {
812 0         0 $CPAN::Frontend->mywarn(qq{
813             Working directory $symlinkcpan created.
814             });
815             }
816             }
817 0 0       0 unless (-d $dotcpan) {
818 0         0 my $mess = qq{
819             Your configuration suggests "$dotcpan" as your
820             CPAN.pm working directory. I could not create this directory due
821             to this error: $firsterror\n};
822 0 0       0 $mess .= qq{
823             As "$dotcpan" is a symlink to "$symlinkcpan",
824             I tried to create that, but I failed with this error: $seconderror
825             } if $seconderror;
826 0         0 $mess .= qq{
827             Please make sure the directory exists and is writable.
828             };
829 0         0 $CPAN::Frontend->mywarn($mess);
830 0         0 return suggest_myconfig;
831             }
832             } # $@ after eval mkpath $dotcpan
833 0         0 if (0) { # to test what happens when a race condition occurs
834             for (reverse 1..10) {
835             print $_, "\n";
836             sleep 1;
837             }
838             }
839             # locking
840 0 0 0     0 if (!$RUN_DEGRADED && !$self->{LOCKFH}) {
841 0         0 my $fh;
842 0 0       0 unless ($fh = FileHandle->new("+>>$lockfile")) {
843 0         0 $CPAN::Frontend->mywarn(qq{
844              
845             Your configuration suggests that CPAN.pm should use a working
846             directory of
847             $CPAN::Config->{cpan_home}
848             Unfortunately we could not create the lock file
849             $lockfile
850             due to '$!'.
851              
852             Please make sure that the configuration variable
853             \$CPAN::Config->{cpan_home}
854             points to a directory where you can write a .lock file. You can set
855             this variable in either a CPAN/MyConfig.pm or a CPAN/Config.pm in your
856             \@INC path;
857             });
858 0         0 return suggest_myconfig;
859             }
860 0         0 my $sleep = 1;
861 0         0 while (!CPAN::_flock($fh, LOCK_EX|LOCK_NB)) {
862 0   0     0 my $err = $! || "unknown error";
863 0 0       0 if ($sleep>3) {
864 0         0 $CPAN::Frontend->mydie("Could not lock '$lockfile' with flock: $err; giving up\n");
865             }
866 0         0 $CPAN::Frontend->mysleep($sleep+=0.1);
867 0         0 $CPAN::Frontend->mywarn("Could not lock '$lockfile' with flock: $err; retrying\n");
868             }
869              
870 0         0 seek $fh, 0, 0;
871 0         0 truncate $fh, 0;
872 0         0 $fh->autoflush(1);
873 0         0 $fh->print($$, "\n");
874 0         0 $fh->print(hostname(), "\n");
875 0         0 $self->{LOCK} = $lockfile;
876 0         0 $self->{LOCKFH} = $fh;
877             }
878             $SIG{TERM} = sub {
879 0     0   0 my $sig = shift;
880 0         0 &cleanup;
881 0         0 $CPAN::Frontend->mydie("Got SIG$sig, leaving");
882 0         0 };
883             $SIG{INT} = sub {
884             # no blocks!!!
885 0     0   0 my $sig = shift;
886 0 0       0 &cleanup if $Signal;
887 0 0       0 die "Got yet another signal" if $Signal > 1;
888 0 0       0 $CPAN::Frontend->mydie("Got another SIG$sig") if $Signal;
889 0         0 $CPAN::Frontend->mywarn("Caught SIG$sig, trying to continue\n");
890 0         0 $Signal++;
891 0         0 };
892              
893             # From: Larry Wall
894             # Subject: Re: deprecating SIGDIE
895             # To: perl5-porters@perl.org
896             # Date: Thu, 30 Sep 1999 14:58:40 -0700 (PDT)
897             #
898             # The original intent of __DIE__ was only to allow you to substitute one
899             # kind of death for another on an application-wide basis without respect
900             # to whether you were in an eval or not. As a global backstop, it should
901             # not be used any more lightly (or any more heavily :-) than class
902             # UNIVERSAL. Any attempt to build a general exception model on it should
903             # be politely squashed. Any bug that causes every eval {} to have to be
904             # modified should be not so politely squashed.
905             #
906             # Those are my current opinions. It is also my opinion that polite
907             # arguments degenerate to personal arguments far too frequently, and that
908             # when they do, it's because both people wanted it to, or at least didn't
909             # sufficiently want it not to.
910             #
911             # Larry
912              
913             # global backstop to cleanup if we should really die
914 0         0 $SIG{__DIE__} = \&cleanup;
915 0 0       0 $self->debug("Signal handler set.") if $CPAN::DEBUG;
916             }
917              
918             #-> sub CPAN::DESTROY ;
919             sub DESTROY {
920 0     0   0 &cleanup; # need an eval?
921             }
922              
923             #-> sub CPAN::anycwd ;
924             sub anycwd () {
925 12     12 1 29 my $getcwd;
926 12   100     74 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
927 12         79 CPAN->$getcwd();
928             }
929              
930             #-> sub CPAN::cwd ;
931 12     12 1 48425 sub cwd {Cwd::cwd();}
932              
933             #-> sub CPAN::getcwd ;
934 0     0 1 0 sub getcwd {Cwd::getcwd();}
935              
936             #-> sub CPAN::fastcwd ;
937 0     0 1 0 sub fastcwd {Cwd::fastcwd();}
938              
939             #-> sub CPAN::getdcwd ;
940 0     0 1 0 sub getdcwd {Cwd::getdcwd();}
941              
942             #-> sub CPAN::backtickcwd ;
943 0     0 1 0 sub backtickcwd {my $cwd = `cwd`; chomp $cwd; $cwd}
  0         0  
  0         0  
944              
945             # Adapted from Probe::Perl
946             #-> sub CPAN::_perl_is_same
947             sub _perl_is_same {
948 0     0   0 my ($perl) = @_;
949 0   0     0 return MM->maybe_command($perl)
950             && `$perl -MConfig=myconfig -e print -e myconfig` eq Config->myconfig;
951             }
952              
953             # Adapted in part from Probe::Perl
954             #-> sub CPAN::find_perl ;
955             sub find_perl () {
956 12 50   12 0 779 if ( File::Spec->file_name_is_absolute($^X) ) {
957 12         199 return $^X;
958             }
959             else {
960 0         0 my $exe = $Config::Config{exe_ext};
961             my @candidates = (
962             File::Spec->catfile($CPAN::iCwd,$^X),
963 0         0 $Config::Config{'perlpath'},
964             );
965 0         0 for my $perl_name ($^X, 'perl', 'perl5', "perl$]") {
966 0         0 for my $path (File::Spec->path(), $Config::Config{'binexp'}) {
967 0 0 0     0 if ( defined($path) && length $path && -d $path ) {
      0        
968 0         0 my $perl = File::Spec->catfile($path,$perl_name);
969 0         0 push @candidates, $perl;
970             # try with extension if not provided already
971 0 0 0     0 if ($^O eq 'VMS') {
    0          
972             # VMS might have a file version at the end
973 0 0       0 push @candidates, $perl . $exe
974             unless $perl =~ m/$exe(;\d+)?$/i;
975             } elsif (defined $exe && length $exe) {
976 0 0       0 push @candidates, $perl . $exe
977             unless $perl =~ m/$exe$/i;
978             }
979             }
980             }
981             }
982 0         0 for my $perl ( @candidates ) {
983 0 0 0     0 if (MM->maybe_command($perl) && _perl_is_same($perl)) {
984 0         0 $^X = $perl;
985 0         0 return $perl;
986             }
987             }
988             }
989 0         0 return $^X; # default fall back
990             }
991              
992             #-> sub CPAN::exists ;
993             sub exists {
994 31     31 0 90 my($mgr,$class,$id) = @_;
995 31 50       85 CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
996 31         125 CPAN::Index->reload;
997             ### Carp::croak "exists called without class argument" unless $class;
998 31   50     73 $id ||= "";
999 31 100       132 $id =~ s/:+/::/g if $class eq "CPAN::Module";
1000 31         45 my $exists;
1001 31 50       62 if (CPAN::_sqlite_running) {
1002 0   0     0 $exists = (exists $META->{readonly}{$class}{$id} or
1003             $CPAN::SQLite->set($class, $id));
1004             } else {
1005 31         97 $exists = exists $META->{readonly}{$class}{$id};
1006             }
1007 31   66     188 $exists ||= exists $META->{readwrite}{$class}{$id}; # unsafe meta access, ok
1008             }
1009              
1010             #-> sub CPAN::delete ;
1011             sub delete {
1012 0     0 0 0 my($mgr,$class,$id) = @_;
1013 0         0 delete $META->{readonly}{$class}{$id}; # unsafe meta access, ok
1014 0         0 delete $META->{readwrite}{$class}{$id}; # unsafe meta access, ok
1015             }
1016              
1017             #-> sub CPAN::has_usable
1018             # has_inst is sometimes too optimistic, we should replace it with this
1019             # has_usable whenever a case is given
1020             sub has_usable {
1021 115     115 1 314 my($self,$mod,$message) = @_;
1022 115 100       504 return 1 if $HAS_USABLE->{$mod};
1023 6         37 my $has_inst = $self->has_inst($mod,$message);
1024 6 100       35 return unless $has_inst;
1025 3         7 my $usable;
1026             $usable = {
1027              
1028             #
1029             # these subroutines die if they believe the installed version is unusable;
1030             #
1031             'CPAN::Meta' => [
1032             sub {
1033 1     1   6 require CPAN::Meta;
1034 1 50       24 unless (CPAN::Version->vge(CPAN::Meta->VERSION, 2.110350)) {
1035 0         0 for ("Will not use CPAN::Meta, need version 2.110350\n") {
1036 0         0 $CPAN::Frontend->mywarn($_);
1037 0         0 die $_;
1038             }
1039             }
1040             },
1041             ],
1042              
1043             'CPAN::Meta::Requirements' => [
1044             sub {
1045 0 0 0 0   0 if (defined $CPAN::Meta::Requirements::VERSION
1046             && CPAN::Version->vlt($CPAN::Meta::Requirements::VERSION, "2.120920")
1047             ) {
1048 0         0 delete $INC{"CPAN/Meta/Requirements.pm"};
1049             }
1050 0         0 require CPAN::Meta::Requirements;
1051 0 0       0 unless (CPAN::Version->vge(CPAN::Meta::Requirements->VERSION, 2.120920)) {
1052 0         0 for ("Will not use CPAN::Meta::Requirements, need version 2.120920\n") {
1053 0         0 $CPAN::Frontend->mywarn($_);
1054 0         0 die $_;
1055             }
1056             }
1057             },
1058             ],
1059              
1060             LWP => [ # we frequently had "Can't locate object
1061             # method "new" via package "LWP::UserAgent" at
1062             # (eval 69) line 2006
1063 0     0   0 sub {require LWP},
1064 0     0   0 sub {require LWP::UserAgent},
1065 0     0   0 sub {require HTTP::Request},
1066 0     0   0 sub {require URI::URL;
1067 0 0       0 unless (CPAN::Version->vge(URI::URL::->VERSION,0.08)) {
1068 0         0 for ("Will not use URI::URL, need 0.08\n") {
1069 0         0 $CPAN::Frontend->mywarn($_);
1070 0         0 die $_;
1071             }
1072             }
1073             },
1074             ],
1075             'Net::FTP' => [
1076             sub {
1077 0   0 0   0 my $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy};
1078 0 0 0     0 if ($var and $var =~ /^http:/i) {
1079             # rt #110833
1080 0         0 for ("Net::FTP cannot handle http proxy") {
1081 0         0 $CPAN::Frontend->mywarn($_);
1082 0         0 die $_;
1083             }
1084             }
1085             },
1086 0     0   0 sub {require Net::FTP},
1087 0     0   0 sub {require Net::Config},
1088             ],
1089             'HTTP::Tiny' => [
1090             sub {
1091 0     0   0 require HTTP::Tiny;
1092 0 0       0 unless (CPAN::Version->vge(HTTP::Tiny->VERSION, 0.005)) {
1093 0         0 for ("Will not use HTTP::Tiny, need version 0.005\n") {
1094 0         0 $CPAN::Frontend->mywarn($_);
1095 0         0 die $_;
1096             }
1097             }
1098             },
1099             ],
1100             'File::HomeDir' => [
1101 0     0   0 sub {require File::HomeDir;
1102 0 0       0 unless (CPAN::Version->vge(File::HomeDir::->VERSION, 0.52)) {
1103 0         0 for ("Will not use File::HomeDir, need 0.52\n") {
1104 0         0 $CPAN::Frontend->mywarn($_);
1105 0         0 die $_;
1106             }
1107             }
1108             },
1109             ],
1110             'Archive::Tar' => [
1111 1     1   11 sub {require Archive::Tar;
1112 1         3 my $demand = "1.50";
1113 1 50       24 unless (CPAN::Version->vge(Archive::Tar::->VERSION, $demand)) {
1114 0         0 my $atv = Archive::Tar->VERSION;
1115 0         0 for ("You have Archive::Tar $atv, but $demand or later is recommended. Please upgrade.\n") {
1116 0         0 $CPAN::Frontend->mywarn($_);
1117             # don't die, because we may need
1118             # Archive::Tar to upgrade
1119             }
1120              
1121             }
1122             },
1123             ],
1124             'File::Temp' => [
1125             # XXX we should probably delete from
1126             # %INC too so we can load after we
1127             # installed a new enough version --
1128             # I'm not sure.
1129 0     0   0 sub {require File::Temp;
1130 0 0       0 unless (CPAN::Version->vge(File::Temp::->VERSION,0.16)) {
1131 0         0 for ("Will not use File::Temp, need 0.16\n") {
1132 0         0 $CPAN::Frontend->mywarn($_);
1133 0         0 die $_;
1134             }
1135             }
1136             },
1137 3         137 ]
1138             };
1139 3 100       17 if ($usable->{$mod}) {
1140 2         14 local @INC = @INC;
1141 2 50       9 pop @INC if $INC[-1] eq '.';
1142 2         4 for my $c (0..$#{$usable->{$mod}}) {
  2         13  
1143 2         5 my $code = $usable->{$mod}[$c];
1144 2         6 my $ret = eval { &$code() };
  2         6  
1145 2 50       6 $ret = "" unless defined $ret;
1146 2 50       10 if ($@) {
1147             # warn "DEBUG: c[$c]\$\@[$@]ret[$ret]";
1148 0         0 return;
1149             }
1150             }
1151             }
1152 3         139 return $HAS_USABLE->{$mod} = 1;
1153             }
1154              
1155             sub frontend {
1156 0     0 1 0 shift;
1157 0 0       0 $CPAN::Frontend = shift if @_;
1158 0         0 $CPAN::Frontend;
1159             }
1160              
1161             sub use_inst {
1162 8     8 1 30 my ($self, $module) = @_;
1163              
1164 8 50       41 unless ($self->has_inst($module)) {
1165 0         0 $self->frontend->mydie("$module not installed, cannot continue");
1166             }
1167             }
1168              
1169             #-> sub CPAN::has_inst
1170             sub has_inst {
1171 50     50 1 2446 my($self,$mod,$message) = @_;
1172 50 50       166 Carp::croak("CPAN->has_inst() called without an argument")
1173             unless defined $mod;
1174 15 100       34 my %dont = map { $_ => 1 } keys %{$CPAN::META->{dontload_hash}||{}},
  50         458  
1175 50 50       285 keys %{$CPAN::Config->{dontload_hash}||{}},
1176 50 50       93 @{$CPAN::Config->{dontload_list}||[]};
  50         269  
1177 50 100 66     350 if (defined $message && $message eq "no" # as far as I remember only used by Nox
      100        
1178             ||
1179             $dont{$mod}
1180             ) {
1181 9   100     39 $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok
1182 9         27 return 0;
1183             }
1184 41         388 local @INC = @INC;
1185 41 50       147 pop @INC if $INC[-1] eq '.';
1186 41         120 my $file = $mod;
1187 41         81 my $obj;
1188 41         583 $file =~ s|::|/|g;
1189 41         145 $file .= ".pm";
1190 41 100       166 if ($INC{$file}) {
    100          
    50          
    50          
    50          
1191             # checking %INC is wrong, because $INC{LWP} may be true
1192             # although $INC{"URI/URL.pm"} may have failed. But as
1193             # I really want to say "blah loaded OK", I have to somehow
1194             # cache results.
1195             ### warn "$file in %INC"; #debug
1196 25         170 return 1;
1197 16         8042 } elsif (eval { require $file }) {
1198             # eval is good: if we haven't yet read the database it's
1199             # perfect and if we have installed the module in the meantime,
1200             # it tries again. The second require is only a NOOP returning
1201             # 1 if we had success, otherwise it's retrying
1202              
1203 6         236244 my $mtime = (stat $INC{$file})[9];
1204             # privileged files loaded by has_inst; Note: we use $mtime
1205             # as a proxy for a checksum.
1206 6         44 $CPAN::Shell::reload->{$file} = $mtime;
1207 6         1613 my $v = eval "\$$mod\::VERSION";
1208 6 50       58 $v = $v ? " (v$v)" : "";
1209 6         124 CPAN::Shell->optprint("load_module","CPAN: $mod loaded ok$v\n");
1210 6 50       100 if ($mod eq "CPAN::WAIT") {
1211 0         0 push @CPAN::Shell::ISA, 'CPAN::WAIT';
1212             }
1213 6         91 return 1;
1214             } elsif ($mod eq "Net::FTP") {
1215             $CPAN::Frontend->mywarn(qq{
1216             Please, install Net::FTP as soon as possible. CPAN.pm installs it for you
1217             if you just type
1218             install Bundle::libnet
1219              
1220 0 0       0 }) unless $Have_warned->{"Net::FTP"}++;
1221 0         0 $CPAN::Frontend->mysleep(3);
1222             } elsif ($mod eq "Digest::SHA") {
1223 0 0       0 if ($Have_warned->{"Digest::SHA"}++) {
1224 0         0 $CPAN::Frontend->mywarn(qq{CPAN: checksum security checks disabled }.
1225             qq{because Digest::SHA not installed.\n});
1226             } else {
1227 0         0 $CPAN::Frontend->mywarn(qq{
1228             CPAN: checksum security checks disabled because Digest::SHA not installed.
1229             Please consider installing the Digest::SHA module.
1230              
1231             });
1232 0         0 $CPAN::Frontend->mysleep(2);
1233             }
1234             } elsif ($mod eq "Module::Signature") {
1235             # NOT prefs_lookup, we are not a distro
1236 0         0 my $check_sigs = $CPAN::Config->{check_sigs};
1237 0 0       0 if (not $check_sigs) {
    0          
1238             # they do not want us:-(
1239             } elsif (not $Have_warned->{"Module::Signature"}++) {
1240             # No point in complaining unless the user can
1241             # reasonably install and use it.
1242 0 0 0     0 if (eval { require Crypt::OpenPGP; 1 } ||
  0   0     0  
  0         0  
1243             (
1244             defined $CPAN::Config->{'gpg'}
1245             &&
1246             $CPAN::Config->{'gpg'} =~ /\S/
1247             )
1248             ) {
1249 0         0 $CPAN::Frontend->mywarn(qq{
1250             CPAN: Module::Signature security checks disabled because Module::Signature
1251             not installed. Please consider installing the Module::Signature module.
1252             You may also need to be able to connect over the Internet to the public
1253             key servers like pool.sks-keyservers.net or pgp.mit.edu.
1254              
1255             });
1256 0         0 $CPAN::Frontend->mysleep(2);
1257             }
1258             }
1259             } else {
1260 10         36 delete $INC{$file}; # if it inc'd LWP but failed during, say, URI
1261             }
1262 10         85 return 0;
1263             }
1264              
1265             #-> sub CPAN::instance ;
1266             sub instance {
1267 46     46 1 146 my($mgr,$class,$id) = @_;
1268 46         207 CPAN::Index->reload;
1269 46   50     132 $id ||= "";
1270             # unsafe meta access, ok?
1271 46 100       214 return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id};
1272 41   33     370 $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id);
1273             }
1274              
1275             #-> sub CPAN::new ;
1276             sub new {
1277 12     12 0 568 bless {}, shift;
1278             }
1279              
1280             #-> sub CPAN::_exit_messages ;
1281             sub _exit_messages {
1282 0     0   0 my ($self) = @_;
1283 0   0     0 $self->{exit_messages} ||= [];
1284             }
1285              
1286             #-> sub CPAN::cleanup ;
1287             sub cleanup {
1288             # warn "cleanup called with arg[@_] End[$CPAN::End] Signal[$Signal]";
1289 12     12 0 133 local $SIG{__DIE__} = '';
1290 12         55 my($message) = @_;
1291 12         42 my $i = 0;
1292 12         36 my $ineval = 0;
1293 12         32 my($subroutine);
1294 12         146 while ((undef,undef,undef,$subroutine) = caller(++$i)) {
1295 24 100       172 $ineval = 1, last if
1296             $subroutine eq '(eval)';
1297             }
1298 12 50 33     151 return if $ineval && !$CPAN::End;
1299 12 50       517 return unless defined $META->{LOCK};
1300 0 0         return unless -f $META->{LOCK};
1301 0           $META->savehist;
1302 0   0       $META->{cachemgr} ||= CPAN::CacheMgr->new('atexit');
1303 0           close $META->{LOCKFH};
1304 0           unlink $META->{LOCK};
1305             # require Carp;
1306             # Carp::cluck("DEBUGGING");
1307 0 0         if ( $CPAN::CONFIG_DIRTY ) {
1308 0           $CPAN::Frontend->mywarn("Warning: Configuration not saved.\n");
1309             }
1310 0           $CPAN::Frontend->myprint("Lockfile removed.\n");
1311 0           for my $msg ( @{ $META->_exit_messages } ) {
  0            
1312 0           $CPAN::Frontend->myprint($msg);
1313             }
1314             }
1315              
1316             #-> sub CPAN::readhist
1317             sub readhist {
1318 0     0 0   my($self,$term,$histfile) = @_;
1319 0   0       my $histsize = $CPAN::Config->{'histsize'} || 100;
1320 0 0         $term->Attribs->{'MaxHistorySize'} = $histsize if (defined($term->Attribs->{'MaxHistorySize'}));
1321 0           my($fh) = FileHandle->new;
1322 0 0         open $fh, "<$histfile" or return;
1323 0           local $/ = "\n";
1324 0           while (<$fh>) {
1325 0           chomp;
1326 0           $term->AddHistory($_);
1327             }
1328 0           close $fh;
1329             }
1330              
1331             #-> sub CPAN::savehist
1332             sub savehist {
1333 0     0 0   my($self) = @_;
1334 0           my($histfile,$histsize);
1335 0 0         unless ($histfile = $CPAN::Config->{'histfile'}) {
1336 0           $CPAN::Frontend->mywarn("No history written (no histfile specified).\n");
1337 0           return;
1338             }
1339 0   0       $histsize = $CPAN::Config->{'histsize'} || 100;
1340 0 0         if ($CPAN::term) {
1341 0 0         unless ($CPAN::term->can("GetHistory")) {
1342 0           $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n");
1343 0           return;
1344             }
1345             } else {
1346 0           return;
1347             }
1348 0           my @h = $CPAN::term->GetHistory;
1349 0 0         splice @h, 0, @h-$histsize if @h>$histsize;
1350 0           my($fh) = FileHandle->new;
1351 0 0         open $fh, ">$histfile" or $CPAN::Frontend->mydie("Couldn't open >$histfile: $!");
1352 0           local $\ = local $, = "\n";
1353 0           print $fh @h;
1354 0           close $fh;
1355             }
1356              
1357             #-> sub CPAN::is_tested
1358             sub is_tested {
1359 0     0 1   my($self,$what,$when) = @_;
1360 0 0         unless ($what) {
1361 0           Carp::cluck("DEBUG: empty what");
1362 0           return;
1363             }
1364 0           $self->{is_tested}{$what} = $when;
1365             }
1366              
1367             #-> sub CPAN::reset_tested
1368             # forget all distributions tested -- resets what gets included in PERL5LIB
1369             sub reset_tested {
1370 0     0 0   my ($self) = @_;
1371 0           $self->{is_tested} = {};
1372             }
1373              
1374             #-> sub CPAN::is_installed
1375             # unsets the is_tested flag: as soon as the thing is installed, it is
1376             # not needed in set_perl5lib anymore
1377             sub is_installed {
1378 0     0 0   my($self,$what) = @_;
1379 0           delete $self->{is_tested}{$what};
1380             }
1381              
1382             sub _list_sorted_descending_is_tested {
1383 0     0     my($self) = @_;
1384 0           my $foul = 0;
1385             my @sorted = sort
1386 0   0       { ($self->{is_tested}{$b}||0) <=> ($self->{is_tested}{$a}||0) }
      0        
1387             grep
1388 0 0         { if ($foul){ 0 } elsif (-e) { 1 } else { $foul = $_; 0 } }
  0 0          
  0            
  0            
  0            
1389 0           keys %{$self->{is_tested}};
  0            
1390 0 0         if ($foul) {
1391 0           $CPAN::Frontend->mywarn("Lost build_dir detected ($foul), giving up all cached test results of currently running session.\n");
1392 0           for my $dbd (sort keys %{$self->{is_tested}}) { # distro-build-dir
  0            
1393 0           SEARCH: for my $d (sort { $a->id cmp $b->id } $CPAN::META->all_objects("CPAN::Distribution")) {
  0            
1394 0 0 0       if ($d->{build_dir} && $d->{build_dir} eq $dbd) {
1395 0           $CPAN::Frontend->mywarn(sprintf "Flushing cache for %s\n", $d->pretty_id);
1396 0           $d->fforce("");
1397 0           last SEARCH;
1398             }
1399             }
1400 0           delete $self->{is_tested}{$dbd};
1401             }
1402 0           return ();
1403             } else {
1404 0           return @sorted;
1405             }
1406             }
1407              
1408             #-> sub CPAN::set_perl5lib
1409             # Notes on max environment variable length:
1410             # - Win32 : XP or later, 8191; Win2000 or NT4, 2047
1411             {
1412             my $fh;
1413             sub set_perl5lib {
1414 0     0 0   my($self,$for) = @_;
1415 0 0         unless ($for) {
1416 0           (undef,undef,undef,$for) = caller(1);
1417 0           $for =~ s/.*://;
1418             }
1419 0   0       $self->{is_tested} ||= {};
1420 0 0         return unless %{$self->{is_tested}};
  0            
1421 0           my $env = $ENV{PERL5LIB};
1422 0 0         $env = $ENV{PERLLIB} unless defined $env;
1423 0           my @env;
1424 0 0 0       push @env, split /\Q$Config::Config{path_sep}\E/, $env if defined $env and length $env;
1425             #my @dirs = map {("$_/blib/arch", "$_/blib/lib")} keys %{$self->{is_tested}};
1426             #$CPAN::Frontend->myprint("Prepending @dirs to PERL5LIB.\n");
1427              
1428 0           my @dirs = map {("$_/blib/arch", "$_/blib/lib")} $self->_list_sorted_descending_is_tested;
  0            
1429 0 0         return if !@dirs;
1430              
1431 0 0         if (@dirs < 12) {
    0          
1432 0           $CPAN::Frontend->optprint('perl5lib', "Prepending @dirs to PERL5LIB for '$for'\n");
1433 0           $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env;
1434             } elsif (@dirs < 24 ) {
1435 0           my @d = map {my $cp = $_;
  0            
1436 0           $cp =~ s/^\Q$CPAN::Config->{build_dir}\E/%BUILDDIR%/;
1437 0           $cp
1438             } @dirs;
1439 0           $CPAN::Frontend->optprint('perl5lib', "Prepending @d to PERL5LIB; ".
1440             "%BUILDDIR%=$CPAN::Config->{build_dir} ".
1441             "for '$for'\n"
1442             );
1443 0           $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env;
1444             } else {
1445 0           my $cnt = keys %{$self->{is_tested}};
  0            
1446 0           $CPAN::Frontend->optprint('perl5lib', "Prepending blib/arch and blib/lib of ".
1447             "$cnt build dirs to PERL5LIB; ".
1448             "for '$for'\n"
1449             );
1450 0           $ENV{PERL5LIB} = join $Config::Config{path_sep}, @dirs, @env;
1451             }
1452             }}
1453              
1454              
1455             1;
1456              
1457              
1458             __END__