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   92787 use strict;
  12         64  
  12         949  
4             package CPAN;
5             $CPAN::VERSION = '2.19';
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   110 use File::Spec ();
  12         32  
  12         1314  
11             BEGIN {
12 12 50   12   290 if (File::Spec->can("rel2abs")) {
13 12         47 for my $inc (@INC) {
14 135 50       1652 $inc = File::Spec->rel2abs($inc) unless ref $inc;
15             }
16             }
17 12 50       779 $SIG{WINCH} = 'IGNORE' if exists $SIG{WINCH};
18             }
19 12     12   4464 use CPAN::Author;
  12         41  
  12         496  
20 12     12   5753 use CPAN::HandleConfig;
  12         50  
  12         529  
21 12     12   4756 use CPAN::Version;
  12         36  
  12         414  
22 12     12   4229 use CPAN::Bundle;
  12         54  
  12         512  
23 12     12   5447 use CPAN::CacheMgr;
  12         37  
  12         462  
24 12     12   4309 use CPAN::Complete;
  12         37  
  12         448  
25 12     12   91 use CPAN::Debug;
  12         24  
  12         347  
26 12     12   9447 use CPAN::Distribution;
  12         48  
  12         637  
27 12     12   5404 use CPAN::Distrostatus;
  12         41  
  12         397  
28 12     12   5254 use CPAN::FTP;
  12         48  
  12         585  
29 12     12   5977 use CPAN::Index 1.93; # https://rt.cpan.org/Ticket/Display.html?id=43349
  12         337  
  12         479  
30 12     12   111 use CPAN::InfoObj;
  12         28  
  12         305  
31 12     12   70 use CPAN::Module;
  12         28  
  12         273  
32 12     12   4576 use CPAN::Prompt;
  12         35  
  12         396  
33 12     12   3649 use CPAN::URL;
  12         33  
  12         341  
34 12     12   3428 use CPAN::Queue;
  12         37  
  12         455  
35 12     12   4680 use CPAN::Tarzip;
  12         56  
  12         667  
36 12     12   4554 use CPAN::DeferredCode;
  12         31  
  12         364  
37 12     12   5861 use CPAN::Shell;
  12         49  
  12         594  
38 12     12   5402 use CPAN::LWP::UserAgent;
  12         30  
  12         388  
39 12     12   4198 use CPAN::Exception::RecursiveDependency;
  12         33  
  12         454  
40 12     12   4163 use CPAN::Exception::yaml_not_installed;
  12         30  
  12         412  
41 12     12   3964 use CPAN::Exception::yaml_process_error;
  12         37  
  12         402  
42              
43 12     12   90 use Carp ();
  12         31  
  12         253  
44 12     12   73 use Config ();
  12         28  
  12         294  
45 12     12   79 use Cwd qw(chdir);
  12         40  
  12         817  
46 12     12   90 use DirHandle ();
  12         29  
  12         235  
47 12     12   72 use Exporter ();
  12         24  
  12         355  
48 12     12   6896 use ExtUtils::MakeMaker qw(prompt); # for some unknown reason,
  12         1220794  
  12         1052  
49             # 5.005_04 does not work without
50             # this
51 12     12   118 use File::Basename ();
  12         31  
  12         292  
52 12     12   3336 use File::Copy ();
  12         22730  
  12         369  
53 12     12   92 use File::Find;
  12         29  
  12         834  
54 12     12   87 use File::Path ();
  12         32  
  12         240  
55 12     12   3625 use FileHandle ();
  12         78827  
  12         484  
56 12     12   97 use Fcntl qw(:flock);
  12         31  
  12         1715  
57 12     12   5929 use Safe ();
  12         430868  
  12         900  
58 12     12   4536 use Sys::Hostname qw(hostname);
  12         12696  
  12         802  
59 12     12   3504 use Text::ParseWords ();
  12         15297  
  12         383  
60 12     12   3683 use Text::Wrap ();
  12         29740  
  12         671  
