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