61              
62             # protect against "called too early"
63             sub find_perl ();
64             sub anycwd ();
65             sub _uniq;
66              
67 12     12   3548 no lib ".";
  12         7520  
  12         88  
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   19201 END { $CPAN::End++; &cleanup; }
  12         70  
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         18150 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   5922 );
  12         39  
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   20 $autoload_recursion++;
184 1         5 my($l) = $AUTOLOAD;
185 1         12 $l =~ s/.*:://;
186 1 50       8 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       7 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         45 @export{@EXPORT} = '';
199 1 50       30 CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
200 1 50       7 if (exists $export{$l}) {
201 0         0 CPAN::Shell->$l(@_);
202             } else {
203 1         17 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   112 use strict;
  12         32  
  12         407  
358 12     12   83 use vars qw($import_done);
  12         31  
  12         16190  
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   29 my $yaml_module = $CPAN::Config->{yaml_module} || "YAML";
521 3 50 33     18 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     30 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         15 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   106 no strict 'refs';
  12         29  
  12         48732  
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   560 if ($negative_cache->{time} && time < $negative_cache->{time} + 60) {
630             # need to cache the result, otherwise too slow
631 129         406 return $negative_cache->{fact};
632             } else {
633 1         4 $negative_cache = {}; # reset
634             }
635 1   33     8 my $ret = $CPAN::Config->{use_sqlite} && ($CPAN::SQLite || _init_sqlite());
636 1 50       5 return $ret if $ret; # fast anyway
637 1         9 $negative_cache->{time} = time;
638 1         8 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 30 my $getcwd;
926 12   100     77 $getcwd = $CPAN::Config->{'getcwd'} || 'cwd';
927 12         97 CPAN->$getcwd();
928             }
929              
930             #-> sub CPAN::cwd ;
931 12     12 1 81988 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 1037 if ( File::Spec->file_name_is_absolute($^X) ) {
957 12         162 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 88 my($mgr,$class,$id) = @_;
995 31 50       101 CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
996 31         139 CPAN::Index->reload;
997             ### Carp::croak "exists called without class argument" unless $class;
998 31   50     86 $id ||= "";
999 31 100       104 $id =~ s/:+/::/g if $class eq "CPAN::Module";
1000 31         60 my $exists;
1001 31 50       76 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         100 $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 266 my($self,$mod,$message) = @_;
1022 115 100       482 return 1 if $HAS_USABLE->{$mod};
1023 6         51 my $has_inst = $self->has_inst($mod,$message);
1024 6 100       36 return unless $has_inst;
1025 3         8 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       23 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   8 sub {require Archive::Tar;
1112 1         2 my $demand = "1.50";
1113 1 50       26 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         128 ]
1138             };
1139 3 100       16 if ($usable->{$mod}) {
1140 2         13 local @INC = @INC;
1141 2 50       8 pop @INC if $INC[-1] eq '.';
1142 2         3 for my $c (0..$#{$usable->{$mod}}) {
  2         10  
1143 2         5 my $code = $usable->{$mod}[$c];
1144 2         3 my $ret = eval { &$code() };
  2         7  
1145 2 50       6 $ret = "" unless defined $ret;
1146 2 50       11 if ($@) {
1147             # warn "DEBUG: c[$c]\$\@[$@]ret[$ret]";
1148 0         0 return;
1149             }
1150             }
1151             }
1152 3         137 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 23 my ($self, $module) = @_;
1163              
1164 8 50       33 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 2932 my($self,$mod,$message) = @_;
1172 50 50       157 Carp::croak("CPAN->has_inst() called without an argument")
1173             unless defined $mod;
1174 15 100       33 my %dont = map { $_ => 1 } keys %{$CPAN::META->{dontload_hash}||{}},
  50         375  
1175 50 50       442 keys %{$CPAN::Config->{dontload_hash}||{}},
1176 50 50       98 @{$CPAN::Config->{dontload_list}||[]};
  50         282  
1177 50 100 66     357 if (defined $message && $message eq "no" # as far as I remember only used by Nox
      100        
1178             ||
1179             $dont{$mod}
1180             ) {
1181 9   100     37 $CPAN::META->{dontload_hash}{$mod}||=1; # unsafe meta access, ok
1182 9         26 return 0;
1183             }
1184 41         328 local @INC = @INC;
1185 41 50       127 pop @INC if $INC[-1] eq '.';
1186 41         92 my $file = $mod;
1187 41         80 my $obj;
1188 41         218 $file =~ s|::|/|g;
1189 41         102 $file .= ".pm";
1190 41 100       173 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         140 return 1;
1197 16         6855 } 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         215521 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         73 $CPAN::Shell::reload->{$file} = $mtime;
1207 6         1014 my $v = eval "\$$mod\::VERSION";
1208 6 50       57 $v = $v ? " (v$v)" : "";
1209 6         147 CPAN::Shell->optprint("load_module","CPAN: $mod loaded ok$v\n");
1210 6 50       39 if ($mod eq "CPAN::WAIT") {
1211 0         0 push @CPAN::Shell::ISA, 'CPAN::WAIT';
1212             }
1213 6         83 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         37 delete $INC{$file}; # if it inc'd LWP but failed during, say, URI
1261             }
1262 10         91 return 0;
1263             }
1264              
1265             #-> sub CPAN::instance ;
1266             sub instance {
1267 46     46 1 132 my($mgr,$class,$id) = @_;
1268 46         192 CPAN::Index->reload;
1269 46   50     126 $id ||= "";
1270             # unsafe meta access, ok?
1271 46 100       325 return $META->{readwrite}{$class}{$id} if exists $META->{readwrite}{$class}{$id};
1272 41   33     320 $META->{readwrite}{$class}{$id} ||= $class->new(ID => $id);
1273             }
1274              
1275             #-> sub CPAN::new ;
1276             sub new {
1277 12     12 0 230 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 139 local $SIG{__DIE__} = '';
1290 12         51 my($message) = @_;
1291 12         40 my $i = 0;
1292 12         38 my $ineval = 0;
1293 12         34 my($subroutine);
1294 12         143 while ((undef,undef,undef,$subroutine) = caller(++$i)) {
1295 24 100       148 $ineval = 1, last if
1296             $subroutine eq '(eval)';
1297             }
1298 12 50 33     155 return if $ineval && !$CPAN::End;
1299 12 50       406 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__