File Coverage

blib/lib/CPAN/Distribution.pm
Criterion Covered Total %
statement 91 2298 3.9
branch 29 1500 1.9
condition 11 570 1.9
subroutine 15 112 13.3
pod 0 74 0.0
total 146 4554 3.2


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             package CPAN::Distribution;
4 13     13   982 use strict;
  13         33  
  13         434  
5 13     13   65 use Cwd qw(chdir);
  13         28  
  13         733  
6 13     13   5391 use CPAN::Distroprefs;
  13         35  
  13         407  
7 13     13   466 use CPAN::InfoObj;
  13         33  
  13         262  
8 13     13   85 use File::Path ();
  13         29  
  13         364  
9             @CPAN::Distribution::ISA = qw(CPAN::InfoObj);
10 13     13   61 use vars qw($VERSION);
  13         25  
  13         784  
11             $VERSION = "2.24";
12              
13             # no prepare, because prepare is not a command on the shell command line
14             # TODO: clear instance cache on reload
15             my %instance;
16             for my $method (qw(get make test install)) {
17 13     13   85 no strict 'refs';
  13         27  
  13         163402  
18             for my $prefix (qw(pre post)) {
19             my $hookname = sprintf "%s_%s", $prefix, $method;
20             *$hookname = sub {
21 0     0   0 my($self) = @_;
22 0         0 for my $plugin (@{$CPAN::Config->{plugin_list}}) {
  0         0  
23 0         0 my($plugin_proper,$args) = split /=/, $plugin, 2;
24 0 0       0 $args = "" unless defined $args;
25 0 0       0 if ($CPAN::META->has_inst($plugin_proper)){
26 0         0 my @args = split /,/, $args;
27 0   0     0 $instance{$plugin} ||= $plugin_proper->new(@args);
28 0 0       0 if ($instance{$plugin}->can($hookname)) {
29 0         0 $instance{$plugin}->$hookname($self);
30             }
31             } else {
32 0         0 $CPAN::Frontend->mydie("Plugin '$plugin_proper' not found for hook '$hookname'");
33             }
34             }
35             };
36             }
37             }
38              
39             # Accessors
40             sub cpan_comment {
41 0     0 0 0 my $self = shift;
42 0 0       0 my $ro = $self->ro or return;
43             $ro->{CPAN_COMMENT}
44 0         0 }
45              
46             #-> CPAN::Distribution::undelay
47             sub undelay {
48 0     0 0 0 my $self = shift;
49 0         0 for my $delayer (
50             "configure_requires_later",
51             "configure_requires_later_for",
52             "later",
53             "later_for",
54             ) {
55 0         0 delete $self->{$delayer};
56             }
57             }
58              
59             #-> CPAN::Distribution::is_dot_dist
60             sub is_dot_dist {
61 0     0 0 0 my($self) = @_;
62 0         0 return substr($self->id,-1,1) eq ".";
63             }
64              
65             # add the A/AN/ stuff
66             #-> CPAN::Distribution::normalize
67             sub normalize {
68 1     1 0 4 my($self,$s) = @_;
69 1 50       5 $s = $self->id unless defined $s;
70 1 50 33     32 if (substr($s,-1,1) eq ".") {
    50          
71             # using a global because we are sometimes called as static method
72 0 0 0     0 if (!$CPAN::META->{LOCK}
73             && !$CPAN::Have_warned->{"$s is unlocked"}++
74             ) {
75 0         0 $CPAN::Frontend->mywarn("You are visiting the local directory
76             '$s'
77             without lock, take care that concurrent processes do not do likewise.\n");
78 0         0 $CPAN::Frontend->mysleep(1);
79             }
80 0 0       0 if ($s eq ".") {
    0          
    0          
81 0         0 $s = "$CPAN::iCwd/.";
82             } elsif (File::Spec->file_name_is_absolute($s)) {
83             } elsif (File::Spec->can("rel2abs")) {
84 0         0 $s = File::Spec->rel2abs($s);
85             } else {
86 0         0 $CPAN::Frontend->mydie("Your File::Spec is too old, please upgrade File::Spec");
87             }
88 0 0       0 CPAN->debug("s[$s]") if $CPAN::DEBUG;
89 0 0       0 unless ($CPAN::META->exists("CPAN::Distribution", $s)) {
90 0         0 for ($CPAN::META->instance("CPAN::Distribution", $s)) {
91 0         0 $_->{build_dir} = $s;
92 0         0 $_->{archived} = "local_directory";
93 0         0 $_->{unwrapped} = CPAN::Distrostatus->new("YES -- local_directory");
94             }
95             }
96             } elsif (
97             $s =~ tr|/|| == 1
98             or
99             $s !~ m|[A-Z]/[A-Z-0-9]{2}/[A-Z-0-9]{2,}/|
100             ) {
101 0 0       0 return $s if $s =~ m:^N/A|^Contact Author: ;
102 0         0 $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4|;
103 0 0       0 CPAN->debug("s[$s]") if $CPAN::DEBUG;
104             }
105 1         6 $s;
106             }
107              
108             #-> sub CPAN::Distribution::author ;
109             sub author {
110 1     1 0 4 my($self) = @_;
111 1         1 my($authorid);
112 1 50       5 if (substr($self->id,-1,1) eq ".") {
113 0         0 $authorid = "LOCAL";
114             } else {
115 1         8 ($authorid) = $self->pretty_id =~ /^([\w\-]+)/;
116             }
117 1         6 CPAN::Shell->expand("Author",$authorid);
118             }
119              
120             # tries to get the yaml from CPAN instead of the distro itself:
121             # EXPERIMENTAL, UNDOCUMENTED AND UNTESTED, for Tels
122             sub fast_yaml {
123 0     0 0 0 my($self) = @_;
124 0         0 my $meta = $self->pretty_id;
125 0         0 $meta =~ s/\.(tar.gz|tgz|zip|tar.bz2)/.meta/;
126 0         0 my(@ls) = CPAN::Shell->globls($meta);
127 0         0 my $norm = $self->normalize($meta);
128              
129 0         0 my($local_file);
130             my($local_wanted) =
131             File::Spec->catfile(
132             $CPAN::Config->{keep_source_where},
133 0         0 "authors",
134             "id",
135             split(/\//,$norm)
136             );
137 0 0       0 $self->debug("Doing localize") if $CPAN::DEBUG;
138 0 0       0 unless ($local_file =
139             CPAN::FTP->localize("authors/id/$norm",
140             $local_wanted)) {
141 0         0 $CPAN::Frontend->mydie("Giving up on downloading yaml file '$local_wanted'\n");
142             }
143 0         0 my $yaml = CPAN->_yaml_loadfile($local_file)->[0];
144             }
145              
146             #-> sub CPAN::Distribution::cpan_userid
147             sub cpan_userid {
148 0     0 0 0 my $self = shift;
149 0 0       0 if ($self->{ID} =~ m{[A-Z]/[A-Z\-]{2}/([A-Z\-]+)/}) {
150 0         0 return $1;
151             }
152 0         0 return $self->SUPER::cpan_userid;
153             }
154              
155             #-> sub CPAN::Distribution::pretty_id
156             sub pretty_id {
157 1     1 0 3 my $self = shift;
158 1         3 my $id = $self->id;
159 1 50       13 return $id unless $id =~ m|^./../|;
160 1         13 substr($id,5);
161             }
162              
163             #-> sub CPAN::Distribution::base_id
164             sub base_id {
165 0     0 0 0 my $self = shift;
166 0         0 my $id = $self->pretty_id();
167 0         0 my $base_id = File::Basename::basename($id);
168 0         0 $base_id =~ s{\.(?:tar\.(bz2|gz|Z)|t(?:gz|bz)|zip)$}{}i;
169 0         0 return $base_id;
170             }
171              
172             #-> sub CPAN::Distribution::tested_ok_but_not_installed
173             sub tested_ok_but_not_installed {
174 0     0 0 0 my $self = shift;
175             return (
176             $self->{make_test}
177             && $self->{build_dir}
178             && (UNIVERSAL::can($self->{make_test},"failed") ?
179             ! $self->{make_test}->failed :
180             $self->{make_test} =~ /^YES/
181             )
182             && (
183             !$self->{install}
184             ||
185             $self->{install}->failed
186             )
187 0   0     0 );
188             }
189              
190              
191             # mark as dirty/clean for the sake of recursion detection. $color=1
192             # means "in use", $color=0 means "not in use anymore". $color=2 means
193             # we have determined prereqs now and thus insist on passing this
194             # through (at least) once again.
195              
196             #-> sub CPAN::Distribution::color_cmd_tmps ;
197             sub color_cmd_tmps {
198 0     0 0 0 my($self) = shift;
199 0   0     0 my($depth) = shift || 0;
200 0   0     0 my($color) = shift || 0;
201 0   0     0 my($ancestors) = shift || [];
202             # a distribution needs to recurse into its prereq_pms
203 0 0       0 $self->debug("color_cmd_tmps[$depth,$color,@$ancestors]") if $CPAN::DEBUG;
204              
205             return if exists $self->{incommandcolor}
206             && $color==1
207 0 0 0     0 && $self->{incommandcolor}==$color;
      0        
208 0   0     0 $CPAN::MAX_RECURSION||=0; # silence 'once' warnings
209 0 0       0 if ($depth>=$CPAN::MAX_RECURSION) {
210 0         0 my $e = CPAN::Exception::RecursiveDependency->new($ancestors);
211 0 0       0 if ($e->is_resolvable) {
212 0         0 return $self->{incommandcolor}=2;
213             } else {
214 0         0 die $e;
215             }
216             }
217             # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
218 0         0 my $prereq_pm = $self->prereq_pm;
219 0 0       0 if (defined $prereq_pm) {
220             # XXX also optional_req & optional_breq? -- xdg, 2012-04-01
221             # A: no, optional deps may recurse -- ak, 2014-05-07
222 0         0 PREREQ: for my $pre (sort(
223 0 0       0 keys %{$prereq_pm->{requires}||{}},
224 0 0       0 keys %{$prereq_pm->{build_requires}||{}},
225             )) {
226 0 0       0 next PREREQ if $pre eq "perl";
227 0         0 my $premo;
228 0 0       0 unless ($premo = CPAN::Shell->expand("Module",$pre)) {
229 0         0 $CPAN::Frontend->mywarn("prerequisite module[$pre] not known\n");
230 0         0 $CPAN::Frontend->mysleep(0.2);
231 0         0 next PREREQ;
232             }
233 0         0 $premo->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
234             }
235             }
236 0 0       0 if ($color==0) {
237 0         0 delete $self->{sponsored_mods};
238              
239             # as we are at the end of a command, we'll give up this
240             # reminder of a broken test. Other commands may test this guy
241             # again. Maybe 'badtestcnt' should be renamed to
242             # 'make_test_failed_within_command'?
243 0         0 delete $self->{badtestcnt};
244             }
245 0         0 $self->{incommandcolor} = $color;
246             }
247              
248             #-> sub CPAN::Distribution::as_string ;
249             sub as_string {
250 0     0 0 0 my $self = shift;
251 0         0 $self->containsmods;
252 0         0 $self->upload_date;
253 0         0 $self->SUPER::as_string(@_);
254             }
255              
256             #-> sub CPAN::Distribution::containsmods ;
257             sub containsmods {
258 0     0 0 0 my $self = shift;
259 0 0       0 return sort keys %{$self->{CONTAINSMODS}} if exists $self->{CONTAINSMODS};
  0         0  
260 0         0 my $dist_id = $self->{ID};
261 0         0 for my $mod ($CPAN::META->all_objects("CPAN::Module")) {
262 0 0       0 my $mod_file = $mod->cpan_file or next;
263 0 0       0 my $mod_id = $mod->{ID} or next;
264             # warn "mod_file[$mod_file] dist_id[$dist_id] mod_id[$mod_id]";
265             # sleep 1;
266 0 0       0 if ($CPAN::Signal) {
267 0         0 delete $self->{CONTAINSMODS};
268 0         0 return;
269             }
270 0 0       0 $self->{CONTAINSMODS}{$mod_id} = undef if $mod_file eq $dist_id;
271             }
272 0   0     0 sort keys %{$self->{CONTAINSMODS}||={}};
  0         0  
273             }
274              
275             #-> sub CPAN::Distribution::upload_date ;
276             sub upload_date {
277 0     0 0 0 my $self = shift;
278 0 0       0 return $self->{UPLOAD_DATE} if exists $self->{UPLOAD_DATE};
279 0         0 my(@local_wanted) = split(/\//,$self->id);
280 0         0 my $filename = pop @local_wanted;
281 0         0 push @local_wanted, "CHECKSUMS";
282 0         0 my $author = CPAN::Shell->expand("Author",$self->cpan_userid);
283 0 0       0 return unless $author;
284 0         0 my @dl = $author->dir_listing(\@local_wanted,0,$CPAN::Config->{show_upload_date});
285 0 0       0 return unless @dl;
286 0         0 my($dirent) = grep { $_->[2] eq $filename } @dl;
  0         0  
287             # warn sprintf "dirent[%s]id[%s]", $dirent, $self->id;
288 0 0       0 return unless $dirent->[1];
289 0         0 return $self->{UPLOAD_DATE} = $dirent->[1];
290             }
291              
292             #-> sub CPAN::Distribution::uptodate ;
293             sub uptodate {
294 0     0 0 0 my($self) = @_;
295 0         0 my $c;
296 0         0 foreach $c ($self->containsmods) {
297 0         0 my $obj = CPAN::Shell->expandany($c);
298 0 0       0 unless ($obj->uptodate) {
299 0         0 my $id = $self->pretty_id;
300 0 0       0 $self->debug("$id not uptodate due to $c") if $CPAN::DEBUG;
301 0         0 return 0;
302             }
303             }
304 0         0 return 1;
305             }
306              
307             #-> sub CPAN::Distribution::called_for ;
308             sub called_for {
309 0     0 0 0 my($self,$id) = @_;
310 0 0       0 $self->{CALLED_FOR} = $id if defined $id;
311 0         0 return $self->{CALLED_FOR};
312             }
313              
314             #-> sub CPAN::Distribution::shortcut_get ;
315             # return values: undef means don't shortcut; 0 means shortcut as fail;
316             # and 1 means shortcut as success
317             sub shortcut_get {
318 0     0 0 0 my ($self) = @_;
319              
320 0 0       0 if (exists $self->{cleanup_after_install_done}) {
321 0 0       0 if ($self->{force_update}) {
322 0         0 delete $self->{cleanup_after_install_done};
323             } else {
324 0   0     0 my $id = $self->{CALLED_FOR} || $self->pretty_id;
325 0         0 return $self->success(
326             "Has already been *installed and cleaned up in the staging area* within this session, will not work on it again; if you really want to start over, try something like `force get $id`"
327             );
328             }
329             }
330              
331 0 0       0 if (my $why = $self->check_disabled) {
332 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO $why");
333             # XXX why is this goodbye() instead of just print/warn?
334             # Alternatively, should other print/warns here be goodbye()?
335             # -- xdg, 2012-04-05
336 0         0 return $self->goodbye("[disabled] -- NA $why");
337             }
338              
339 0 0       0 $self->debug("checking already unwrapped[$self->{ID}]") if $CPAN::DEBUG;
340 0 0 0     0 if (exists $self->{build_dir} && -d $self->{build_dir}) {
341             # this deserves print, not warn:
342 0         0 return $self->success("Has already been unwrapped into directory ".
343             "$self->{build_dir}"
344             );
345             }
346              
347             # XXX I'm not sure this should be here because it's not really
348             # a test for whether get should continue or return; this is
349             # a side effect -- xdg, 2012-04-05
350 0 0       0 $self->debug("checking missing build_dir[$self->{ID}]") if $CPAN::DEBUG;
351 0 0 0     0 if (exists $self->{build_dir} && ! -d $self->{build_dir}){
352             # we have lost it.
353 0         0 $self->fforce(""); # no method to reset all phases but not set force (dodge)
354 0         0 return undef; # no shortcut
355             }
356              
357             # although we talk about 'force' we shall not test on
358             # force directly. New model of force tries to refrain from
359             # direct checking of force.
360 0 0       0 $self->debug("checking unwrapping error[$self->{ID}]") if $CPAN::DEBUG;
361 0 0 0     0 if ( exists $self->{unwrapped} and (
    0          
362             UNIVERSAL::can($self->{unwrapped},"failed") ?
363             $self->{unwrapped}->failed :
364             $self->{unwrapped} =~ /^NO/ )
365             ) {
366 0         0 return $self->goodbye("Unwrapping had some problem, won't try again without force");
367             }
368              
369 0         0 return undef; # no shortcut
370             }
371              
372             #-> sub CPAN::Distribution::get ;
373             sub get {
374 0     0 0 0 my($self) = @_;
375              
376 0         0 $self->pre_get();
377              
378 0 0       0 $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
379 0 0       0 if (my $goto = $self->prefs->{goto}) {
380 0         0 return $self->goto($goto);
381             }
382              
383 0 0       0 if ( defined( my $sc = $self->shortcut_get) ) {
384 0         0 return $sc;
385             }
386              
387             local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
388             ? $ENV{PERL5LIB}
389 0 0 0     0 : ($ENV{PERLLIB} || "");
390 0 0       0 local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
391             # local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # get
392 0         0 $CPAN::META->set_perl5lib;
393 0         0 local $ENV{MAKEFLAGS}; # protect us from outer make calls
394              
395 0         0 my $sub_wd = CPAN::anycwd(); # for cleaning up as good as possible
396              
397 0         0 my($local_file);
398             # XXX I don't think this check needs to be here, as it
399             # is already checked in shortcut_get() -- xdg, 2012-04-05
400 0 0 0     0 unless ($self->{build_dir} && -d $self->{build_dir}) {
401 0         0 $self->get_file_onto_local_disk;
402 0 0       0 return if $CPAN::Signal;
403 0         0 $self->check_integrity;
404 0 0       0 return if $CPAN::Signal;
405 0         0 (my $packagedir,$local_file) = $self->run_preps_on_packagedir;
406             # XXX why is this check here? -- xdg, 2012-04-08
407 0 0 0     0 if (exists $self->{writemakefile} && ref $self->{writemakefile}
      0        
      0        
408             && $self->{writemakefile}->can("failed") &&
409             $self->{writemakefile}->failed) {
410             #
411 0         0 return;
412             }
413 0   0     0 $packagedir ||= $self->{build_dir};
414 0         0 $self->{build_dir} = $packagedir;
415             }
416              
417             # XXX should this move up to after run_preps_on_packagedir?
418             # Otherwise, failing writemakefile can return without
419             # a $CPAN::Signal check -- xdg, 2012-04-05
420 0 0       0 if ($CPAN::Signal) {
421 0         0 $self->safe_chdir($sub_wd);
422 0         0 return;
423             }
424 0 0       0 return unless $self->patch;
425 0         0 $self->store_persistent_state;
426              
427 0         0 $self->post_get();
428              
429 0         0 return 1; # success
430             }
431              
432             #-> CPAN::Distribution::get_file_onto_local_disk
433             sub get_file_onto_local_disk {
434 0     0 0 0 my($self) = @_;
435              
436 0 0       0 return if $self->is_dot_dist;
437 0         0 my($local_file);
438             my($local_wanted) =
439             File::Spec->catfile(
440             $CPAN::Config->{keep_source_where},
441 0         0 "authors",
442             "id",
443             split(/\//,$self->id)
444             );
445              
446 0 0       0 $self->debug("Doing localize") if $CPAN::DEBUG;
447 0 0       0 unless ($local_file =
448             CPAN::FTP->localize("authors/id/$self->{ID}",
449             $local_wanted)) {
450 0         0 my $note = "";
451 0 0       0 if ($CPAN::Index::DATE_OF_02) {
452 0         0 $note = "Note: Current database in memory was generated ".
453             "on $CPAN::Index::DATE_OF_02\n";
454             }
455 0         0 $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n$note");
456             }
457              
458 0 0       0 $self->debug("local_wanted[$local_wanted]local_file[$local_file]") if $CPAN::DEBUG;
459 0         0 $self->{localfile} = $local_file;
460             }
461              
462              
463             #-> CPAN::Distribution::check_integrity
464             sub check_integrity {
465 0     0 0 0 my($self) = @_;
466              
467 0 0       0 return if $self->is_dot_dist;
468 0 0       0 if ($CPAN::META->has_inst("Digest::SHA")) {
469 0         0 $self->debug("Digest::SHA is installed, verifying");
470 0         0 $self->verifyCHECKSUM;
471             } else {
472 0         0 $self->debug("Digest::SHA is NOT installed");
473             }
474             }
475              
476             #-> CPAN::Distribution::run_preps_on_packagedir
477             sub run_preps_on_packagedir {
478 0     0 0 0 my($self) = @_;
479 0 0       0 return if $self->is_dot_dist;
480              
481 0   0     0 $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); # unsafe meta access, ok
482 0         0 my $builddir = $CPAN::META->{cachemgr}->dir; # unsafe meta access, ok
483 0         0 $self->safe_chdir($builddir);
484 0 0       0 $self->debug("Removing tmp-$$") if $CPAN::DEBUG;
485 0         0 File::Path::rmtree("tmp-$$");
486 0 0       0 unless (mkdir "tmp-$$", 0755) {
487 0         0 $CPAN::Frontend->unrecoverable_error(<
488             Couldn't mkdir '$builddir/tmp-$$': $!
489              
490             Cannot continue: Please find the reason why I cannot make the
491             directory
492             $builddir/tmp-$$
493             and fix the problem, then retry.
494              
495             EOF
496             }
497 0 0       0 if ($CPAN::Signal) {
498 0         0 return;
499             }
500 0         0 $self->safe_chdir("tmp-$$");
501              
502             #
503             # Unpack the goods
504             #
505 0         0 my $local_file = $self->{localfile};
506 0         0 my $ct = eval{CPAN::Tarzip->new($local_file)};
  0         0  
507 0 0       0 unless ($ct) {
508 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO");
509 0         0 delete $self->{build_dir};
510 0         0 return;
511             }
512 0 0       0 if ($local_file =~ /(\.tar\.(bz2|gz|Z)|\.tgz)(?!\n)\Z/i) {
    0          
513 0 0       0 $self->{was_uncompressed}++ unless eval{$ct->gtest()};
  0         0  
514 0         0 $self->untar_me($ct);
515             } elsif ( $local_file =~ /\.zip(?!\n)\Z/i ) {
516 0         0 $self->unzip_me($ct);
517             } else {
518 0 0       0 $self->{was_uncompressed}++ unless $ct->gtest();
519 0         0 $local_file = $self->handle_singlefile($local_file);
520             }
521              
522             # we are still in the tmp directory!
523             # Let's check if the package has its own directory.
524 0 0       0 my $dh = DirHandle->new(File::Spec->curdir)
525             or Carp::croak("Couldn't opendir .: $!");
526 0         0 my @readdir = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh->read; ### MAC??
527 0 0       0 if (grep { $_ eq "pax_global_header" } @readdir) {
  0         0  
528 0         0 $CPAN::Frontend->mywarn("Your (un)tar seems to have extracted a file named 'pax_global_header'
529             from the tarball '$local_file'.
530             This is almost certainly an error. Please upgrade your tar.
531             I'll ignore this file for now.
532             See also http://rt.cpan.org/Ticket/Display.html?id=38932\n");
533 0         0 $CPAN::Frontend->mysleep(5);
534 0         0 @readdir = grep { $_ ne "pax_global_header" } @readdir;
  0         0  
535             }
536 0         0 $dh->close;
537 0         0 my $tdir_base;
538             my $from_dir;
539 0         0 my @dirents;
540 0 0 0     0 if (@readdir == 1 && -d $readdir[0]) {
541 0         0 $tdir_base = $readdir[0];
542 0         0 $from_dir = File::Spec->catdir(File::Spec->curdir,$readdir[0]);
543 0         0 my $dh2;
544 0 0       0 unless ($dh2 = DirHandle->new($from_dir)) {
545 0         0 my($mode) = (stat $from_dir)[2];
546 0         0 my $why = sprintf
547             (
548             "Couldn't opendir '%s', mode '%o': %s",
549             $from_dir,
550             $mode,
551             $!,
552             );
553 0         0 $CPAN::Frontend->mywarn("$why\n");
554 0         0 $self->{writemakefile} = CPAN::Distrostatus->new("NO -- $why");
555 0         0 return;
556             }
557 0         0 @dirents = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh2->read; ### MAC??
558             } else {
559 0         0 my $userid = $self->cpan_userid;
560 0         0 CPAN->debug("userid[$userid]");
561 0 0 0     0 if (!$userid or $userid eq "N/A") {
562 0         0 $userid = "anon";
563             }
564 0         0 $tdir_base = $userid;
565 0         0 $from_dir = File::Spec->curdir;
566 0         0 @dirents = @readdir;
567             }
568 0         0 eval { File::Path::mkpath $builddir; };
  0         0  
569 0 0       0 if ($@) {
570 0         0 $CPAN::Frontend->mydie("Cannot create directory $builddir: $@");
571             }
572 0         0 my $packagedir;
573 0 0 0     0 my $eexist = ($CPAN::META->has_usable("Errno") && defined &Errno::EEXIST)
574             ? &Errno::EEXIST : undef;
575 0         0 for(my $suffix = 0; ; $suffix++) {
576 0         0 $packagedir = File::Spec->catdir($builddir, "$tdir_base-$suffix");
577 0         0 my $parent = $builddir;
578 0 0       0 mkdir($packagedir, 0777) and last;
579 0 0 0     0 if((defined($eexist) && $! != $eexist) || $suffix == 999) {
      0        
580 0         0 $CPAN::Frontend->mydie("Cannot create directory $packagedir: $!\n");
581             }
582             }
583 0         0 my $f;
584 0         0 for $f (@dirents) { # is already without "." and ".."
585 0         0 my $from = File::Spec->catfile($from_dir,$f);
586 0         0 my $to = File::Spec->catfile($packagedir,$f);
587 0 0       0 unless (File::Copy::move($from,$to)) {
588 0         0 my $err = $!;
589 0         0 $from = File::Spec->rel2abs($from);
590 0 0       0 $CPAN::Frontend->mydie(
    0          
591             "Couldn't move $from to $to: $err; #82295? ".
592             "CPAN::VERSION=$CPAN::VERSION; ".
593             "File::Copy::VERSION=$File::Copy::VERSION; ".
594             "$from " . (-e $from ? "exists; " : "does not exist; ").
595             "$to " . (-e $to ? "exists; " : "does not exist; ").
596             "cwd=" . CPAN::anycwd() . ";"
597             );
598             }
599             }
600 0         0 $self->{build_dir} = $packagedir;
601 0         0 $self->safe_chdir($builddir);
602 0         0 File::Path::rmtree("tmp-$$");
603              
604 0         0 $self->safe_chdir($packagedir);
605 0         0 $self->_signature_business();
606 0         0 $self->safe_chdir($builddir);
607              
608 0         0 return($packagedir,$local_file);
609             }
610              
611             #-> sub CPAN::Distribution::pick_meta_file ;
612             sub pick_meta_file {
613 41     41 0 6589 my($self, $filter) = @_;
614 41 50       117 $filter = '.' unless defined $filter;
615              
616 41         57 my $build_dir;
617 41 50       113 unless ($build_dir = $self->{build_dir}) {
618             # maybe permission on build_dir was missing
619 0         0 $CPAN::Frontend->mywarn("Warning: cannot determine META.yml without a build_dir.\n");
620 0         0 return;
621             }
622              
623 41         136 my $has_cm = $CPAN::META->has_usable("CPAN::Meta");
624 41         82 my $has_pcm = $CPAN::META->has_usable("Parse::CPAN::Meta");
625              
626 41         61 my @choices;
627 41 50       105 push @choices, 'MYMETA.json' if $has_cm;
628 41 50 33     108 push @choices, 'MYMETA.yml' if $has_cm || $has_pcm;
629 41 50       87 push @choices, 'META.json' if $has_cm;
630 41 50 33     106 push @choices, 'META.yml' if $has_cm || $has_pcm;
631              
632 41         87 for my $file ( grep { /$filter/ } @choices ) {
  164         530  
633 101         942 my $path = File::Spec->catfile( $build_dir, $file );
634 101 100       1422 return $path if -f $path
635             }
636              
637 3         23 return;
638             }
639              
640             #-> sub CPAN::Distribution::parse_meta_yml ;
641             sub parse_meta_yml {
642 0     0 0 0 my($self, $yaml) = @_;
643 0 0 0     0 $self->debug(sprintf("parse_meta_yml[%s]",$yaml||'undef')) if $CPAN::DEBUG;
644 0 0       0 my $build_dir = $self->{build_dir} or die "PANIC: cannot parse yaml without a build_dir";
645 0   0     0 $yaml ||= File::Spec->catfile($build_dir,"META.yml");
646 0 0       0 $self->debug("meta[$yaml]") if $CPAN::DEBUG;
647 0 0       0 return unless -f $yaml;
648 0         0 my $early_yaml;
649 0         0 eval {
650 0 0       0 $CPAN::META->has_inst("Parse::CPAN::Meta") or die;
651 0 0       0 die "Parse::CPAN::Meta yaml too old" unless $Parse::CPAN::Meta::VERSION >= "1.40";
652             # P::C::M returns last document in scalar context
653 0         0 $early_yaml = Parse::CPAN::Meta::LoadFile($yaml);
654             };
655 0 0       0 unless ($early_yaml) {
656 0         0 eval { $early_yaml = CPAN->_yaml_loadfile($yaml)->[0]; };
  0         0  
657             }
658 0 0 0     0 $self->debug(sprintf("yaml[%s]", $early_yaml || 'UNDEF')) if $CPAN::DEBUG;
659 0 0 0     0 $self->debug($early_yaml) if $CPAN::DEBUG && $early_yaml;
660 0 0 0     0 if (!ref $early_yaml or ref $early_yaml ne "HASH"){
661             # fix rt.cpan.org #95271
662 0         0 $CPAN::Frontend->mywarn("The content of '$yaml' is not a HASH reference. Cannot use it.\n");
663 0         0 return {};
664             }
665 0   0     0 return $early_yaml || undef;
666             }
667              
668             #-> sub CPAN::Distribution::satisfy_requires ;
669             # return values: 1 means requirements are satisfied;
670             # and 0 means not satisfied (and maybe queued)
671             sub satisfy_requires {
672 0     0 0 0 my ($self) = @_;
673 0 0       0 $self->debug("Entering satisfy_requires") if $CPAN::DEBUG;
674 0 0       0 if (my @prereq = $self->unsat_prereq("later")) {
675 0 0       0 if ($CPAN::DEBUG){
676 0         0 require Data::Dumper;
677 0         0 my $prereq = Data::Dumper->new(\@prereq)->Terse(1)->Indent(0)->Dump;
678 0         0 $self->debug("unsatisfied[$prereq]");
679             }
680 0 0       0 if ($prereq[0][0] eq "perl") {
681 0         0 my $need = "requires perl '$prereq[0][1]'";
682 0         0 my $id = $self->pretty_id;
683 0         0 $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n");
684 0         0 $self->{make} = CPAN::Distrostatus->new("NO $need");
685 0         0 $self->store_persistent_state;
686 0         0 die "[prereq] -- NOT OK\n";
687             } else {
688 0         0 my $follow = eval { $self->follow_prereqs("later",@prereq); };
  0         0  
689 0 0 0     0 if (0) {
    0 0        
690 0         0 } elsif ($follow) {
691 0         0 return; # we need deps
692             } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) {
693 0         0 $CPAN::Frontend->mywarn($@);
694 0         0 die "[depend] -- NOT OK\n";
695             }
696             }
697             }
698 0         0 return 1;
699             }
700              
701             #-> sub CPAN::Distribution::satisfy_configure_requires ;
702             # return values: 1 means configure_require is satisfied;
703             # and 0 means not satisfied (and maybe queued)
704             sub satisfy_configure_requires {
705 0     0 0 0 my($self) = @_;
706 0 0       0 $self->debug("Entering satisfy_configure_requires") if $CPAN::DEBUG;
707 0         0 my $enable_configure_requires = 1;
708 0 0       0 if (!$enable_configure_requires) {
709 0         0 return 1;
710             # if we return 1 here, everything is as before we introduced
711             # configure_requires that means, things with
712             # configure_requires simply fail, all others succeed
713             }
714 0         0 my @prereq = $self->unsat_prereq("configure_requires_later");
715 0 0       0 $self->debug(sprintf "configure_requires[%s]", join(",",map {join "/",@$_} @prereq)) if $CPAN::DEBUG;
  0         0  
716 0 0       0 return 1 unless @prereq;
717 0 0       0 $self->debug(\@prereq) if $CPAN::DEBUG;
718 0 0       0 if ($self->{configure_requires_later}) {
719 0 0       0 for my $k (sort keys %{$self->{configure_requires_later_for}||{}}) {
  0         0  
720 0 0       0 if ($self->{configure_requires_later_for}{$k}>1) {
721 0         0 my $type = "";
722 0         0 for my $p (@prereq) {
723 0 0       0 if ($p->[0] eq $k) {
724 0         0 $type = $p->[1];
725             }
726             }
727 0 0       0 $type = " $type" if $type;
728 0         0 $CPAN::Frontend->mywarn("Warning: unmanageable(?) prerequisite $k$type");
729 0         0 sleep 1;
730             }
731             }
732             }
733 0 0       0 if ($prereq[0][0] eq "perl") {
734 0         0 my $need = "requires perl '$prereq[0][1]'";
735 0         0 my $id = $self->pretty_id;
736 0         0 $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n");
737 0         0 $self->{make} = CPAN::Distrostatus->new("NO $need");
738 0         0 $self->store_persistent_state;
739 0         0 return $self->goodbye("[prereq] -- NOT OK");
740             } else {
741 0         0 my $follow = eval {
742 0         0 $self->follow_prereqs("configure_requires_later", @prereq);
743             };
744 0 0 0     0 if (0) {
    0 0        
745 0         0 } elsif ($follow) {
746 0         0 return; # we need deps
747             } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) {
748 0         0 $CPAN::Frontend->mywarn($@);
749 0         0 return $self->goodbye("[depend] -- NOT OK");
750             }
751             else {
752 0         0 return $self->goodbye("[configure_requires] -- NOT OK");
753             }
754             }
755 0         0 die "never reached";
756             }
757              
758             #-> sub CPAN::Distribution::choose_MM_or_MB ;
759             sub choose_MM_or_MB {
760 0     0 0 0 my($self) = @_;
761 0 0       0 $self->satisfy_configure_requires() or return;
762 0         0 my $local_file = $self->{localfile};
763 0         0 my($mpl) = File::Spec->catfile($self->{build_dir},"Makefile.PL");
764 0         0 my($mpl_exists) = -f $mpl;
765 0 0       0 unless ($mpl_exists) {
766             # NFS has been reported to have racing problems after the
767             # renaming of a directory in some environments.
768             # This trick helps.
769 0         0 $CPAN::Frontend->mysleep(1);
770             my $mpldh = DirHandle->new($self->{build_dir})
771 0 0       0 or Carp::croak("Couldn't opendir $self->{build_dir}: $!");
772 0         0 $mpl_exists = grep /^Makefile\.PL$/, $mpldh->read;
773 0         0 $mpldh->close;
774             }
775 0         0 my $prefer_installer = "eumm"; # eumm|mb
776 0 0       0 if (-f File::Spec->catfile($self->{build_dir},"Build.PL")) {
777 0 0       0 if ($mpl_exists) { # they *can* choose
778 0 0       0 if ($CPAN::META->has_inst("Module::Build")) {
779 0         0 $prefer_installer = CPAN::HandleConfig->prefs_lookup(
780             $self, q{prefer_installer}
781             );
782             # M::B <= 0.35 left a DATA handle open that
783             # causes problems upgrading M::B on Windows
784 0 0       0 close *Module::Build::Version::DATA
785             if fileno *Module::Build::Version::DATA;
786             }
787             } else {
788 0         0 $prefer_installer = "mb";
789             }
790             }
791 0 0       0 if (lc($prefer_installer) eq "rand") {
792 0 0       0 $prefer_installer = rand()<.5 ? "eumm" : "mb";
793             }
794 0 0       0 if (lc($prefer_installer) eq "mb") {
    0          
    0          
795 0         0 $self->{modulebuild} = 1;
796             } elsif ($self->{archived} eq "patch") {
797             # not an edge case, nothing to install for sure
798 0         0 my $why = "A patch file cannot be installed";
799 0         0 $CPAN::Frontend->mywarn("Refusing to handle this file: $why\n");
800 0         0 $self->{writemakefile} = CPAN::Distrostatus->new("NO $why");
801             } elsif (! $mpl_exists) {
802 0         0 $self->_edge_cases($mpl,$local_file);
803             }
804 0 0 0     0 if ($self->{build_dir}
805             &&
806             $CPAN::Config->{build_dir_reuse}
807             ) {
808 0         0 $self->store_persistent_state;
809             }
810 0         0 return $self;
811             }
812              
813             # see also reanimate_build_dir
814             #-> CPAN::Distribution::store_persistent_state
815             sub store_persistent_state {
816 0     0 0 0 my($self) = @_;
817 0         0 my $dir = $self->{build_dir};
818 0 0 0     0 unless (defined $dir && length $dir) {
819 0         0 my $id = $self->id;
820 0         0 $CPAN::Frontend->mywarnonce("build_dir of $id is not known, ".
821             "will not store persistent state\n");
822 0         0 return;
823             }
824             # self-build-dir
825 0         0 my $sbd = Cwd::realpath(
826             File::Spec->catdir($dir, File::Spec->updir ())
827             );
828             # config-build-dir
829             my $cbd = Cwd::realpath(
830             # the catdir is a workaround for bug https://rt.cpan.org/Ticket/Display.html?id=101283
831 0         0 File::Spec->catdir($CPAN::Config->{build_dir}, File::Spec->curdir())
832             );
833 0 0       0 unless ($sbd eq $cbd) {
834 0         0 $CPAN::Frontend->mywarnonce("Directory '$dir' not below $CPAN::Config->{build_dir}, ".
835             "will not store persistent state\n");
836 0         0 return;
837             }
838 0         0 my $file = sprintf "%s.yml", $dir;
839 0         0 my $yaml_module = CPAN::_yaml_module();
840 0 0       0 if ($CPAN::META->has_inst($yaml_module)) {
841 0         0 CPAN->_yaml_dumpfile(
842             $file,
843             {
844             time => time,
845             perl => CPAN::_perl_fingerprint(),
846             distribution => $self,
847             }
848             );
849             } else {
850 0         0 $CPAN::Frontend->myprintonce("'$yaml_module' not installed, ".
851             "will not store persistent state\n");
852             }
853             }
854              
855             #-> CPAN::Distribution::try_download
856             sub try_download {
857 0     0 0 0 my($self,$patch) = @_;
858 0         0 my $norm = $self->normalize($patch);
859             my($local_wanted) =
860             File::Spec->catfile(
861             $CPAN::Config->{keep_source_where},
862 0         0 "authors",
863             "id",
864             split(/\//,$norm),
865             );
866 0 0       0 $self->debug("Doing localize") if $CPAN::DEBUG;
867 0         0 return CPAN::FTP->localize("authors/id/$norm",
868             $local_wanted);
869             }
870              
871             {
872             my $stdpatchargs = "";
873             #-> CPAN::Distribution::patch
874             sub patch {
875 0     0 0 0 my($self) = @_;
876 0 0       0 $self->debug("checking patches id[$self->{ID}]") if $CPAN::DEBUG;
877 0         0 my $patches = $self->prefs->{patches};
878 0   0     0 $patches ||= "";
879 0 0       0 $self->debug("patches[$patches]") if $CPAN::DEBUG;
880 0 0       0 if ($patches) {
881 0 0       0 return unless @$patches;
882 0         0 $self->safe_chdir($self->{build_dir});
883 0 0       0 CPAN->debug("patches[$patches]") if $CPAN::DEBUG;
884 0         0 my $patchbin = $CPAN::Config->{patch};
885 0 0 0     0 unless ($patchbin && length $patchbin) {
886 0         0 $CPAN::Frontend->mydie("No external patch command configured\n\n".
887             "Please run 'o conf init /patch/'\n\n");
888             }
889 0 0       0 unless (MM->maybe_command($patchbin)) {
890 0         0 $CPAN::Frontend->mydie("No external patch command available\n\n".
891             "Please run 'o conf init /patch/'\n\n");
892             }
893 0         0 $patchbin = CPAN::HandleConfig->safe_quote($patchbin);
894 0         0 local $ENV{PATCH_GET} = 0; # formerly known as -g0
895 0 0       0 unless ($stdpatchargs) {
896 0         0 my $system = "$patchbin --version |";
897 0         0 local *FH;
898 0 0       0 open FH, $system or die "Could not fork '$system': $!";
899 0         0 local $/ = "\n";
900 0         0 my $pversion;
901 0         0 PARSEVERSION: while () {
902 0 0       0 if (/^patch\s+([\d\.]+)/) {
903 0         0 $pversion = $1;
904 0         0 last PARSEVERSION;
905             }
906             }
907 0 0       0 if ($pversion) {
908 0         0 $stdpatchargs = "-N --fuzz=3";
909             } else {
910 0         0 $stdpatchargs = "-N";
911             }
912             }
913 0 0       0 my $countedpatches = @$patches == 1 ? "1 patch" : (scalar @$patches . " patches");
914 0         0 $CPAN::Frontend->myprint("Applying $countedpatches:\n");
915 0         0 my $patches_dir = $CPAN::Config->{patches_dir};
916 0         0 for my $patch (@$patches) {
917 0 0 0     0 if ($patches_dir && !File::Spec->file_name_is_absolute($patch)) {
918 0         0 my $f = File::Spec->catfile($patches_dir, $patch);
919 0 0       0 $patch = $f if -f $f;
920             }
921 0 0       0 unless (-f $patch) {
922 0 0       0 CPAN->debug("not on disk: patch[$patch]") if $CPAN::DEBUG;
923 0 0       0 if (my $trydl = $self->try_download($patch)) {
924 0         0 $patch = $trydl;
925             } else {
926 0         0 my $fail = "Could not find patch '$patch'";
927 0         0 $CPAN::Frontend->mywarn("$fail; cannot continue\n");
928 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail");
929 0         0 delete $self->{build_dir};
930 0         0 return;
931             }
932             }
933 0         0 $CPAN::Frontend->myprint(" $patch\n");
934 0         0 my $readfh = CPAN::Tarzip->TIEHANDLE($patch);
935              
936 0         0 my $pcommand;
937 0         0 my($ppp,$pfiles) = $self->_patch_p_parameter($readfh);
938 0 0       0 if ($ppp eq "applypatch") {
939 0         0 $pcommand = "$CPAN::Config->{applypatch} -verbose";
940             } else {
941 0         0 my $thispatchargs = join " ", $stdpatchargs, $ppp;
942 0         0 $pcommand = "$patchbin $thispatchargs";
943 0         0 require Config; # usually loaded from CPAN.pm
944 0 0       0 if ($Config::Config{osname} eq "solaris") {
945             # native solaris patch cannot patch readonly files
946 0 0       0 for my $file (@{$pfiles||[]}) {
  0         0  
947 0 0       0 my @stat = stat $file or next;
948 0         0 chmod $stat[2] | 0600, $file; # may fail
949             }
950             }
951             }
952              
953 0         0 $readfh = CPAN::Tarzip->TIEHANDLE($patch); # open again
954 0         0 my $writefh = FileHandle->new;
955 0         0 $CPAN::Frontend->myprint(" $pcommand\n");
956 0 0       0 unless (open $writefh, "|$pcommand") {
957 0         0 my $fail = "Could not fork '$pcommand'";
958 0         0 $CPAN::Frontend->mywarn("$fail; cannot continue\n");
959 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail");
960 0         0 delete $self->{build_dir};
961 0         0 return;
962             }
963 0         0 binmode($writefh);
964 0         0 while (my $x = $readfh->READLINE) {
965 0         0 print $writefh $x;
966             }
967 0 0       0 unless (close $writefh) {
968 0         0 my $fail = "Could not apply patch '$patch'";
969 0         0 $CPAN::Frontend->mywarn("$fail; cannot continue\n");
970 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail");
971 0         0 delete $self->{build_dir};
972 0         0 return;
973             }
974             }
975 0         0 $self->{patched}++;
976             }
977 0         0 return 1;
978             }
979             }
980              
981             # may return
982             # - "applypatch"
983             # - ("-p0"|"-p1", $files)
984             sub _patch_p_parameter {
985 0     0   0 my($self,$fh) = @_;
986 0         0 my $cnt_files = 0;
987 0         0 my $cnt_p0files = 0;
988 0         0 my @files;
989 0         0 local($_);
990 0         0 while ($_ = $fh->READLINE) {
991 0 0 0     0 if (
992             $CPAN::Config->{applypatch}
993             &&
994             /\#\#\#\# ApplyPatch data follows \#\#\#\#/
995             ) {
996 0         0 return "applypatch"
997             }
998 0 0       0 next unless /^[\*\+]{3}\s(\S+)/;
999 0         0 my $file = $1;
1000 0         0 push @files, $file;
1001 0         0 $cnt_files++;
1002 0 0       0 $cnt_p0files++ if -f $file;
1003 0 0       0 CPAN->debug("file[$file]cnt_files[$cnt_files]cnt_p0files[$cnt_p0files]")
1004             if $CPAN::DEBUG;
1005             }
1006 0 0       0 return "-p1" unless $cnt_files;
1007 0 0       0 my $opt_p = $cnt_files==$cnt_p0files ? "-p0" : "-p1";
1008 0         0 return ($opt_p, \@files);
1009             }
1010              
1011             #-> sub CPAN::Distribution::_edge_cases
1012             # with "configure" or "Makefile" or single file scripts
1013             sub _edge_cases {
1014 0     0   0 my($self,$mpl,$local_file) = @_;
1015 0 0       0 $self->debug(sprintf("makefilepl[%s]anycwd[%s]",
1016             $mpl,
1017             CPAN::anycwd(),
1018             )) if $CPAN::DEBUG;
1019 0         0 my $build_dir = $self->{build_dir};
1020 0         0 my($configure) = File::Spec->catfile($build_dir,"Configure");
1021 0 0       0 if (-f $configure) {
    0          
1022             # do we have anything to do?
1023 0         0 $self->{configure} = $configure;
1024             } elsif (-f File::Spec->catfile($build_dir,"Makefile")) {
1025 0         0 $CPAN::Frontend->mywarn(qq{
1026             Package comes with a Makefile and without a Makefile.PL.
1027             We\'ll try to build it with that Makefile then.
1028             });
1029 0         0 $self->{writemakefile} = CPAN::Distrostatus->new("YES");
1030 0         0 $CPAN::Frontend->mysleep(2);
1031             } else {
1032 0   0     0 my $cf = $self->called_for || "unknown";
1033 0 0       0 if ($cf =~ m|/|) {
1034 0         0 $cf =~ s|.*/||;
1035 0         0 $cf =~ s|\W.*||;
1036             }
1037 0         0 $cf =~ s|[/\\:]||g; # risk of filesystem damage
1038 0 0       0 $cf = "unknown" unless length($cf);
1039 0 0       0 if (my $crud = $self->_contains_crud($build_dir)) {
1040 0         0 my $why = qq{Package contains $crud; not recognized as a perl package, giving up};
1041 0         0 $CPAN::Frontend->mywarn("$why\n");
1042 0         0 $self->{writemakefile} = CPAN::Distrostatus->new(qq{NO -- $why});
1043 0         0 return;
1044             }
1045 0         0 $CPAN::Frontend->mywarn(qq{Package seems to come without Makefile.PL.
1046             (The test -f "$mpl" returned false.)
1047             Writing one on our own (setting NAME to $cf)\a\n});
1048 0         0 $self->{had_no_makefile_pl}++;
1049 0         0 $CPAN::Frontend->mysleep(3);
1050              
1051             # Writing our own Makefile.PL
1052              
1053 0         0 my $exefile_stanza = "";
1054 0 0       0 if ($self->{archived} eq "maybe_pl") {
1055 0         0 $exefile_stanza = $self->_exefile_stanza($build_dir,$local_file);
1056             }
1057              
1058 0         0 my $fh = FileHandle->new;
1059 0 0       0 $fh->open(">$mpl")
1060             or Carp::croak("Could not open >$mpl: $!");
1061 0         0 $fh->print(
1062             qq{# This Makefile.PL has been autogenerated by the module CPAN.pm
1063             # because there was no Makefile.PL supplied.
1064             # Autogenerated on: }.scalar localtime().qq{
1065              
1066             use ExtUtils::MakeMaker;
1067             WriteMakefile(
1068             NAME => q[$cf],$exefile_stanza
1069             );
1070             });
1071 0         0 $fh->close;
1072             }
1073             }
1074              
1075             #-> CPAN;:Distribution::_contains_crud
1076             sub _contains_crud {
1077 0     0   0 my($self,$dir) = @_;
1078 0         0 my(@dirs, $dh, @files);
1079 0 0       0 opendir $dh, $dir or return;
1080 0         0 my $dirent;
1081 0         0 for $dirent (readdir $dh) {
1082 0 0       0 next if $dirent =~ /^\.\.?$/;
1083 0         0 my $path = File::Spec->catdir($dir,$dirent);
1084 0 0       0 if (-d $path) {
    0          
1085 0         0 push @dirs, $dirent;
1086             } elsif (-f $path) {
1087 0         0 push @files, $dirent;
1088             }
1089             }
1090 0 0 0     0 if (@dirs && @files) {
    0          
1091 0         0 return "both files[@files] and directories[@dirs]";
1092             } elsif (@files > 2) {
1093 0         0 return "several files[@files] but no Makefile.PL or Build.PL";
1094             }
1095 0         0 return;
1096             }
1097              
1098             #-> CPAN;:Distribution::_exefile_stanza
1099             sub _exefile_stanza {
1100 0     0   0 my($self,$build_dir,$local_file) = @_;
1101              
1102 0         0 my $fh = FileHandle->new;
1103 0         0 my $script_file = File::Spec->catfile($build_dir,$local_file);
1104 0 0       0 $fh->open($script_file)
1105             or Carp::croak("Could not open script '$script_file': $!");
1106 0         0 local $/ = "\n";
1107             # parse name and prereq
1108 0         0 my($state) = "poddir";
1109 0         0 my($name, $prereq) = ("", "");
1110 0         0 while (<$fh>) {
1111 0 0 0     0 if ($state eq "poddir" && /^=head\d\s+(\S+)/) {
    0          
    0          
1112 0 0       0 if ($1 eq 'NAME') {
    0          
1113 0         0 $state = "name";
1114             } elsif ($1 eq 'PREREQUISITES') {
1115 0         0 $state = "prereq";
1116             }
1117             } elsif ($state =~ m{^(name|prereq)$}) {
1118 0 0       0 if (/^=/) {
    0          
    0          
    0          
1119 0         0 $state = "poddir";
1120             } elsif (/^\s*$/) {
1121             # nop
1122             } elsif ($state eq "name") {
1123 0 0       0 if ($name eq "") {
1124 0         0 ($name) = /^(\S+)/;
1125 0         0 $state = "poddir";
1126             }
1127             } elsif ($state eq "prereq") {
1128 0         0 $prereq .= $_;
1129             }
1130             } elsif (/^=cut\b/) {
1131 0         0 last;
1132             }
1133             }
1134 0         0 $fh->close;
1135              
1136 0         0 for ($name) {
1137 0         0 s{.*<}{}; # strip X<...>
1138 0         0 s{>.*}{};
1139             }
1140 0         0 chomp $prereq;
1141 0         0 $prereq = join " ", split /\s+/, $prereq;
1142             my($PREREQ_PM) = join("\n", map {
1143 0         0 s{.*<}{}; # strip X<...>
  0         0  
1144 0         0 s{>.*}{};
1145 0 0       0 if (/[\s\'\"]/) { # prose?
1146             } else {
1147 0         0 s/[^\w:]$//; # period?
1148 0         0 " "x28 . "'$_' => 0,";
1149             }
1150             } split /\s*,\s*/, $prereq);
1151              
1152 0 0       0 if ($name) {
1153 0         0 my $to_file = File::Spec->catfile($build_dir, $name);
1154 0 0       0 rename $script_file, $to_file
1155             or die "Can't rename $script_file to $to_file: $!";
1156             }
1157              
1158 0         0 return "
1159             EXE_FILES => ['$name'],
1160             PREREQ_PM => {
1161             $PREREQ_PM
1162             },
1163             ";
1164             }
1165              
1166             #-> CPAN::Distribution::_signature_business
1167             sub _signature_business {
1168 0     0   0 my($self) = @_;
1169 0         0 my $check_sigs = CPAN::HandleConfig->prefs_lookup($self,
1170             q{check_sigs});
1171 0 0       0 if ($check_sigs) {
1172 0 0       0 if ($CPAN::META->has_inst("Module::Signature")) {
1173 0 0       0 if (-f "SIGNATURE") {
1174 0 0       0 $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG;
1175 0         0 my $rv = Module::Signature::verify();
1176 0 0 0     0 if ($rv != Module::Signature::SIGNATURE_OK() and
1177             $rv != Module::Signature::SIGNATURE_MISSING()) {
1178 0         0 $CPAN::Frontend->mywarn(
1179             qq{\nSignature invalid for }.
1180             qq{distribution file. }.
1181             qq{Please investigate.\n\n}
1182             );
1183              
1184             my $wrap =
1185             sprintf(qq{I'd recommend removing %s. Some error occurred }.
1186             qq{while checking its signature, so it could }.
1187             qq{be invalid. Maybe you have configured }.
1188             qq{your 'urllist' with a bad URL. Please check this }.
1189             qq{array with 'o conf urllist' and retry. Or }.
1190             qq{examine the distribution in a subshell. Try
1191             look %s
1192             and run
1193             cpansign -v
1194             },
1195             $self->{localfile},
1196 0         0 $self->pretty_id,
1197             );
1198 0         0 $self->{signature_verify} = CPAN::Distrostatus->new("NO");
1199 0         0 $CPAN::Frontend->mywarn(Text::Wrap::wrap("","",$wrap));
1200 0 0       0 $CPAN::Frontend->mysleep(5) if $CPAN::Frontend->can("mysleep");
1201             } else {
1202 0         0 $self->{signature_verify} = CPAN::Distrostatus->new("YES");
1203 0 0       0 $self->debug("Module::Signature has verified") if $CPAN::DEBUG;
1204             }
1205             } else {
1206 0         0 $CPAN::Frontend->mywarn(qq{Package came without SIGNATURE\n\n});
1207             }
1208             } else {
1209 0 0       0 $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG;
1210             }
1211             }
1212             }
1213              
1214             #-> CPAN::Distribution::untar_me ;
1215             sub untar_me {
1216 0     0 0 0 my($self,$ct) = @_;
1217 0         0 $self->{archived} = "tar";
1218 0         0 my $result = eval { $ct->untar() };
  0         0  
1219 0 0       0 if ($result) {
1220 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("YES");
1221             } else {
1222             # unfortunately we have no $@ here, Tarzip is using mydie which dies with "\n"
1223 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- untar failed");
1224             }
1225             }
1226              
1227             # CPAN::Distribution::unzip_me ;
1228             sub unzip_me {
1229 0     0 0 0 my($self,$ct) = @_;
1230 0         0 $self->{archived} = "zip";
1231 0 0       0 if ($ct->unzip()) {
1232 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("YES");
1233             } else {
1234 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- unzip failed");
1235             }
1236 0         0 return;
1237             }
1238              
1239             sub handle_singlefile {
1240 0     0 0 0 my($self,$local_file) = @_;
1241              
1242 0 0       0 if ( $local_file =~ /\.pm(\.(gz|Z))?(?!\n)\Z/ ) {
    0          
1243 0         0 $self->{archived} = "pm";
1244             } elsif ( $local_file =~ /\.patch(\.(gz|bz2))?(?!\n)\Z/ ) {
1245 0         0 $self->{archived} = "patch";
1246             } else {
1247 0         0 $self->{archived} = "maybe_pl";
1248             }
1249              
1250 0         0 my $to = File::Basename::basename($local_file);
1251 0 0       0 if ($to =~ s/\.(gz|Z)(?!\n)\Z//) {
1252 0 0       0 if (eval{CPAN::Tarzip->new($local_file)->gunzip($to)}) {
  0         0  
1253 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("YES");
1254             } else {
1255 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- uncompressing failed");
1256             }
1257             } else {
1258 0 0       0 if (File::Copy::cp($local_file,".")) {
1259 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("YES");
1260             } else {
1261 0         0 $self->{unwrapped} = CPAN::Distrostatus->new("NO -- copying failed");
1262             }
1263             }
1264 0         0 return $to;
1265             }
1266              
1267             #-> sub CPAN::Distribution::new ;
1268             sub new {
1269 29     29 0 5033 my($class,%att) = @_;
1270              
1271             # $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new();
1272              
1273 29         113 my $this = { %att };
1274 29         138 return bless $this, $class;
1275             }
1276              
1277             #-> sub CPAN::Distribution::look ;
1278             sub look {
1279 0     0 0 0 my($self) = @_;
1280              
1281 0 0       0 if ($^O eq 'MacOS') {
1282 0         0 $self->Mac::BuildTools::look;
1283 0         0 return;
1284             }
1285              
1286 0 0       0 if ( $CPAN::Config->{'shell'} ) {
1287 0         0 $CPAN::Frontend->myprint(qq{
1288             Trying to open a subshell in the build directory...
1289             });
1290             } else {
1291 0         0 $CPAN::Frontend->myprint(qq{
1292             Your configuration does not define a value for subshells.
1293             Please define it with "o conf shell "
1294             });
1295 0         0 return;
1296             }
1297 0         0 my $dist = $self->id;
1298 0         0 my $dir;
1299 0 0       0 unless ($dir = $self->dir) {
1300 0         0 $self->get;
1301             }
1302 0 0 0     0 unless ($dir ||= $self->dir) {
1303 0         0 $CPAN::Frontend->mywarn(qq{
1304             Could not determine which directory to use for looking at $dist.
1305             });
1306 0         0 return;
1307             }
1308 0         0 my $pwd = CPAN::anycwd();
1309 0         0 $self->safe_chdir($dir);
1310 0         0 $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
1311             {
1312 0   0     0 local $ENV{CPAN_SHELL_LEVEL} = $ENV{CPAN_SHELL_LEVEL}||0;
  0         0  
1313 0         0 $ENV{CPAN_SHELL_LEVEL} += 1;
1314 0         0 my $shell = CPAN::HandleConfig->safe_quote($CPAN::Config->{'shell'});
1315              
1316             local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
1317             ? $ENV{PERL5LIB}
1318 0 0 0     0 : ($ENV{PERLLIB} || "");
1319              
1320 0 0       0 local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
1321             # local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # look
1322 0         0 $CPAN::META->set_perl5lib;
1323 0         0 local $ENV{MAKEFLAGS}; # protect us from outer make calls
1324              
1325 0 0       0 unless (system($shell) == 0) {
1326 0         0 my $code = $? >> 8;
1327 0         0 $CPAN::Frontend->mywarn("Subprocess shell exit code $code\n");
1328             }
1329             }
1330 0         0 $self->safe_chdir($pwd);
1331             }
1332              
1333             # CPAN::Distribution::cvs_import ;
1334             sub cvs_import {
1335 0     0 0 0 my($self) = @_;
1336 0         0 $self->get;
1337 0         0 my $dir = $self->dir;
1338              
1339 0         0 my $package = $self->called_for;
1340 0         0 my $module = $CPAN::META->instance('CPAN::Module', $package);
1341 0         0 my $version = $module->cpan_version;
1342              
1343 0         0 my $userid = $self->cpan_userid;
1344              
1345 0         0 my $cvs_dir = (split /\//, $dir)[-1];
1346 0         0 $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//;
1347             my $cvs_root =
1348 0   0     0 $CPAN::Config->{cvsroot} || $ENV{CVSROOT};
1349             my $cvs_site_perl =
1350 0   0     0 $CPAN::Config->{cvs_site_perl} || $ENV{CVS_SITE_PERL};
1351 0 0       0 if ($cvs_site_perl) {
1352 0         0 $cvs_dir = "$cvs_site_perl/$cvs_dir";
1353             }
1354 0         0 my $cvs_log = qq{"imported $package $version sources"};
1355 0         0 $version =~ s/\./_/g;
1356             # XXX cvs: undocumented and unclear how it was meant to work
1357 0         0 my @cmd = ('cvs', '-d', $cvs_root, 'import', '-m', $cvs_log,
1358             "$cvs_dir", $userid, "v$version");
1359              
1360 0         0 my $pwd = CPAN::anycwd();
1361 0 0       0 chdir($dir) or $CPAN::Frontend->mydie(qq{Could not chdir to "$dir": $!});
1362              
1363 0         0 $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
1364              
1365 0         0 $CPAN::Frontend->myprint(qq{@cmd\n});
1366 0 0       0 system(@cmd) == 0 or
1367             # XXX cvs
1368             $CPAN::Frontend->mydie("cvs import failed");
1369 0 0       0 chdir($pwd) or $CPAN::Frontend->mydie(qq{Could not chdir to "$pwd": $!});
1370             }
1371              
1372             #-> sub CPAN::Distribution::readme ;
1373             sub readme {
1374 0     0 0 0 my($self) = @_;
1375 0         0 my($dist) = $self->id;
1376 0         0 my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/;
1377 0 0       0 $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG;
1378 0         0 my($local_file);
1379             my($local_wanted) =
1380             File::Spec->catfile(
1381             $CPAN::Config->{keep_source_where},
1382 0         0 "authors",
1383             "id",
1384             split(/\//,"$sans.readme"),
1385             );
1386 0         0 my $readme = "authors/id/$sans.readme";
1387 0 0       0 $self->debug("Doing localize for '$readme'") if $CPAN::DEBUG;
1388 0 0       0 $local_file = CPAN::FTP->localize($readme,
1389             $local_wanted)
1390             or $CPAN::Frontend->mydie(qq{No $sans.readme found});
1391              
1392 0 0       0 if ($^O eq 'MacOS') {
1393 0         0 Mac::BuildTools::launch_file($local_file);
1394 0         0 return;
1395             }
1396              
1397 0         0 my $fh_pager = FileHandle->new;
1398 0         0 local($SIG{PIPE}) = "IGNORE";
1399 0   0     0 my $pager = $CPAN::Config->{'pager'} || "cat";
1400 0 0       0 $fh_pager->open("|$pager")
1401             or die "Could not open pager $pager\: $!";
1402 0         0 my $fh_readme = FileHandle->new;
1403 0 0       0 $fh_readme->open($local_file)
1404             or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!});
1405 0         0 $CPAN::Frontend->myprint(qq{
1406             Displaying file
1407             $local_file
1408             with pager "$pager"
1409             });
1410 0         0 $fh_pager->print(<$fh_readme>);
1411 0         0 $fh_pager->close;
1412             }
1413              
1414             #-> sub CPAN::Distribution::verifyCHECKSUM ;
1415             sub verifyCHECKSUM {
1416 0     0 0 0 my($self) = @_;
1417             EXCUSE: {
1418 0         0 my @e;
  0         0  
1419 0   0     0 $self->{CHECKSUM_STATUS} ||= "";
1420 0 0       0 $self->{CHECKSUM_STATUS} eq "OK" and push @e, "Checksum was ok";
1421 0 0 0     0 $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
  0         0  
1422             }
1423 0         0 my($lc_want,$lc_file,@local,$basename);
1424 0         0 @local = split(/\//,$self->id);
1425 0         0 pop @local;
1426 0         0 push @local, "CHECKSUMS";
1427             $lc_want =
1428             File::Spec->catfile($CPAN::Config->{keep_source_where},
1429 0         0 "authors", "id", @local);
1430 0         0 local($") = "/";
1431 0 0       0 if (my $size = -s $lc_want) {
1432 0 0       0 $self->debug("lc_want[$lc_want]size[$size]") if $CPAN::DEBUG;
1433 0 0       0 if ($self->CHECKSUM_check_file($lc_want,1)) {
1434 0         0 return $self->{CHECKSUM_STATUS} = "OK";
1435             }
1436             }
1437 0         0 $lc_file = CPAN::FTP->localize("authors/id/@local",
1438             $lc_want,1);
1439 0 0       0 unless ($lc_file) {
1440 0         0 $CPAN::Frontend->myprint("Trying $lc_want.gz\n");
1441 0         0 $local[-1] .= ".gz";
1442 0         0 $lc_file = CPAN::FTP->localize("authors/id/@local",
1443             "$lc_want.gz",1);
1444 0 0       0 if ($lc_file) {
1445 0         0 $lc_file =~ s/\.gz(?!\n)\Z//;
1446 0         0 eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)};
  0         0  
1447             } else {
1448 0         0 return;
1449             }
1450             }
1451 0 0       0 if ($self->CHECKSUM_check_file($lc_file)) {
1452 0         0 return $self->{CHECKSUM_STATUS} = "OK";
1453             }
1454             }
1455              
1456             #-> sub CPAN::Distribution::SIG_check_file ;
1457             sub SIG_check_file {
1458 0     0 0 0 my($self,$chk_file) = @_;
1459 0         0 my $rv = eval { Module::Signature::_verify($chk_file) };
  0         0  
1460              
1461 0 0       0 if ($rv == Module::Signature::SIGNATURE_OK()) {
1462 0         0 $CPAN::Frontend->myprint("Signature for $chk_file ok\n");
1463 0         0 return $self->{SIG_STATUS} = "OK";
1464             } else {
1465 0         0 $CPAN::Frontend->myprint(qq{\nSignature invalid for }.
1466             qq{distribution file. }.
1467             qq{Please investigate.\n\n}.
1468             $self->as_string,
1469             $CPAN::META->instance(
1470             'CPAN::Author',
1471             $self->cpan_userid
1472             )->as_string);
1473              
1474 0         0 my $wrap = qq{I\'d recommend removing $chk_file. Its signature
1475             is invalid. Maybe you have configured your 'urllist' with
1476             a bad URL. Please check this array with 'o conf urllist', and
1477             retry.};
1478              
1479 0         0 $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap));
1480             }
1481             }
1482              
1483             #-> sub CPAN::Distribution::CHECKSUM_check_file ;
1484              
1485             # sloppy is 1 when we have an old checksums file that maybe is good
1486             # enough
1487              
1488             sub CHECKSUM_check_file {
1489 0     0 0 0 my($self,$chk_file,$sloppy) = @_;
1490 0         0 my($cksum,$file,$basename);
1491              
1492 0   0     0 $sloppy ||= 0;
1493 0 0       0 $self->debug("chk_file[$chk_file]sloppy[$sloppy]") if $CPAN::DEBUG;
1494 0         0 my $check_sigs = CPAN::HandleConfig->prefs_lookup($self,
1495             q{check_sigs});
1496 0 0       0 if ($check_sigs) {
1497 0 0       0 if ($CPAN::META->has_inst("Module::Signature")) {
1498 0 0       0 $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG;
1499 0         0 $self->SIG_check_file($chk_file);
1500             } else {
1501 0 0       0 $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG;
1502             }
1503             }
1504              
1505 0         0 $file = $self->{localfile};
1506 0         0 $basename = File::Basename::basename($file);
1507 0         0 my $fh = FileHandle->new;
1508 0 0       0 if (open $fh, $chk_file) {
1509 0         0 local($/);
1510 0         0 my $eval = <$fh>;
1511 0         0 $eval =~ s/\015?\012/\n/g;
1512 0         0 close $fh;
1513 0         0 my($compmt) = Safe->new();
1514 0         0 $cksum = $compmt->reval($eval);
1515 0 0       0 if ($@) {
1516 0         0 rename $chk_file, "$chk_file.bad";
1517 0 0       0 Carp::confess($@) if $@;
1518             }
1519             } else {
1520 0         0 Carp::carp "Could not open $chk_file for reading";
1521             }
1522              
1523 0 0 0     0 if (! ref $cksum or ref $cksum ne "HASH") {
    0          
1524 0         0 $CPAN::Frontend->mywarn(qq{
1525             Warning: checksum file '$chk_file' broken.
1526              
1527             When trying to read that file I expected to get a hash reference
1528             for further processing, but got garbage instead.
1529             });
1530 0         0 my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed nonetheless?", "no");
1531 0 0       0 $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n");
1532 0         0 $self->{CHECKSUM_STATUS} = "NIL -- CHECKSUMS file broken";
1533 0         0 return;
1534             } elsif (exists $cksum->{$basename}{sha256}) {
1535 0 0       0 $self->debug("Found checksum for $basename:" .
1536             "$cksum->{$basename}{sha256}\n") if $CPAN::DEBUG;
1537              
1538 0         0 open($fh, $file);
1539 0         0 binmode $fh;
1540 0         0 my $eq = $self->eq_CHECKSUM($fh,$cksum->{$basename}{sha256});
1541 0         0 $fh->close;
1542 0         0 $fh = CPAN::Tarzip->TIEHANDLE($file);
1543              
1544 0 0       0 unless ($eq) {
1545 0         0 my $dg = Digest::SHA->new(256);
1546 0         0 my($data,$ref);
1547 0         0 $ref = \$data;
1548 0         0 while ($fh->READ($ref, 4096) > 0) {
1549 0         0 $dg->add($data);
1550             }
1551 0         0 my $hexdigest = $dg->hexdigest;
1552 0         0 $eq += $hexdigest eq $cksum->{$basename}{'sha256-ungz'};
1553             }
1554              
1555 0 0       0 if ($eq) {
1556 0         0 $CPAN::Frontend->myprint("Checksum for $file ok\n");
1557 0         0 return $self->{CHECKSUM_STATUS} = "OK";
1558             } else {
1559 0         0 $CPAN::Frontend->myprint(qq{\nChecksum mismatch for }.
1560             qq{distribution file. }.
1561             qq{Please investigate.\n\n}.
1562             $self->as_string,
1563             $CPAN::META->instance(
1564             'CPAN::Author',
1565             $self->cpan_userid
1566             )->as_string);
1567              
1568 0         0 my $wrap = qq{I\'d recommend removing $file. Its
1569             checksum is incorrect. Maybe you have configured your 'urllist' with
1570             a bad URL. Please check this array with 'o conf urllist', and
1571             retry.};
1572              
1573 0         0 $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap));
1574              
1575             # former versions just returned here but this seems a
1576             # serious threat that deserves a die
1577              
1578             # $CPAN::Frontend->myprint("\n\n");
1579             # sleep 3;
1580             # return;
1581             }
1582             # close $fh if fileno($fh);
1583             } else {
1584 0 0       0 return if $sloppy;
1585 0 0       0 unless ($self->{CHECKSUM_STATUS}) {
1586 0         0 $CPAN::Frontend->mywarn(qq{
1587             Warning: No checksum for $basename in $chk_file.
1588              
1589             The cause for this may be that the file is very new and the checksum
1590             has not yet been calculated, but it may also be that something is
1591             going awry right now.
1592             });
1593 0         0 my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed?", "yes");
1594 0 0       0 $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n");
1595             }
1596 0         0 $self->{CHECKSUM_STATUS} = "NIL -- distro not in CHECKSUMS file";
1597 0         0 return;
1598             }
1599             }
1600              
1601             #-> sub CPAN::Distribution::eq_CHECKSUM ;
1602             sub eq_CHECKSUM {
1603 0     0 0 0 my($self,$fh,$expect) = @_;
1604 0 0       0 if ($CPAN::META->has_inst("Digest::SHA")) {
1605 0         0 my $dg = Digest::SHA->new(256);
1606 0         0 my($data);
1607 0         0 while (read($fh, $data, 4096)) {
1608 0         0 $dg->add($data);
1609             }
1610 0         0 my $hexdigest = $dg->hexdigest;
1611             # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]";
1612 0         0 return $hexdigest eq $expect;
1613             }
1614 0         0 return 1;
1615             }
1616              
1617             #-> sub CPAN::Distribution::force ;
1618              
1619             # Both CPAN::Modules and CPAN::Distributions know if "force" is in
1620             # effect by autoinspection, not by inspecting a global variable. One
1621             # of the reason why this was chosen to work that way was the treatment
1622             # of dependencies. They should not automatically inherit the force
1623             # status. But this has the downside that ^C and die() will return to
1624             # the prompt but will not be able to reset the force_update
1625             # attributes. We try to correct for it currently in the read_metadata
1626             # routine, and immediately before we check for a Signal. I hope this
1627             # works out in one of v1.57_53ff
1628              
1629             # "Force get forgets previous error conditions"
1630              
1631             #-> sub CPAN::Distribution::fforce ;
1632             sub fforce {
1633 0     0 0 0 my($self, $method) = @_;
1634 0         0 $self->force($method,1);
1635             }
1636              
1637             #-> sub CPAN::Distribution::force ;
1638             sub force {
1639 0     0 0 0 my($self, $method,$fforce) = @_;
1640 0         0 my %phase_map = (
1641             get => [
1642             "unwrapped",
1643             "build_dir",
1644             "archived",
1645             "localfile",
1646             "CHECKSUM_STATUS",
1647             "signature_verify",
1648             "prefs",
1649             "prefs_file",
1650             "prefs_file_doc",
1651             "cleanup_after_install_done",
1652             ],
1653             make => [
1654             "writemakefile",
1655             "make",
1656             "modulebuild",
1657             "prereq_pm",
1658             "cleanup_after_install_done",
1659             ],
1660             test => [
1661             "badtestcnt",
1662             "make_test",
1663             "cleanup_after_install_done",
1664             ],
1665             install => [
1666             "install",
1667             "cleanup_after_install_done",
1668             ],
1669             unknown => [
1670             "reqtype",
1671             "yaml_content",
1672             "cleanup_after_install_done",
1673             ],
1674             );
1675 0         0 my $methodmatch = 0;
1676 0         0 my $ldebug = 0;
1677 0         0 PHASE: for my $phase (qw(unknown get make test install)) { # order matters
1678 0 0 0     0 $methodmatch = 1 if $fforce || ($method && $phase eq $method);
      0        
1679 0 0       0 next unless $methodmatch;
1680 0         0 ATTRIBUTE: for my $att (@{$phase_map{$phase}}) {
  0         0  
1681 0 0       0 if ($phase eq "get") {
    0          
1682 0 0 0     0 if (substr($self->id,-1,1) eq "."
1683             && $att =~ /(unwrapped|build_dir|archived)/ ) {
1684             # cannot be undone for local distros
1685 0         0 next ATTRIBUTE;
1686             }
1687 0 0 0     0 if ($att eq "build_dir"
      0        
1688             && $self->{build_dir}
1689             && $CPAN::META->{is_tested}
1690             ) {
1691 0         0 delete $CPAN::META->{is_tested}{$self->{build_dir}};
1692             }
1693             } elsif ($phase eq "test") {
1694 0 0 0     0 if ($att eq "make_test"
      0        
      0        
1695             && $self->{make_test}
1696             && $self->{make_test}{COMMANDID}
1697             && $self->{make_test}{COMMANDID} == $CPAN::CurrentCommandId
1698             ) {
1699             # endless loop too likely
1700 0         0 next ATTRIBUTE;
1701             }
1702             }
1703 0         0 delete $self->{$att};
1704 0 0 0     0 if ($ldebug || $CPAN::DEBUG) {
1705             # local $CPAN::DEBUG = 16; # Distribution
1706 0         0 CPAN->debug(sprintf "id[%s]phase[%s]att[%s]", $self->id, $phase, $att);
1707             }
1708             }
1709             }
1710 0 0 0     0 if ($method && $method =~ /make|test|install/) {
1711 0         0 $self->{force_update} = 1; # name should probably have been force_install
1712             }
1713             }
1714              
1715             #-> sub CPAN::Distribution::notest ;
1716             sub notest {
1717 0     0 0 0 my($self, $method) = @_;
1718             # $CPAN::Frontend->mywarn("XDEBUG: set notest for $self $method");
1719 0         0 $self->{"notest"}++; # name should probably have been force_install
1720             }
1721              
1722             #-> sub CPAN::Distribution::unnotest ;
1723             sub unnotest {
1724 0     0 0 0 my($self) = @_;
1725             # warn "XDEBUG: deleting notest";
1726 0         0 delete $self->{notest};
1727             }
1728              
1729             #-> sub CPAN::Distribution::unforce ;
1730             sub unforce {
1731 0     0 0 0 my($self) = @_;
1732 0         0 delete $self->{force_update};
1733             }
1734              
1735             #-> sub CPAN::Distribution::isa_perl ;
1736             sub isa_perl {
1737 0     0 0 0 my($self) = @_;
1738 0         0 my $file = File::Basename::basename($self->id);
1739 0 0 0     0 if ($file =~ m{ ^ perl
    0          
1740             (
1741             -(5\.\d+\.\d+)
1742             |
1743             (5)[._-](00[0-5](?:_[0-4][0-9])?)
1744             )
1745             \.tar[._-](?:gz|bz2)
1746             (?!\n)\Z
1747             }xs) {
1748 0         0 my $perl_version;
1749 0 0       0 if ($2) {
1750 0         0 $perl_version = $2;
1751             } else {
1752 0         0 $perl_version = "$3.$4";
1753             }
1754 0         0 return $perl_version;
1755             } elsif ($self->cpan_comment
1756             &&
1757             $self->cpan_comment =~ /isa_perl\(.+?\)/) {
1758 0         0 return $1;
1759             }
1760             }
1761              
1762              
1763             #-> sub CPAN::Distribution::perl ;
1764             sub perl {
1765 0     0 0 0 my ($self) = @_;
1766 0 0       0 if (! $self) {
1767 13     13   172 use Carp qw(carp);
  13         36  
  13         235416  
1768 0         0 carp __PACKAGE__ . "::perl was called without parameters.";
1769             }
1770 0         0 return CPAN::HandleConfig->safe_quote($CPAN::Perl);
1771             }
1772              
1773             #-> sub CPAN::Distribution::shortcut_prepare ;
1774             # return values: undef means don't shortcut; 0 means shortcut as fail;
1775             # and 1 means shortcut as success
1776              
1777             sub shortcut_prepare {
1778 0     0 0 0 my ($self) = @_;
1779              
1780 0 0       0 $self->debug("checking archive type[$self->{ID}]") if $CPAN::DEBUG;
1781 0 0 0     0 if (!$self->{archived} || $self->{archived} eq "NO") {
1782 0         0 return $self->goodbye("Is neither a tar nor a zip archive.");
1783             }
1784              
1785 0 0       0 $self->debug("checking unwrapping[$self->{ID}]") if $CPAN::DEBUG;
1786 0 0 0     0 if (!$self->{unwrapped}
    0          
1787             || (
1788             UNIVERSAL::can($self->{unwrapped},"failed") ?
1789             $self->{unwrapped}->failed :
1790             $self->{unwrapped} =~ /^NO/
1791             )) {
1792 0         0 return $self->goodbye("Had problems unarchiving. Please build manually");
1793             }
1794              
1795 0 0       0 $self->debug("checking signature[$self->{ID}]") if $CPAN::DEBUG;
1796 0 0 0     0 if ( ! $self->{force_update}
    0 0        
1797             && exists $self->{signature_verify}
1798             && (
1799             UNIVERSAL::can($self->{signature_verify},"failed") ?
1800             $self->{signature_verify}->failed :
1801             $self->{signature_verify} =~ /^NO/
1802             )
1803             ) {
1804 0         0 return $self->goodbye("Did not pass the signature test.");
1805             }
1806              
1807 0 0       0 $self->debug("checking writemakefile[$self->{ID}]") if $CPAN::DEBUG;
1808 0 0       0 if ($self->{writemakefile}) {
1809 0 0       0 if (
    0          
1810             UNIVERSAL::can($self->{writemakefile},"failed") ?
1811             $self->{writemakefile}->failed :
1812             $self->{writemakefile} =~ /^NO/
1813             ) {
1814             # XXX maybe a retry would be in order?
1815             my $err = UNIVERSAL::can($self->{writemakefile},"text") ?
1816             $self->{writemakefile}->text :
1817 0 0       0 $self->{writemakefile};
1818 0         0 $err =~ s/^NO\s*(--\s+)?//;
1819 0   0     0 $err ||= "Had some problem writing Makefile";
1820 0         0 $err .= ", not re-running";
1821 0         0 return $self->goodbye($err);
1822             } else {
1823 0         0 return $self->success("Has already been prepared");
1824             }
1825             }
1826              
1827 0 0       0 $self->debug("checking configure_requires_later[$self->{ID}]") if $CPAN::DEBUG;
1828 0 0       0 if( my $later = $self->{configure_requires_later} ) { # see also undelay
1829 0         0 return $self->goodbye($later);
1830             }
1831              
1832 0         0 return undef; # no shortcut
1833             }
1834              
1835             sub prepare {
1836 0     0 0 0 my ($self) = @_;
1837              
1838 0 0       0 $self->get
1839             or return;
1840              
1841 0 0       0 if ( defined( my $sc = $self->shortcut_prepare) ) {
1842 0         0 return $sc;
1843             }
1844              
1845             local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
1846             ? $ENV{PERL5LIB}
1847 0 0 0     0 : ($ENV{PERLLIB} || "");
1848 0 0       0 local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
1849 0 0       0 local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # prepare
1850 0         0 $CPAN::META->set_perl5lib;
1851 0         0 local $ENV{MAKEFLAGS}; # protect us from outer make calls
1852              
1853 0 0       0 if ($CPAN::Signal) {
1854 0         0 delete $self->{force_update};
1855 0         0 return;
1856             }
1857              
1858 0 0       0 my $builddir = $self->dir or
1859             $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n");
1860              
1861 0 0       0 unless (chdir $builddir) {
1862 0         0 $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!");
1863 0         0 return;
1864             }
1865              
1866 0 0       0 if ($CPAN::Signal) {
1867 0         0 delete $self->{force_update};
1868 0         0 return;
1869             }
1870              
1871 0 0       0 $self->debug("Changed directory to $builddir") if $CPAN::DEBUG;
1872              
1873 0   0     0 local $ENV{PERL_AUTOINSTALL} = $ENV{PERL_AUTOINSTALL} || '';
1874 0   0     0 local $ENV{PERL_EXTUTILS_AUTOINSTALL} = $ENV{PERL_EXTUTILS_AUTOINSTALL} || '';
1875 0 0       0 $self->choose_MM_or_MB
1876             or return;
1877              
1878             my $configurator = $self->{configure} ? "Configure"
1879 0 0       0 : $self->{modulebuild} ? "Build.PL"
    0          
1880             : "Makefile.PL";
1881              
1882 0         0 $CPAN::Frontend->myprint("Configuring ".$self->id." with $configurator\n");
1883              
1884 0 0       0 if ($CPAN::Config->{prerequisites_policy} eq "follow") {
1885 0   0     0 $ENV{PERL_AUTOINSTALL} ||= "--defaultdeps";
1886 0   0     0 $ENV{PERL_EXTUTILS_AUTOINSTALL} ||= "--defaultdeps";
1887             }
1888              
1889 0         0 my $system;
1890             my $pl_commandline;
1891 0 0       0 if ($self->prefs->{pl}) {
1892 0         0 $pl_commandline = $self->prefs->{pl}{commandline};
1893             }
1894 0 0       0 local $ENV{PERL} = defined $ENV{PERL}? $ENV{PERL} : $^X;
1895 0   0     0 local $ENV{PERL5_CPAN_IS_EXECUTING} = $ENV{PERL5_CPAN_IS_EXECUTING} || '';
1896 0 0       0 local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
1897 0 0       0 local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
1898 0 0       0 if ($pl_commandline) {
    0          
    0          
1899 0         0 $system = $pl_commandline;
1900 0         0 $ENV{PERL} = $^X;
1901             } elsif ($self->{'configure'}) {
1902 0         0 $system = $self->{'configure'};
1903             } elsif ($self->{modulebuild}) {
1904 0 0       0 my($perl) = $self->perl or die "Couldn\'t find executable perl\n";
1905 0         0 my $mbuildpl_arg = $self->_make_phase_arg("pl");
1906 0 0       0 $system = sprintf("%s Build.PL%s",
1907             $perl,
1908             $mbuildpl_arg ? " $mbuildpl_arg" : "",
1909             );
1910             } else {
1911 0 0       0 my($perl) = $self->perl or die "Couldn\'t find executable perl\n";
1912 0         0 my $switch = "";
1913             # This needs a handler that can be turned on or off:
1914             # $switch = "-MExtUtils::MakeMaker ".
1915             # "-Mops=:default,:filesys_read,:filesys_open,require,chdir"
1916             # if $] > 5.00310;
1917 0         0 my $makepl_arg = $self->_make_phase_arg("pl");
1918             $ENV{PERL5_CPAN_IS_EXECUTING} = File::Spec->catfile($self->{build_dir},
1919 0         0 "Makefile.PL");
1920 0 0       0 $system = sprintf("%s%s Makefile.PL%s",
    0          
1921             $perl,
1922             $switch ? " $switch" : "",
1923             $makepl_arg ? " $makepl_arg" : "",
1924             );
1925             }
1926 0         0 my $pl_env;
1927 0 0       0 if ($self->prefs->{pl}) {
1928 0         0 $pl_env = $self->prefs->{pl}{env};
1929             }
1930 0 0       0 local @ENV{keys %$pl_env} = values %$pl_env if $pl_env;
1931 0 0       0 if (exists $self->{writemakefile}) {
1932             } else {
1933 0     0   0 local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" };
  0         0  
1934 0         0 my($ret,$pid,$output);
1935 0         0 $@ = "";
1936 0         0 my $go_via_alarm;
1937 0 0       0 if ($CPAN::Config->{inactivity_timeout}) {
1938 0         0 require Config;
1939 0 0 0     0 if ($Config::Config{d_alarm}
1940             &&
1941             $Config::Config{d_alarm} eq "define"
1942             ) {
1943 0         0 $go_via_alarm++
1944             } else {
1945 0         0 $CPAN::Frontend->mywarn("Warning: you have configured the config ".
1946             "variable 'inactivity_timeout' to ".
1947             "'$CPAN::Config->{inactivity_timeout}'. But ".
1948             "on this machine the system call 'alarm' ".
1949             "isn't available. This means that we cannot ".
1950             "provide the feature of intercepting long ".
1951             "waiting code and will turn this feature off.\n"
1952             );
1953 0         0 $CPAN::Config->{inactivity_timeout} = 0;
1954             }
1955             }
1956 0 0       0 if ($go_via_alarm) {
1957 0 0       0 if ( $self->_should_report('pl') ) {
1958             ($output, $ret) = CPAN::Reporter::record_command(
1959             $system,
1960             $CPAN::Config->{inactivity_timeout},
1961 0         0 );
1962 0         0 CPAN::Reporter::grade_PL( $self, $system, $output, $ret );
1963             }
1964             else {
1965 0         0 eval {
1966 0         0 alarm $CPAN::Config->{inactivity_timeout};
1967 0         0 local $SIG{CHLD}; # = sub { wait };
1968 0 0       0 if (defined($pid = fork)) {
1969 0 0       0 if ($pid) { #parent
1970             # wait;
1971 0         0 waitpid $pid, 0;
1972             } else { #child
1973             # note, this exec isn't necessary if
1974             # inactivity_timeout is 0. On the Mac I'd
1975             # suggest, we set it always to 0.
1976 0         0 exec $system;
1977             }
1978             } else {
1979 0         0 $CPAN::Frontend->myprint("Cannot fork: $!");
1980 0         0 return;
1981             }
1982             };
1983 0         0 alarm 0;
1984 0 0       0 if ($@) {
1985 0         0 kill 9, $pid;
1986 0         0 waitpid $pid, 0;
1987 0         0 my $err = "$@";
1988 0         0 $CPAN::Frontend->myprint($err);
1989 0         0 $self->{writemakefile} = CPAN::Distrostatus->new("NO $err");
1990 0         0 $@ = "";
1991 0         0 $self->store_persistent_state;
1992 0         0 return $self->goodbye("$system -- TIMED OUT");
1993             }
1994             }
1995             } else {
1996 0 0       0 if (my $expect_model = $self->_prefs_with_expect("pl")) {
    0          
1997             # XXX probably want to check _should_report here and warn
1998             # about not being able to use CPAN::Reporter with expect
1999 0         0 $ret = $self->_run_via_expect($system,'writemakefile',$expect_model);
2000 0 0 0     0 if (! defined $ret
      0        
2001             && $self->{writemakefile}
2002             && $self->{writemakefile}->failed) {
2003             # timeout
2004 0         0 return;
2005             }
2006             }
2007             elsif ( $self->_should_report('pl') ) {
2008 0         0 ($output, $ret) = eval { CPAN::Reporter::record_command($system) };
  0         0  
2009 0 0 0     0 if (! defined $output or $@) {
2010 0   0     0 my $err = $@ || "Unknown error";
2011 0         0 $CPAN::Frontend->mywarn("Error while running PL phase: $err\n");
2012 0         0 $self->{writemakefile} = CPAN::Distrostatus
2013             ->new("NO '$system' returned status $ret and no output");
2014 0         0 return $self->goodbye("$system -- NOT OK");
2015             }
2016 0         0 CPAN::Reporter::grade_PL( $self, $system, $output, $ret );
2017             }
2018             else {
2019 0         0 $ret = system($system);
2020             }
2021 0 0       0 if ($ret != 0) {
2022 0         0 $self->{writemakefile} = CPAN::Distrostatus
2023             ->new("NO '$system' returned status $ret");
2024 0         0 $CPAN::Frontend->mywarn("Warning: No success on command[$system]\n");
2025 0         0 $self->store_persistent_state;
2026 0         0 return $self->goodbye("$system -- NOT OK");
2027             }
2028             }
2029 0 0 0     0 if (-f "Makefile" || -f "Build" || ($^O eq 'VMS' && (-f 'descrip.mms' || -f 'Build.com'))) {
      0        
      0        
      0        
2030 0         0 $self->{writemakefile} = CPAN::Distrostatus->new("YES");
2031 0         0 delete $self->{make_clean}; # if cleaned before, enable next
2032 0         0 $self->store_persistent_state;
2033 0         0 return $self->success("$system -- OK");
2034             } else {
2035 0 0       0 my $makefile = $self->{modulebuild} ? "Build" : "Makefile";
2036 0         0 my $why = "No '$makefile' created";
2037 0         0 $CPAN::Frontend->mywarn($why);
2038 0         0 $self->{writemakefile} = CPAN::Distrostatus
2039             ->new(qq{NO -- $why\n});
2040 0         0 $self->store_persistent_state;
2041 0         0 return $self->goodbye("$system -- NOT OK");
2042             }
2043             }
2044 0         0 $self->store_persistent_state;
2045 0         0 return 1; # success
2046             }
2047              
2048             #-> sub CPAN::Distribution::shortcut_make ;
2049             # return values: undef means don't shortcut; 0 means shortcut as fail;
2050             # and 1 means shortcut as success
2051             sub shortcut_make {
2052 0     0 0 0 my ($self) = @_;
2053              
2054 0 0       0 $self->debug("checking make/build results[$self->{ID}]") if $CPAN::DEBUG;
2055 0 0       0 if (defined $self->{make}) {
2056 0 0       0 if (UNIVERSAL::can($self->{make},"failed") ?
    0          
2057             $self->{make}->failed :
2058             $self->{make} =~ /^NO/
2059             ) {
2060 0 0       0 if ($self->{force_update}) {
2061             # Trying an already failed 'make' (unless somebody else blocks)
2062 0         0 return undef; # no shortcut
2063             } else {
2064             # introduced for turning recursion detection into a distrostatus
2065             my $error = length $self->{make}>3
2066 0 0       0 ? substr($self->{make},3) : "Unknown error";
2067 0         0 $self->store_persistent_state;
2068 0         0 return $self->goodbye("Could not make: $error\n");
2069             }
2070             } else {
2071 0         0 return $self->success("Has already been made")
2072             }
2073             }
2074 0         0 return undef; # no shortcut
2075             }
2076              
2077             #-> sub CPAN::Distribution::make ;
2078             sub make {
2079 0     0 0 0 my($self) = @_;
2080              
2081 0         0 $self->pre_make();
2082              
2083 0 0       0 if (exists $self->{cleanup_after_install_done}) {
2084 0         0 return $self->get;
2085             }
2086              
2087 0 0       0 $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
2088 0 0       0 if (my $goto = $self->prefs->{goto}) {
2089 0         0 return $self->goto($goto);
2090             }
2091             # Emergency brake if they said install Pippi and get newest perl
2092              
2093             # XXX Would this make more sense in shortcut_prepare, since
2094             # that doesn't make sense on a perl dist either? Broader
2095             # question: what is the purpose of suggesting force install
2096             # on a perl distribution? That seems unlikely to result in
2097             # such a dependency being satisfied, even if the perl is
2098             # successfully installed. This situation is tantamount to
2099             # a prereq on a version of perl greater than the current one
2100             # so I think we should just abort. -- xdg, 2012-04-06
2101 0 0       0 if ($self->isa_perl) {
2102 0 0 0     0 if (
2103             $self->called_for ne $self->id &&
2104             ! $self->{force_update}
2105             ) {
2106             # if we die here, we break bundles
2107 0         0 $CPAN::Frontend
2108             ->mywarn(sprintf(
2109             qq{The most recent version "%s" of the module "%s"
2110             is part of the perl-%s distribution. To install that, you need to run
2111             force install %s --or--
2112             install %s
2113             },
2114             $CPAN::META->instance(
2115             'CPAN::Module',
2116             $self->called_for
2117             )->cpan_version,
2118             $self->called_for,
2119             $self->isa_perl,
2120             $self->called_for,
2121             $self->pretty_id,
2122             ));
2123 0         0 $self->{make} = CPAN::Distrostatus->new("NO isa perl");
2124 0         0 $CPAN::Frontend->mysleep(1);
2125 0         0 return;
2126             }
2127             }
2128              
2129             $self->prepare
2130 0 0       0 or return;
2131              
2132 0 0       0 if ( defined( my $sc = $self->shortcut_make) ) {
2133 0         0 return $sc;
2134             }
2135              
2136 0 0       0 if ($CPAN::Signal) {
2137 0         0 delete $self->{force_update};
2138 0         0 return;
2139             }
2140              
2141 0 0       0 my $builddir = $self->dir or
2142             $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n");
2143              
2144 0 0       0 unless (chdir $builddir) {
2145 0         0 $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!");
2146 0         0 return;
2147             }
2148              
2149 0 0       0 my $make = $self->{modulebuild} ? "Build" : "make";
2150 0         0 $CPAN::Frontend->myprint(sprintf "Running %s for %s\n", $make, $self->id);
2151             local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
2152             ? $ENV{PERL5LIB}
2153 0 0 0     0 : ($ENV{PERLLIB} || "");
2154 0 0       0 local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
2155 0 0       0 local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # make
2156 0         0 $CPAN::META->set_perl5lib;
2157 0         0 local $ENV{MAKEFLAGS}; # protect us from outer make calls
2158              
2159 0 0       0 if ($CPAN::Signal) {
2160 0         0 delete $self->{force_update};
2161 0         0 return;
2162             }
2163              
2164 0 0       0 if ($^O eq 'MacOS') {
2165 0         0 Mac::BuildTools::make($self);
2166 0         0 return;
2167             }
2168              
2169 0         0 my %env;
2170 0         0 while (my($k,$v) = each %ENV) {
2171 0 0       0 next if defined $v;
2172 0         0 $env{$k} = '';
2173             }
2174 0         0 local @ENV{keys %env} = values %env;
2175 0         0 my $satisfied = eval { $self->satisfy_requires };
  0         0  
2176 0 0       0 return $self->goodbye($@) if $@;
2177 0 0       0 return unless $satisfied ;
2178 0 0       0 if ($CPAN::Signal) {
2179 0         0 delete $self->{force_update};
2180 0         0 return;
2181             }
2182              
2183             # need to chdir again, because $self->satisfy_requires might change the directory
2184 0 0       0 unless (chdir $builddir) {
2185 0         0 $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!");
2186 0         0 return;
2187             }
2188              
2189 0         0 my $system;
2190             my $make_commandline;
2191 0 0       0 if ($self->prefs->{make}) {
2192 0         0 $make_commandline = $self->prefs->{make}{commandline};
2193             }
2194 0 0       0 local $ENV{PERL} = defined $ENV{PERL}? $ENV{PERL} : $^X;
2195 0 0       0 local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
2196 0 0       0 local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
2197 0 0       0 if ($make_commandline) {
2198 0         0 $system = $make_commandline;
2199 0         0 $ENV{PERL} = CPAN::find_perl();
2200             } else {
2201 0 0       0 if ($self->{modulebuild}) {
2202 0 0 0     0 unless (-f "Build" || ($^O eq 'VMS' && -f 'Build.com')) {
      0        
2203 0         0 my $cwd = CPAN::anycwd();
2204 0         0 $CPAN::Frontend->mywarn("Alert: no Build file available for 'make $self->{id}'".
2205             " in cwd[$cwd]. Danger, Will Robinson!\n");
2206 0         0 $CPAN::Frontend->mysleep(5);
2207             }
2208 0         0 $system = join " ", $self->_build_command(), $CPAN::Config->{mbuild_arg};
2209             } else {
2210 0         0 $system = join " ", $self->_make_command(), $CPAN::Config->{make_arg};
2211             }
2212 0         0 $system =~ s/\s+$//;
2213 0         0 my $make_arg = $self->_make_phase_arg("make");
2214 0 0       0 $system = sprintf("%s%s",
2215             $system,
2216             $make_arg ? " $make_arg" : "",
2217             );
2218             }
2219 0         0 my $make_env;
2220 0 0       0 if ($self->prefs->{make}) {
2221 0         0 $make_env = $self->prefs->{make}{env};
2222             }
2223 0 0       0 local @ENV{keys %$make_env} = values %$make_env if $make_env;
2224 0         0 my $expect_model = $self->_prefs_with_expect("make");
2225 0         0 my $want_expect = 0;
2226 0 0 0     0 if ( $expect_model && @{$expect_model->{talk}} ) {
  0         0  
2227 0         0 my $can_expect = $CPAN::META->has_inst("Expect");
2228 0 0       0 if ($can_expect) {
2229 0         0 $want_expect = 1;
2230             } else {
2231 0         0 $CPAN::Frontend->mywarn("Expect not installed, falling back to ".
2232             "system()\n");
2233             }
2234             }
2235 0         0 my ($system_ok, $system_err);
2236 0 0       0 if ($want_expect) {
    0          
2237             # XXX probably want to check _should_report here and
2238             # warn about not being able to use CPAN::Reporter with expect
2239 0         0 $system_ok = $self->_run_via_expect($system,'make',$expect_model) == 0;
2240             }
2241             elsif ( $self->_should_report('make') ) {
2242 0         0 my ($output, $ret) = CPAN::Reporter::record_command($system);
2243 0         0 CPAN::Reporter::grade_make( $self, $system, $output, $ret );
2244 0         0 $system_ok = ! $ret;
2245             }
2246             else {
2247 0         0 my $rc = system($system);
2248 0         0 $system_ok = $rc == 0;
2249 0 0       0 $system_err = $! if $rc == -1;
2250             }
2251 0         0 $self->introduce_myself;
2252 0 0       0 if ( $system_ok ) {
2253 0         0 $CPAN::Frontend->myprint(" $system -- OK\n");
2254 0         0 $self->{make} = CPAN::Distrostatus->new("YES");
2255             } else {
2256 0   0     0 $self->{writemakefile} ||= CPAN::Distrostatus->new("YES");
2257 0         0 $self->{make} = CPAN::Distrostatus->new("NO");
2258 0         0 $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
2259 0 0       0 $CPAN::Frontend->mywarn(" $system_err\n") if defined $system_err;
2260             }
2261 0         0 $self->store_persistent_state;
2262              
2263 0         0 $self->post_make();
2264              
2265 0         0 return !! $system_ok;
2266             }
2267              
2268             # CPAN::Distribution::goodbye ;
2269             sub goodbye {
2270 0     0 0 0 my($self,$goodbye) = @_;
2271 0         0 my $id = $self->pretty_id;
2272 0         0 $CPAN::Frontend->mywarn(" $id\n $goodbye\n");
2273 0         0 return 0; # must be explicit false, not undef
2274             }
2275              
2276             sub success {
2277 0     0 0 0 my($self,$why) = @_;
2278 0         0 my $id = $self->pretty_id;
2279 0         0 $CPAN::Frontend->myprint(" $id\n $why\n");
2280 0         0 return 1;
2281             }
2282              
2283             # CPAN::Distribution::_run_via_expect ;
2284             sub _run_via_expect {
2285 0     0   0 my($self,$system,$phase,$expect_model) = @_;
2286 0 0       0 CPAN->debug("system[$system]expect_model[$expect_model]") if $CPAN::DEBUG;
2287 0 0       0 if ($CPAN::META->has_inst("Expect")) {
2288 0         0 my $expo = Expect->new; # expo Expect object;
2289 0         0 $expo->spawn($system);
2290 0   0     0 $expect_model->{mode} ||= "deterministic";
2291 0 0       0 if ($expect_model->{mode} eq "deterministic") {
    0          
2292 0         0 return $self->_run_via_expect_deterministic($expo,$phase,$expect_model);
2293             } elsif ($expect_model->{mode} eq "anyorder") {
2294 0         0 return $self->_run_via_expect_anyorder($expo,$phase,$expect_model);
2295             } else {
2296 0         0 die "Panic: Illegal expect mode: $expect_model->{mode}";
2297             }
2298             } else {
2299 0         0 $CPAN::Frontend->mywarn("Expect not installed, falling back to system()\n");
2300 0         0 return system($system);
2301             }
2302             }
2303              
2304             sub _run_via_expect_anyorder {
2305 0     0   0 my($self,$expo,$phase,$expect_model) = @_;
2306 0   0     0 my $timeout = $expect_model->{timeout} || 5;
2307 0         0 my $reuse = $expect_model->{reuse};
2308 0         0 my @expectacopy = @{$expect_model->{talk}}; # we trash it!
  0         0  
2309 0         0 my $but = "";
2310 0         0 my $timeout_start = time;
2311 0         0 EXPECT: while () {
2312 0         0 my($eof,$ran_into_timeout);
2313             # XXX not up to the full power of expect. one could certainly
2314             # wrap all of the talk pairs into a single expect call and on
2315             # success tweak it and step ahead to the next question. The
2316             # current implementation unnecessarily limits itself to a
2317             # single match.
2318             my @match = $expo->expect(1,
2319             [ eof => sub {
2320 0     0   0 $eof++;
2321             } ],
2322             [ timeout => sub {
2323 0     0   0 $ran_into_timeout++;
2324 0         0 } ],
2325             -re => eval"qr{.}",
2326             );
2327 0 0       0 if ($match[2]) {
2328 0         0 $but .= $match[2];
2329             }
2330 0         0 $but .= $expo->clear_accum;
2331 0 0       0 if ($eof) {
    0          
2332 0         0 $expo->soft_close;
2333 0         0 return $expo->exitstatus();
2334             } elsif ($ran_into_timeout) {
2335             # warn "DEBUG: they are asking a question, but[$but]";
2336 0         0 for (my $i = 0; $i <= $#expectacopy; $i+=2) {
2337 0         0 my($next,$send) = @expectacopy[$i,$i+1];
2338 0         0 my $regex = eval "qr{$next}";
2339             # warn "DEBUG: will compare with regex[$regex].";
2340 0 0       0 if ($but =~ /$regex/) {
2341             # warn "DEBUG: will send send[$send]";
2342 0         0 $expo->send($send);
2343             # never allow reusing an QA pair unless they told us
2344 0 0       0 splice @expectacopy, $i, 2 unless $reuse;
2345 0         0 $but =~ s/(?s:^.*?)$regex//;
2346 0         0 $timeout_start = time;
2347 0         0 next EXPECT;
2348             }
2349             }
2350 0         0 my $have_waited = time - $timeout_start;
2351 0 0       0 if ($have_waited < $timeout) {
2352             # warn "DEBUG: have_waited[$have_waited]timeout[$timeout]";
2353 0         0 next EXPECT;
2354             }
2355 0         0 my $why = "could not answer a question during the dialog";
2356 0         0 $CPAN::Frontend->mywarn("Failing: $why\n");
2357 0         0 $self->{$phase} =
2358             CPAN::Distrostatus->new("NO $why");
2359 0         0 return 0;
2360             }
2361             }
2362             }
2363              
2364             sub _run_via_expect_deterministic {
2365 0     0   0 my($self,$expo,$phase,$expect_model) = @_;
2366 0         0 my $ran_into_timeout;
2367             my $ran_into_eof;
2368 0   0     0 my $timeout = $expect_model->{timeout} || 15; # currently unsettable
2369 0         0 my $expecta = $expect_model->{talk};
2370 0         0 EXPECT: for (my $i = 0; $i <= $#$expecta; $i+=2) {
2371 0         0 my($re,$send) = @$expecta[$i,$i+1];
2372 0 0       0 CPAN->debug("timeout[$timeout]re[$re]") if $CPAN::DEBUG;
2373 0         0 my $regex = eval "qr{$re}";
2374             $expo->expect($timeout,
2375             [ eof => sub {
2376 0     0   0 my $but = $expo->clear_accum;
2377 0         0 $CPAN::Frontend->mywarn("EOF (maybe harmless)
2378             expected[$regex]\nbut[$but]\n\n");
2379 0         0 $ran_into_eof++;
2380             } ],
2381             [ timeout => sub {
2382 0     0   0 my $but = $expo->clear_accum;
2383 0         0 $CPAN::Frontend->mywarn("TIMEOUT
2384             expected[$regex]\nbut[$but]\n\n");
2385 0         0 $ran_into_timeout++;
2386 0         0 } ],
2387             -re => $regex);
2388 0 0       0 if ($ran_into_timeout) {
    0          
2389             # note that the caller expects 0 for success
2390 0         0 $self->{$phase} =
2391             CPAN::Distrostatus->new("NO timeout during expect dialog");
2392 0         0 return 0;
2393             } elsif ($ran_into_eof) {
2394 0         0 last EXPECT;
2395             }
2396 0         0 $expo->send($send);
2397             }
2398 0         0 $expo->soft_close;
2399 0         0 return $expo->exitstatus();
2400             }
2401              
2402             #-> CPAN::Distribution::_validate_distropref
2403             sub _validate_distropref {
2404 0     0   0 my($self,@args) = @_;
2405 0 0 0     0 if (
2406             $CPAN::META->has_inst("CPAN::Kwalify")
2407             &&
2408             $CPAN::META->has_inst("Kwalify")
2409             ) {
2410 0         0 eval {CPAN::Kwalify::_validate("distroprefs",@args);};
  0         0  
2411 0 0       0 if ($@) {
2412 0         0 $CPAN::Frontend->mywarn($@);
2413             }
2414             } else {
2415 0 0       0 CPAN->debug("not validating '@args'") if $CPAN::DEBUG;
2416             }
2417             }
2418              
2419             #-> CPAN::Distribution::_find_prefs
2420             sub _find_prefs {
2421 0     0   0 my($self) = @_;
2422 0         0 my $distroid = $self->pretty_id;
2423             #CPAN->debug("distroid[$distroid]") if $CPAN::DEBUG;
2424 0         0 my $prefs_dir = $CPAN::Config->{prefs_dir};
2425 0 0       0 return if $prefs_dir =~ /^\s*$/;
2426 0         0 eval { File::Path::mkpath($prefs_dir); };
  0         0  
2427 0 0       0 if ($@) {
2428 0         0 $CPAN::Frontend->mydie("Cannot create directory $prefs_dir");
2429             }
2430             # shortcut if there are no distroprefs files
2431             {
2432 0 0       0 my $dh = DirHandle->new($prefs_dir) or $CPAN::Frontend->mydie("Couldn't open '$prefs_dir': $!");
  0         0  
2433 0         0 my @files = map { /\.(yml|dd|st)\z/i } $dh->read;
  0         0  
2434 0 0       0 return unless @files;
2435             }
2436 0         0 my $yaml_module = CPAN::_yaml_module();
2437 0         0 my $ext_map = {};
2438 0         0 my @extensions;
2439 0 0       0 if ($CPAN::META->has_inst($yaml_module)) {
2440 0         0 $ext_map->{yml} = 'CPAN';
2441             } else {
2442 0         0 my @fallbacks;
2443 0 0       0 if ($CPAN::META->has_inst("Data::Dumper")) {
2444 0         0 push @fallbacks, $ext_map->{dd} = 'Data::Dumper';
2445             }
2446 0 0       0 if ($CPAN::META->has_inst("Storable")) {
2447 0         0 push @fallbacks, $ext_map->{st} = 'Storable';
2448             }
2449 0 0       0 if (@fallbacks) {
2450 0         0 local $" = " and ";
2451 0 0       0 unless ($self->{have_complained_about_missing_yaml}++) {
2452 0         0 $CPAN::Frontend->mywarnonce("'$yaml_module' not installed, falling back ".
2453             "to @fallbacks to read prefs '$prefs_dir'\n");
2454             }
2455             } else {
2456 0 0       0 unless ($self->{have_complained_about_missing_yaml}++) {
2457 0         0 $CPAN::Frontend->mywarnonce("'$yaml_module' not installed, cannot ".
2458             "read prefs '$prefs_dir'\n");
2459             }
2460             }
2461             }
2462 0         0 my $finder = CPAN::Distroprefs->find($prefs_dir, $ext_map);
2463 0         0 DIRENT: while (my $result = $finder->next) {
2464 0 0       0 if ($result->is_warning) {
    0          
2465 0         0 $CPAN::Frontend->mywarn($result->as_string);
2466 0         0 $CPAN::Frontend->mysleep(1);
2467 0         0 next DIRENT;
2468             } elsif ($result->is_fatal) {
2469 0         0 $CPAN::Frontend->mydie($result->as_string);
2470             }
2471              
2472 0         0 my @prefs = @{ $result->prefs };
  0         0  
2473              
2474 0         0 ELEMENT: for my $y (0..$#prefs) {
2475 0         0 my $pref = $prefs[$y];
2476 0         0 $self->_validate_distropref($pref->data, $result->abs, $y);
2477              
2478             # I don't know why we silently skip when there's no match, but
2479             # complain if there's an empty match hashref, and there's no
2480             # comment explaining why -- hdp, 2008-03-18
2481 0 0       0 unless ($pref->has_any_match) {
2482 0         0 next ELEMENT;
2483             }
2484              
2485 0 0       0 unless ($pref->has_valid_subkeys) {
2486 0         0 $CPAN::Frontend->mydie(sprintf
2487             "Nonconforming .%s file '%s': " .
2488             "missing match/* subattribute. " .
2489             "Please remove, cannot continue.",
2490             $result->ext, $result->abs,
2491             );
2492             }
2493              
2494             my $arg = {
2495             env => \%ENV,
2496             distribution => $distroid,
2497             perl => \&CPAN::find_perl,
2498             perlconfig => \%Config::Config,
2499 0     0   0 module => sub { [ $self->containsmods ] },
2500 0         0 };
2501              
2502 0 0       0 if ($pref->matches($arg)) {
2503             return {
2504 0         0 prefs => $pref->data,
2505             prefs_file => $result->abs,
2506             prefs_file_doc => $y,
2507             };
2508             }
2509              
2510             }
2511             }
2512 0         0 return;
2513             }
2514              
2515             # CPAN::Distribution::prefs
2516             sub prefs {
2517 0     0 0 0 my($self) = @_;
2518 0 0 0     0 if (exists $self->{negative_prefs_cache}
2519             &&
2520             $self->{negative_prefs_cache} != $CPAN::CurrentCommandId
2521             ) {
2522 0         0 delete $self->{negative_prefs_cache};
2523 0         0 delete $self->{prefs};
2524             }
2525 0 0       0 if (exists $self->{prefs}) {
2526 0         0 return $self->{prefs}; # XXX comment out during debugging
2527             }
2528 0 0       0 if ($CPAN::Config->{prefs_dir}) {
2529 0 0       0 CPAN->debug("prefs_dir[$CPAN::Config->{prefs_dir}]") if $CPAN::DEBUG;
2530 0         0 my $prefs = $self->_find_prefs();
2531 0   0     0 $prefs ||= ""; # avoid warning next line
2532 0 0       0 CPAN->debug("prefs[$prefs]") if $CPAN::DEBUG;
2533 0 0       0 if ($prefs) {
2534 0         0 for my $x (qw(prefs prefs_file prefs_file_doc)) {
2535 0         0 $self->{$x} = $prefs->{$x};
2536             }
2537             my $bs = sprintf(
2538             "%s[%s]",
2539             File::Basename::basename($self->{prefs_file}),
2540             $self->{prefs_file_doc},
2541 0         0 );
2542 0         0 my $filler1 = "_" x 22;
2543 0         0 my $filler2 = int(66 - length($bs))/2;
2544 0 0       0 $filler2 = 0 if $filler2 < 0;
2545 0         0 $filler2 = " " x $filler2;
2546 0         0 $CPAN::Frontend->myprint("
2547             $filler1 D i s t r o P r e f s $filler1
2548             $filler2 $bs $filler2
2549             ");
2550 0         0 $CPAN::Frontend->mysleep(1);
2551 0         0 return $self->{prefs};
2552             }
2553             }
2554 0         0 $self->{negative_prefs_cache} = $CPAN::CurrentCommandId;
2555 0         0 return $self->{prefs} = +{};
2556             }
2557              
2558             # CPAN::Distribution::_make_phase_arg
2559             sub _make_phase_arg {
2560 0     0   0 my($self, $phase) = @_;
2561 0         0 my $_make_phase_arg;
2562 0         0 my $prefs = $self->prefs;
2563 0 0 0     0 if (
      0        
      0        
2564             $prefs
2565             && exists $prefs->{$phase}
2566             && exists $prefs->{$phase}{args}
2567             && $prefs->{$phase}{args}
2568             ) {
2569             $_make_phase_arg = join(" ",
2570 0         0 map {CPAN::HandleConfig
2571 0         0 ->safe_quote($_)} @{$prefs->{$phase}{args}},
  0         0  
2572             );
2573             }
2574              
2575             # cpan[2]> o conf make[TAB]
2576             # make make_install_make_command
2577             # make_arg makepl_arg
2578             # make_install_arg
2579             # cpan[2]> o conf mbuild[TAB]
2580             # mbuild_arg mbuild_install_build_command
2581             # mbuild_install_arg mbuildpl_arg
2582              
2583 0         0 my $mantra; # must switch make/mbuild here
2584 0 0       0 if ($self->{modulebuild}) {
2585 0         0 $mantra = "mbuild";
2586             } else {
2587 0         0 $mantra = "make";
2588             }
2589 0         0 my %map = (
2590             pl => "pl_arg",
2591             make => "_arg",
2592             test => "_test_arg", # does not really exist but maybe
2593             # will some day and now protects
2594             # us from unini warnings
2595             install => "_install_arg",
2596             );
2597 0         0 my $phase_underscore_meshup = $map{$phase};
2598 0         0 my $what = sprintf "%s%s", $mantra, $phase_underscore_meshup;
2599              
2600 0   0     0 $_make_phase_arg ||= $CPAN::Config->{$what};
2601 0         0 return $_make_phase_arg;
2602             }
2603              
2604             # CPAN::Distribution::_make_command
2605             sub _make_command {
2606 0     0   0 my ($self) = @_;
2607 0 0       0 if ($self) {
2608             return
2609             CPAN::HandleConfig
2610             ->safe_quote(
2611             CPAN::HandleConfig->prefs_lookup($self,
2612             q{make})
2613             || $Config::Config{make}
2614 0   0     0 || 'make'
2615             );
2616             } else {
2617             # Old style call, without object. Deprecated
2618 0         0 Carp::confess("CPAN::_make_command() used as function. Don't Do That.");
2619             return
2620             safe_quote(undef,
2621             CPAN::HandleConfig->prefs_lookup($self,q{make})
2622             || $CPAN::Config->{make}
2623             || $Config::Config{make}
2624 0   0     0 || 'make');
2625             }
2626             }
2627              
2628             sub _make_install_make_command {
2629 0     0   0 my ($self) = @_;
2630 0         0 my $mimc =
2631             CPAN::HandleConfig->prefs_lookup($self, q{make_install_make_command});
2632 0 0       0 return $self->_make_command() unless $mimc;
2633              
2634             # Quote the "make install" make command on Windows, where it is commonly
2635             # found in, e.g., C:\Program Files\... and therefore needs quoting. We can't
2636             # do this in general because the command maybe "sudo make..." (i.e. a
2637             # program with arguments), but that is unlikely to be the case on Windows.
2638 0 0       0 $mimc = CPAN::HandleConfig->safe_quote($mimc) if $^O eq 'MSWin32';
2639              
2640 0         0 return $mimc;
2641             }
2642              
2643             #-> sub CPAN::Distribution::is_locally_optional
2644             sub is_locally_optional {
2645 0     0 0 0 my($self, $prereq_pm, $prereq) = @_;
2646 0   0     0 $prereq_pm ||= $self->{prereq_pm};
2647 0         0 my($nmo,$opt);
2648 0         0 for my $rt (qw(requires build_requires)) {
2649 0 0       0 if (exists $prereq_pm->{$rt}{$prereq}) {
2650             # rt 121914
2651 0   0     0 $nmo ||= $CPAN::META->instance("CPAN::Module",$prereq);
2652 0         0 my $av = $nmo->available_version;
2653 0 0 0     0 return 0 if !$av || CPAN::Version->vlt($av,$prereq_pm->{$rt}{$prereq});
2654             }
2655 0 0       0 if (exists $prereq_pm->{"opt_$rt"}{$prereq}) {
2656 0         0 $opt = 1;
2657             }
2658             }
2659 0   0     0 return $opt||0;
2660             }
2661              
2662             #-> sub CPAN::Distribution::follow_prereqs ;
2663             sub follow_prereqs {
2664 0     0 0 0 my($self) = shift;
2665 0         0 my($slot) = shift;
2666 0         0 my(@prereq_tuples) = grep {$_->[0] ne "perl"} @_;
  0         0  
2667 0 0       0 return unless @prereq_tuples;
2668 0         0 my(@good_prereq_tuples);
2669 0         0 for my $p (@prereq_tuples) {
2670             # e.g. $p = ['Devel::PartialDump', 'r', 1]
2671             # promote if possible
2672 0 0       0 if ($p->[1] =~ /^(r|c)$/) {
    0          
2673 0         0 push @good_prereq_tuples, $p;
2674             } elsif ($p->[1] =~ /^(b)$/) {
2675 0         0 my $reqtype = CPAN::Queue->reqtype_of($p->[0]);
2676 0 0       0 if ($reqtype =~ /^(r|c)$/) {
2677 0         0 push @good_prereq_tuples, [$p->[0], $reqtype, $p->[2]];
2678             } else {
2679 0         0 push @good_prereq_tuples, $p;
2680             }
2681             } else {
2682 0         0 die "Panic: in follow_prereqs: reqtype[$p->[1]] seen, should never happen";
2683             }
2684             }
2685 0         0 my $pretty_id = $self->pretty_id;
2686 0         0 my %map = (
2687             b => "build_requires",
2688             r => "requires",
2689             c => "commandline",
2690             );
2691 0         0 my($filler1,$filler2,$filler3,$filler4);
2692 0         0 my $unsat = "Unsatisfied dependencies detected during";
2693 0 0       0 my $w = length($unsat) > length($pretty_id) ? length($unsat) : length($pretty_id);
2694             {
2695 0         0 my $r = int(($w - length($unsat))/2);
2696 0         0 my $l = $w - length($unsat) - $r;
2697 0         0 $filler1 = "-"x4 . " "x$l;
2698 0         0 $filler2 = " "x$r . "-"x4 . "\n";
2699             }
2700             {
2701 0         0 my $r = int(($w - length($pretty_id))/2);
  0         0  
  0         0  
2702 0         0 my $l = $w - length($pretty_id) - $r;
2703 0         0 $filler3 = "-"x4 . " "x$l;
2704 0         0 $filler4 = " "x$r . "-"x4 . "\n";
2705             }
2706             $CPAN::Frontend->
2707             myprint("$filler1 $unsat $filler2".
2708             "$filler3 $pretty_id $filler4".
2709 0 0       0 join("", map {sprintf " %s \[%s%s]\n", $_->[0], $map{$_->[1]}, $self->is_locally_optional(undef,$_->[0]) ? ",optional" : ""} @good_prereq_tuples),
  0         0  
2710             );
2711 0         0 my $follow = 0;
2712 0 0       0 if ($CPAN::Config->{prerequisites_policy} eq "follow") {
    0          
2713 0         0 $follow = 1;
2714             } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") {
2715 0         0 my $answer = CPAN::Shell::colorable_makemaker_prompt(
2716             "Shall I follow them and prepend them to the queue
2717             of modules we are processing right now?", "yes");
2718 0         0 $follow = $answer =~ /^\s*y/i;
2719             } else {
2720 0         0 my @prereq = map { $_->[0] } @good_prereq_tuples;
  0         0  
2721 0         0 local($") = ", ";
2722 0         0 $CPAN::Frontend->
2723             myprint(" Ignoring dependencies on modules @prereq\n");
2724             }
2725 0 0       0 if ($follow) {
2726 0         0 my $id = $self->id;
2727 0         0 my(@to_queue_mand,@to_queue_opt);
2728 0         0 for my $gp (@good_prereq_tuples) {
2729 0         0 my($prereq,$reqtype,$optional) = @$gp;
2730 0         0 my $qthing = +{qmod=>$prereq,reqtype=>$reqtype,optional=>$optional};
2731 0 0 0     0 if ($optional &&
2732             $self->is_locally_optional(undef,$prereq)
2733             ){
2734             # Since we do not depend on this one, we do not need
2735             # this in a mandatory arrangement:
2736 0         0 push @to_queue_opt, $qthing;
2737             } else {
2738 0         0 my $any = CPAN::Shell->expandany($prereq);
2739 0         0 $self->{$slot . "_for"}{$any->id}++;
2740 0 0       0 if ($any) {
2741 0 0       0 unless ($optional) {
2742             # No recursion check in an optional area of the tree
2743 0         0 $any->color_cmd_tmps(0,2);
2744             }
2745             } else {
2746 0         0 $CPAN::Frontend->mywarn("Warning (maybe a bug): Cannot expand prereq '$prereq'\n");
2747 0         0 $CPAN::Frontend->mysleep(2);
2748             }
2749             # order everything that is not locally_optional just
2750             # like mandatory items: this keeps leaves before
2751             # branches
2752 0         0 unshift @to_queue_mand, $qthing;
2753             }
2754             }
2755 0 0       0 if (@to_queue_mand) {
    0          
2756 0         0 unshift @to_queue_mand, {qmod => $id, reqtype => $self->{reqtype}, optional=> !$self->{mandatory}};
2757 0         0 CPAN::Queue->jumpqueue(@to_queue_opt,@to_queue_mand);
2758 0         0 $self->{$slot} = "Delayed until after prerequisites";
2759 0         0 return 1; # signal we need dependencies
2760             } elsif (@to_queue_opt) {
2761 0         0 CPAN::Queue->jumpqueue(@to_queue_opt);
2762             }
2763             }
2764 0         0 return;
2765             }
2766              
2767             sub _feature_depends {
2768 0     0   0 my($self) = @_;
2769 0         0 my $meta_yml = $self->parse_meta_yml();
2770 0 0       0 my $optf = $meta_yml->{optional_features} or return;
2771 0 0 0     0 if (!ref $optf or ref $optf ne "HASH"){
2772 0         0 $CPAN::Frontend->mywarn("The content of optional_features is not a HASH reference. Cannot use it.\n");
2773 0         0 $optf = {};
2774             }
2775 0 0       0 my $wantf = $self->prefs->{features} or return;
2776 0 0 0     0 if (!ref $wantf or ref $wantf ne "ARRAY"){
2777 0         0 $CPAN::Frontend->mywarn("The content of 'features' is not an ARRAY reference. Cannot use it.\n");
2778 0         0 $wantf = [];
2779             }
2780 0         0 my $dep = +{};
2781 0         0 for my $wf (@$wantf) {
2782 0 0       0 if (my $f = $optf->{$wf}) {
2783             $CPAN::Frontend->myprint("Found the demanded feature '$wf' that ".
2784             "is accompanied by this description:\n".
2785             $f->{description}.
2786 0         0 "\n\n"
2787             );
2788             # configure_requires currently not in the spec, unlikely to be useful anyway
2789 0         0 for my $reqtype (qw(configure_requires build_requires requires)) {
2790 0 0       0 my $reqhash = $f->{$reqtype} or next;
2791 0         0 while (my($k,$v) = each %$reqhash) {
2792 0         0 $dep->{$reqtype}{$k} = $v;
2793             }
2794             }
2795             } else {
2796 0         0 $CPAN::Frontend->mywarn("The demanded feature '$wf' was not ".
2797             "found in the META.yml file".
2798             "\n\n"
2799             );
2800             }
2801             }
2802 0         0 $dep;
2803             }
2804              
2805             sub prereqs_for_slot {
2806 0     0 0 0 my($self,$slot) = @_;
2807 0         0 my($prereq_pm);
2808 0 0       0 unless ($CPAN::META->has_usable("CPAN::Meta::Requirements")) {
2809 0         0 my $whynot = "not available";
2810 0 0       0 if (defined $CPAN::Meta::Requirements::VERSION) {
2811 0         0 $whynot = "version $CPAN::Meta::Requirements::VERSION not sufficient";
2812             }
2813 0         0 $CPAN::Frontend->mywarn("CPAN::Meta::Requirements $whynot\n");
2814 0         0 my $before = "";
2815 0 0       0 if ($self->{CALLED_FOR}){
2816 0 0       0 if ($self->{CALLED_FOR} =~
2817             /^(
2818             CPAN::Meta::Requirements
2819             |version
2820             |parent
2821             |ExtUtils::MakeMaker
2822             |Test::Harness
2823             )$/x) {
2824 0         0 $CPAN::Frontend->mywarn("Setting requirements to nil as a workaround\n");
2825 0         0 return;
2826             }
2827 0         0 $before = " before $self->{CALLED_FOR}";
2828             }
2829 0         0 $CPAN::Frontend->mydie("Please install CPAN::Meta::Requirements manually$before");
2830             }
2831 0         0 my $merged = CPAN::Meta::Requirements->new;
2832 0   0     0 my $prefs_depends = $self->prefs->{depends}||{};
2833 0         0 my $feature_depends = $self->_feature_depends();
2834 0 0       0 if ($slot eq "configure_requires_later") {
    0          
2835 0         0 for my $hash ( $self->configure_requires,
2836             $prefs_depends->{configure_requires},
2837             $feature_depends->{configure_requires},
2838             ) {
2839 0         0 $merged->add_requirements(
2840             CPAN::Meta::Requirements->from_string_hash($hash)
2841             );
2842             }
2843 0 0 0     0 if (-f "Build.PL"
      0        
      0        
2844             && ! -f File::Spec->catfile($self->{build_dir},"Makefile.PL")
2845             && ! $merged->requirements_for_module("Module::Build")
2846             && ! $CPAN::META->has_inst("Module::Build")
2847             ) {
2848 0         0 $CPAN::Frontend->mywarn(
2849             " Warning: CPAN.pm discovered Module::Build as undeclared prerequisite.\n".
2850             " Adding it now as such.\n"
2851             );
2852 0         0 $CPAN::Frontend->mysleep(5);
2853 0         0 $merged->add_minimum( "Module::Build" => 0 );
2854 0         0 delete $self->{writemakefile};
2855             }
2856 0         0 $prereq_pm = {}; # configure_requires defined as "b"
2857             } elsif ($slot eq "later") {
2858 0   0     0 my $prereq_pm_0 = $self->prereq_pm || {};
2859 0         0 for my $reqtype (qw(requires build_requires opt_requires opt_build_requires)) {
2860 0 0       0 $prereq_pm->{$reqtype} = {%{$prereq_pm_0->{$reqtype}||{}}}; # copy to not pollute it
  0         0  
2861 0         0 for my $dep ($prefs_depends,$feature_depends) {
2862 0 0       0 for my $k (keys %{$dep->{$reqtype}||{}}) {
  0         0  
2863 0         0 $prereq_pm->{$reqtype}{$k} = $dep->{$reqtype}{$k};
2864             }
2865             }
2866             }
2867             # XXX what about optional_req|breq? -- xdg, 2012-04-01
2868 0         0 for my $hash (
2869             $prereq_pm->{requires},
2870             $prereq_pm->{build_requires},
2871             $prereq_pm->{opt_requires},
2872             $prereq_pm->{opt_build_requires},
2873              
2874             ) {
2875 0         0 $merged->add_requirements(
2876             CPAN::Meta::Requirements->from_string_hash($hash)
2877             );
2878             }
2879             } else {
2880 0         0 die "Panic: illegal slot '$slot'";
2881             }
2882 0         0 return ($merged->as_string_hash, $prereq_pm);
2883             }
2884              
2885             #-> sub CPAN::Distribution::unsat_prereq ;
2886             # return ([Foo,"r"],[Bar,"b"]) for normal modules
2887             # return ([perl=>5.008]) if we need a newer perl than we are running under
2888             # (sorry for the inconsistency, it was an accident)
2889             sub unsat_prereq {
2890 0     0 0 0 my($self,$slot) = @_;
2891 0         0 my($merged_hash,$prereq_pm) = $self->prereqs_for_slot($slot);
2892 0         0 my(@need);
2893 0 0       0 unless ($CPAN::META->has_usable("CPAN::Meta::Requirements")) {
2894 0         0 $CPAN::Frontend->mywarn("CPAN::Meta::Requirements not available, please install as soon as possible, trying to continue with severly limited capabilities\n");
2895 0         0 return;
2896             }
2897 0         0 my $merged = CPAN::Meta::Requirements->from_string_hash($merged_hash);
2898 0         0 my @merged = sort $merged->required_modules;
2899 0 0       0 CPAN->debug("all merged_prereqs[@merged]") if $CPAN::DEBUG;
2900 0         0 NEED: for my $need_module ( @merged ) {
2901 0         0 my $need_version = $merged->requirements_for_module($need_module);
2902 0         0 my($available_version,$inst_file,$available_file,$nmo);
2903 0 0       0 if ($need_module eq "perl") {
2904 0         0 $available_version = $];
2905 0         0 $available_file = CPAN::find_perl();
2906             } else {
2907 0 0       0 if (CPAN::_sqlite_running()) {
2908 0         0 CPAN::Index->reload;
2909 0         0 $CPAN::SQLite->search("CPAN::Module",$need_module);
2910             }
2911 0         0 $nmo = $CPAN::META->instance("CPAN::Module",$need_module);
2912 0   0     0 $inst_file = $nmo->inst_file || '';
2913 0   0     0 $available_file = $nmo->available_file || '';
2914 0         0 $available_version = $nmo->available_version;
2915 0 0       0 if ($nmo->uptodate) {
2916 0         0 my $accepts = eval {
2917 0         0 $merged->accepts_module($need_module, $available_version);
2918             };
2919 0 0       0 unless ($accepts) {
2920 0         0 my $rq = $merged->requirements_for_module( $need_module );
2921 0         0 $CPAN::Frontend->mywarn(
2922             "Warning: Version '$available_version' of ".
2923             "'$need_module' is up to date but does not ".
2924             "fulfill requirements ($rq). I will continue, ".
2925             "but chances to succeed are low.\n");
2926             }
2927 0         0 next NEED;
2928             }
2929              
2930             # if they have not specified a version, we accept any
2931             # installed one; in that case inst_file is always
2932             # sufficient and available_file is sufficient on
2933             # both build_requires and configure_requires
2934             my $sufficient = $inst_file ||
2935 0   0     0 ( exists $prereq_pm->{requires}{$need_module} ? 0 : $available_file );
2936 0 0 0     0 if ( $sufficient
      0        
2937             and ( # a few quick short circuits
2938             not defined $need_version
2939             or $need_version eq '0' # "==" would trigger warning when not numeric
2940             or $need_version eq "undef"
2941             )) {
2942 0 0       0 unless ($nmo->inst_deprecated) {
2943 0         0 next NEED;
2944             }
2945             }
2946             }
2947              
2948             # We only want to install prereqs if either they're not installed
2949             # or if the installed version is too old. We cannot omit this
2950             # check, because if 'force' is in effect, nobody else will check.
2951             # But we don't want to accept a deprecated module installed as part
2952             # of the Perl core, so we continue if the available file is the installed
2953             # one and is deprecated
2954              
2955 0 0       0 if ( $available_file ) {
2956 0         0 my $fulfills_all_version_rqs = $self->_fulfills_all_version_rqs
2957             (
2958             $need_module,
2959             $available_file,
2960             $available_version,
2961             $need_version,
2962             );
2963 0 0 0     0 if ( $inst_file
    0 0        
      0        
      0        
      0        
      0        
      0        
2964             && $available_file eq $inst_file
2965             && $nmo->inst_deprecated
2966             ) {
2967             # continue installing as a prereq. we really want that
2968             # because the deprecated module may spit out warnings
2969             # and third party did not know until today. Only one
2970             # exception is OK, because CPANPLUS is special after
2971             # all:
2972 0 0 0     0 if ( $fulfills_all_version_rqs and
2973             $nmo->id =~ /^CPANPLUS(?:::Dist::Build)$/
2974             ) {
2975             # here we have an available version that is good
2976             # enough although deprecated (preventing circular
2977             # loop CPANPLUS => CPANPLUS::Dist::Build RT#83042)
2978 0         0 next NEED;
2979             }
2980             } elsif (
2981             $self->{reqtype} # e.g. maybe we came via goto?
2982             && $self->{reqtype} =~ /^(r|c)$/
2983             && ( exists $prereq_pm->{requires}{$need_module}
2984             || exists $prereq_pm->{opt_requires}{$need_module} )
2985             && $nmo
2986             && !$inst_file
2987             ) {
2988             # continue installing as a prereq; this may be a
2989             # distro we already used when it was a build_requires
2990             # so we did not install it. But suddenly somebody
2991             # wants it as a requires
2992 0         0 my $need_distro = $nmo->distribution;
2993 0 0 0     0 if ($need_distro->{install} && $need_distro->{install}->failed && $need_distro->{install}->text =~ /is only/) {
      0        
2994 0         0 my $id = $need_distro->pretty_id;
2995 0         0 $CPAN::Frontend->myprint("Promoting $id from build_requires to requires due $need_module\n");
2996 0         0 delete $need_distro->{install}; # promote to another installation attempt
2997 0         0 $need_distro->{reqtype} = "r";
2998 0         0 $need_distro->install;
2999 0         0 next NEED;
3000             }
3001             }
3002             else {
3003 0 0       0 next NEED if $fulfills_all_version_rqs;
3004             }
3005             }
3006              
3007 0 0       0 if ($need_module eq "perl") {
3008 0         0 return ["perl", $need_version];
3009             }
3010 0   0     0 $self->{sponsored_mods}{$need_module} ||= 0;
3011 0 0       0 CPAN->debug("need_module[$need_module]s/s/n[$self->{sponsored_mods}{$need_module}]") if $CPAN::DEBUG;
3012 0 0       0 if (my $sponsoring = $self->{sponsored_mods}{$need_module}++) {
3013             # We have already sponsored it and for some reason it's still
3014             # not available. So we do ... what??
3015              
3016             # if we push it again, we have a potential infinite loop
3017              
3018             # The following "next" was a very problematic construct.
3019             # It helped a lot but broke some day and had to be
3020             # replaced.
3021              
3022             # We must be able to deal with modules that come again and
3023             # again as a prereq and have themselves prereqs and the
3024             # queue becomes long but finally we would find the correct
3025             # order. The RecursiveDependency check should trigger a
3026             # die when it's becoming too weird. Unfortunately removing
3027             # this next breaks many other things.
3028              
3029             # The bug that brought this up is described in Todo under
3030             # "5.8.9 cannot install Compress::Zlib"
3031              
3032             # next; # this is the next that had to go away
3033              
3034             # The following "next NEED" are fine and the error message
3035             # explains well what is going on. For example when the DBI
3036             # fails and consequently DBD::SQLite fails and now we are
3037             # processing CPAN::SQLite. Then we must have a "next" for
3038             # DBD::SQLite. How can we get it and how can we identify
3039             # all other cases we must identify?
3040              
3041 0         0 my $do = $nmo->distribution;
3042 0 0       0 next NEED unless $do; # not on CPAN
3043 0 0       0 if (CPAN::Version->vcmp($need_version, $nmo->ro->{CPAN_VERSION}) > 0){
3044 0         0 $CPAN::Frontend->mywarn("Warning: Prerequisite ".
3045             "'$need_module => $need_version' ".
3046             "for '$self->{ID}' seems ".
3047             "not available according to the indices\n"
3048             );
3049 0         0 next NEED;
3050             }
3051 0         0 NOSAYER: for my $nosayer (
3052             "unwrapped",
3053             "writemakefile",
3054             "signature_verify",
3055             "make",
3056             "make_test",
3057             "install",
3058             "make_clean",
3059             ) {
3060 0 0       0 if ($do->{$nosayer}) {
3061 0         0 my $selfid = $self->pretty_id;
3062 0         0 my $did = $do->pretty_id;
3063 0 0       0 if (UNIVERSAL::can($do->{$nosayer},"failed") ?
    0          
3064             $do->{$nosayer}->failed :
3065             $do->{$nosayer} =~ /^NO/) {
3066 0 0 0     0 if ($nosayer eq "make_test"
3067             &&
3068             $do->{make_test}{COMMANDID} != $CPAN::CurrentCommandId
3069             ) {
3070 0         0 next NOSAYER;
3071             }
3072             ### XXX don't complain about missing optional deps -- xdg, 2012-04-01
3073 0 0       0 if ($self->is_locally_optional($prereq_pm, $need_module)) {
3074             # don't complain about failing optional prereqs
3075             }
3076             else {
3077 0         0 $CPAN::Frontend->mywarn("Warning: Prerequisite ".
3078             "'$need_module => $need_version' ".
3079             "for '$selfid' failed when ".
3080             "processing '$did' with ".
3081             "'$nosayer => $do->{$nosayer}'. Continuing, ".
3082             "but chances to succeed are limited.\n"
3083             );
3084 0         0 $CPAN::Frontend->mysleep($sponsoring/10);
3085             }
3086 0         0 next NEED;
3087             } else { # the other guy succeeded
3088 0 0       0 if ($nosayer =~ /^(install|make_test)$/) {
3089             # we had this with
3090             # DMAKI/DateTime-Calendar-Chinese-0.05.tar.gz
3091             # in 2007-03 for 'make install'
3092             # and 2008-04: #30464 (for 'make test')
3093             # $CPAN::Frontend->mywarn("Warning: Prerequisite ".
3094             # "'$need_module => $need_version' ".
3095             # "for '$selfid' already built ".
3096             # "but the result looks suspicious. ".
3097             # "Skipping another build attempt, ".
3098             # "to prevent looping endlessly.\n"
3099             # );
3100 0         0 next NEED;
3101             }
3102             }
3103             }
3104             }
3105             }
3106 0         0 my $needed_as;
3107 0 0       0 if (0) {
    0          
3108 0 0       0 } elsif (exists $prereq_pm->{requires}{$need_module}
3109             || exists $prereq_pm->{opt_requires}{$need_module}
3110             ) {
3111 0         0 $needed_as = "r";
3112             } elsif ($slot eq "configure_requires_later") {
3113             # in ae872487d5 we said: C< we have not yet run the
3114             # {Build,Makefile}.PL, we must presume "r" >; but the
3115             # meta.yml standard says C< These dependencies are not
3116             # required after the distribution is installed. >; so now
3117             # we change it back to "b" and care for the proper
3118             # promotion later.
3119 0         0 $needed_as = "b";
3120             } else {
3121 0         0 $needed_as = "b";
3122             }
3123             # here need to flag as optional for recommends/suggests
3124             # -- xdg, 2012-04-01
3125             $self->debug(sprintf "%s manadory?[%s]",
3126             $self->pretty_id,
3127             $self->{mandatory})
3128 0 0       0 if $CPAN::DEBUG;
3129             my $optional = !$self->{mandatory}
3130 0   0     0 || $self->is_locally_optional($prereq_pm, $need_module);
3131 0         0 push @need, [$need_module,$needed_as,$optional];
3132             }
3133 0         0 my @unfolded = map { "[".join(",",@$_)."]" } @need;
  0         0  
3134 0 0       0 CPAN->debug("returning from unsat_prereq[@unfolded]") if $CPAN::DEBUG;
3135 0         0 @need;
3136             }
3137              
3138             sub _fulfills_all_version_rqs {
3139 0     0   0 my($self,$need_module,$available_file,$available_version,$need_version) = @_;
3140 0         0 my(@all_requirements) = split /\s*,\s*/, $need_version;
3141 0         0 local($^W) = 0;
3142 0         0 my $ok = 0;
3143 0         0 RQ: for my $rq (@all_requirements) {
3144 0 0       0 if ($rq =~ s|>=\s*||) {
    0          
    0          
    0          
    0          
3145             } elsif ($rq =~ s|>\s*||) {
3146             # 2005-12: one user
3147 0 0       0 if (CPAN::Version->vgt($available_version,$rq)) {
3148 0         0 $ok++;
3149             }
3150 0         0 next RQ;
3151             } elsif ($rq =~ s|!=\s*||) {
3152             # 2005-12: no user
3153 0 0       0 if (CPAN::Version->vcmp($available_version,$rq)) {
3154 0         0 $ok++;
3155 0         0 next RQ;
3156             } else {
3157 0         0 $ok=0;
3158 0         0 last RQ;
3159             }
3160             } elsif ($rq =~ m|<=?\s*|) {
3161             # 2005-12: no user
3162 0         0 $CPAN::Frontend->mywarn("Downgrading not supported (rq[$rq])\n");
3163 0         0 $ok++;
3164 0         0 next RQ;
3165             } elsif ($rq =~ s|==\s*||) {
3166             # 2009-07: ELLIOTJS/Perl-Critic-1.099_002.tar.gz
3167 0 0       0 if (CPAN::Version->vcmp($available_version,$rq)) {
3168 0         0 $ok=0;
3169 0         0 last RQ;
3170             } else {
3171 0         0 $ok++;
3172 0         0 next RQ;
3173             }
3174             }
3175 0 0       0 if (! CPAN::Version->vgt($rq, $available_version)) {
3176 0         0 $ok++;
3177             }
3178 0 0       0 CPAN->debug(sprintf("need_module[%s]available_file[%s]".
3179             "available_version[%s]rq[%s]ok[%d]",
3180             $need_module,
3181             $available_file,
3182             $available_version,
3183             CPAN::Version->readable($rq),
3184             $ok,
3185             )) if $CPAN::DEBUG;
3186             }
3187 0         0 my $ret = $ok == @all_requirements;
3188 0 0       0 CPAN->debug(sprintf("need_module[%s]ok[%s]all_requirements[%d]",$need_module, $ok, scalar @all_requirements)) if $CPAN::DEBUG;
3189 0         0 return $ret;
3190             }
3191              
3192             #-> sub CPAN::Distribution::read_meta
3193             # read any sort of meta files, return CPAN::Meta object if no errors
3194             sub read_meta {
3195 30     30 0 139 my($self) = @_;
3196 30 100       81 my $meta_file = $self->pick_meta_file
3197             or return;
3198              
3199 28 50       120 return unless $CPAN::META->has_usable("CPAN::Meta");
3200 28 50       52 my $meta = eval { CPAN::Meta->load_file($meta_file)}
  28         123  
3201             or return;
3202              
3203             # Very old EU::MM could have wrong META
3204 28 50 33     210196 if ($meta_file eq 'META.yml'
3205             && $meta->generated_by =~ /ExtUtils::MakeMaker version ([\d\._]+)/
3206             ) {
3207 0         0 my $eummv = do { local $^W = 0; $1+0; };
  0         0  
  0         0  
3208 0 0       0 return if $eummv < 6.2501;
3209             }
3210              
3211 28         117 return $meta;
3212             }
3213              
3214             #-> sub CPAN::Distribution::read_yaml ;
3215             # XXX This should be DEPRECATED -- dagolden, 2011-02-05
3216             sub read_yaml {
3217 0     0 0 0 my($self) = @_;
3218 0         0 my $meta_file = $self->pick_meta_file('\.yml$');
3219 0 0       0 $self->debug("meta_file[$meta_file]") if $CPAN::DEBUG;
3220 0 0       0 return unless $meta_file;
3221 0         0 my $yaml;
3222 0         0 eval { $yaml = $self->parse_meta_yml($meta_file) };
  0         0  
3223 0 0 0     0 if ($@ or ! $yaml) {
3224 0         0 return undef; # if we die, then we cannot read YAML's own META.yml
3225             }
3226             # not "authoritative"
3227 0 0 0     0 if (defined $yaml && (! ref $yaml || ref $yaml ne "HASH")) {
      0        
3228 0         0 $CPAN::Frontend->mywarn("META.yml does not seem to be conforming, cannot use it.\n");
3229 0         0 $yaml = undef;
3230             }
3231 0 0 0     0 $self->debug(sprintf "yaml[%s]", $yaml || "UNDEF")
3232             if $CPAN::DEBUG;
3233 0 0 0     0 $self->debug($yaml) if $CPAN::DEBUG && $yaml;
3234             # MYMETA.yml is static and authoritative by definition
3235 0 0       0 if ( $meta_file =~ /MYMETA\.yml/ ) {
3236 0         0 return $yaml;
3237             }
3238             # META.yml is authoritative only if dynamic_config is defined and false
3239 0 0 0     0 if ( defined $yaml->{dynamic_config} && ! $yaml->{dynamic_config} ) {
3240 0         0 return $yaml;
3241             }
3242             # otherwise, we can't use what we found
3243 0         0 return undef;
3244             }
3245              
3246             #-> sub CPAN::Distribution::configure_requires ;
3247             sub configure_requires {
3248 0     0 0 0 my($self) = @_;
3249 0 0       0 return unless my $meta_file = $self->pick_meta_file('^META');
3250 0 0       0 if (my $meta_obj = $self->read_meta) {
3251 0         0 my $prereqs = $meta_obj->effective_prereqs;
3252 0         0 my $cr = $prereqs->requirements_for(qw/configure requires/);
3253 0 0       0 return $cr ? $cr->as_string_hash : undef;
3254             }
3255             else {
3256 0         0 my $yaml = eval { $self->parse_meta_yml($meta_file) };
  0         0  
3257 0         0 return $yaml->{configure_requires};
3258             }
3259             }
3260              
3261             #-> sub CPAN::Distribution::prereq_pm ;
3262             sub prereq_pm {
3263 8     8 0 84 my($self) = @_;
3264             return unless $self->{writemakefile} # no need to have succeeded
3265             # but we must have run it
3266 8 0 33     26 || $self->{modulebuild};
3267 8 50       34 unless ($self->{build_dir}) {
3268 0         0 return;
3269             }
3270             # no Makefile/Build means configuration aborted, so don't look for prereqs
3271 8 50       130 my $makefile = File::Spec->catfile($self->{build_dir}, $^O eq 'VMS' ? 'descrip.mms' : 'Makefile');
3272 8 50       73 my $buildfile = File::Spec->catfile($self->{build_dir}, $^O eq 'VMS' ? 'Build.com' : 'Build');
3273 8 50 33     159 return unless -f $makefile || -f $buildfile;
3274             CPAN->debug(sprintf "writemakefile[%s]modulebuild[%s]",
3275             $self->{writemakefile}||"",
3276 8 50 0     36 $self->{modulebuild}||"",
      0        
3277             ) if $CPAN::DEBUG;
3278 8         20 my($req,$breq, $opt_req, $opt_breq);
3279 8         28 my $meta_obj = $self->read_meta;
3280             # META/MYMETA is only authoritative if dynamic_config is false
3281 8 50 33     55 if ($meta_obj && ! $meta_obj->dynamic_config) {
    0          
3282 8         74 my $prereqs = $meta_obj->effective_prereqs;
3283 8         5829 my $requires = $prereqs->requirements_for(qw/runtime requires/);
3284 8         359 my $build_requires = $prereqs->requirements_for(qw/build requires/);
3285 8         308 my $test_requires = $prereqs->requirements_for(qw/test requires/);
3286             # XXX we don't yet distinguish build vs test, so merge them for now
3287 8         293 $build_requires->add_requirements($test_requires);
3288 8         559 $req = $requires->as_string_hash;
3289 8         778 $breq = $build_requires->as_string_hash;
3290              
3291             # XXX assemble optional_req && optional_breq from recommends/suggests
3292             # depending on corresponding policies -- xdg, 2012-04-01
3293 8         403 CPAN->use_inst("CPAN::Meta::Requirements");
3294 8         32 my $opt_runtime = CPAN::Meta::Requirements->new;
3295 8         113 my $opt_build = CPAN::Meta::Requirements->new;
3296 8 50       99 if ( $CPAN::Config->{recommends_policy} ) {
3297 0         0 $opt_runtime->add_requirements( $prereqs->requirements_for(qw/runtime recommends/));
3298 0         0 $opt_build->add_requirements( $prereqs->requirements_for(qw/build recommends/));
3299 0         0 $opt_build->add_requirements( $prereqs->requirements_for(qw/test recommends/));
3300              
3301             }
3302 8 50       27 if ( $CPAN::Config->{suggests_policy} ) {
3303 0         0 $opt_runtime->add_requirements( $prereqs->requirements_for(qw/runtime suggests/));
3304 0         0 $opt_build->add_requirements( $prereqs->requirements_for(qw/build suggests/));
3305 0         0 $opt_build->add_requirements( $prereqs->requirements_for(qw/test suggests/));
3306             }
3307 8         21 $opt_req = $opt_runtime->as_string_hash;
3308 8         89 $opt_breq = $opt_build->as_string_hash;
3309             }
3310             elsif (my $yaml = $self->read_yaml) { # often dynamic_config prevents a result here
3311 0   0     0 $req = $yaml->{requires} || {};
3312 0   0     0 $breq = $yaml->{build_requires} || {};
3313 0 0       0 if ( $CPAN::Config->{recommends_policy} ) {
3314 0   0     0 $opt_req = $yaml->{recommends} || {};
3315             }
3316 0 0 0     0 undef $req unless ref $req eq "HASH" && %$req;
3317 0 0       0 if ($req) {
3318 0 0 0     0 if ($yaml->{generated_by} &&
3319             $yaml->{generated_by} =~ /ExtUtils::MakeMaker version ([\d\._]+)/) {
3320 0         0 my $eummv = do { local $^W = 0; $1+0; };
  0         0  
  0         0  
3321 0 0       0 if ($eummv < 6.2501) {
3322             # thanks to Slaven for digging that out: MM before
3323             # that could be wrong because it could reflect a
3324             # previous release
3325 0         0 undef $req;
3326             }
3327             }
3328 0         0 my $areq;
3329             my $do_replace;
3330 0 0       0 foreach my $k (sort keys %{$req||{}}) {
  0         0  
3331 0         0 my $v = $req->{$k};
3332 0 0       0 next unless defined $v;
3333 0 0 0     0 if ($v =~ /\d/) {
    0 0        
3334 0         0 $areq->{$k} = $v;
3335             } elsif ($k =~ /[A-Za-z]/ &&
3336             $v =~ /[A-Za-z]/ &&
3337             $CPAN::META->exists("CPAN::Module",$v)
3338             ) {
3339 0         0 $CPAN::Frontend->mywarn("Suspicious key-value pair in META.yml's ".
3340             "requires hash: $k => $v; I'll take both ".
3341             "key and value as a module name\n");
3342 0         0 $CPAN::Frontend->mysleep(1);
3343 0         0 $areq->{$k} = 0;
3344 0         0 $areq->{$v} = 0;
3345 0         0 $do_replace++;
3346             }
3347             }
3348 0 0       0 $req = $areq if $do_replace;
3349             }
3350             }
3351             else {
3352 0         0 $CPAN::Frontend->mywarnonce("Could not read metadata file. Falling back to other ".
3353             "methods to determine prerequisites\n");
3354             }
3355              
3356 8 50 33     157 unless ($req || $breq) {
3357 0         0 my $build_dir;
3358 0 0       0 unless ( $build_dir = $self->{build_dir} ) {
3359 0         0 return;
3360             }
3361 0         0 my $makefile = File::Spec->catfile($build_dir,"Makefile");
3362 0         0 my $fh;
3363 0 0 0     0 if (-f $makefile
3364             and
3365             $fh = FileHandle->new("<$makefile\0")) {
3366 0 0       0 CPAN->debug("Getting prereq from Makefile") if $CPAN::DEBUG;
3367 0         0 local($/) = "\n";
3368 0         0 while (<$fh>) {
3369 0 0       0 last if /MakeMaker post_initialize section/;
3370 0         0 my($p) = m{^[\#]
3371             \s+PREREQ_PM\s+=>\s+(.+)
3372             }x;
3373 0 0       0 next unless $p;
3374             # warn "Found prereq expr[$p]";
3375              
3376             # Regexp modified by A.Speer to remember actual version of file
3377             # PREREQ_PM hash key wants, then add to
3378 0         0 while ( $p =~ m/(?:\s)([\w\:]+)=>(q\[.*?\]|undef),?/g ) {
3379 0         0 my($m,$n) = ($1,$2);
3380             # When a prereq is mentioned twice: let the bigger
3381             # win; usual culprit is that they declared
3382             # build_requires separately from requires; see
3383             # rt.cpan.org #47774
3384 0         0 my($prevn);
3385 0 0       0 if ( defined $req->{$m} ) {
3386 0         0 $prevn = $req->{$m};
3387             }
3388 0 0       0 if ($n =~ /^q\[(.*?)\]$/) {
3389 0         0 $n = $1;
3390             }
3391 0 0 0     0 if (!$prevn || CPAN::Version->vlt($prevn, $n)){
3392 0         0 $req->{$m} = $n;
3393             }
3394             }
3395 0         0 last;
3396             }
3397             }
3398             }
3399 8 50 33     24 unless ($req || $breq) {
3400 0 0       0 my $build_dir = $self->{build_dir} or die "Panic: no build_dir?";
3401 0         0 my $buildfile = File::Spec->catfile($build_dir,"Build");
3402 0 0       0 if (-f $buildfile) {
3403 0 0       0 CPAN->debug("Found '$buildfile'") if $CPAN::DEBUG;
3404 0         0 my $build_prereqs = File::Spec->catfile($build_dir,"_build","prereqs");
3405 0 0       0 if (-f $build_prereqs) {
3406 0 0       0 CPAN->debug("Getting prerequisites from '$build_prereqs'") if $CPAN::DEBUG;
3407 0         0 my $content = do { local *FH;
  0         0  
3408 0 0       0 open FH, $build_prereqs
3409             or $CPAN::Frontend->mydie("Could not open ".
3410             "'$build_prereqs': $!");
3411 0         0 local $/;
3412 0         0 ;
3413             };
3414 0         0 my $bphash = eval $content;
3415 0 0       0 if ($@) {
3416             } else {
3417 0   0     0 $req = $bphash->{requires} || +{};
3418 0   0     0 $breq = $bphash->{build_requires} || +{};
3419             }
3420             }
3421             }
3422             }
3423             # XXX needs to be adapted for optional_req & optional_breq -- xdg, 2012-04-01
3424 8 50 33     46 if ($req || $breq || $opt_req || $opt_breq ) {
      33        
      0        
3425             return $self->{prereq_pm} = {
3426 8         118 requires => $req,
3427             build_requires => $breq,
3428             opt_requires => $opt_req,
3429             opt_build_requires => $opt_breq,
3430             };
3431             }
3432             }
3433              
3434             #-> sub CPAN::Distribution::shortcut_test ;
3435             # return values: undef means don't shortcut; 0 means shortcut as fail;
3436             # and 1 means shortcut as success
3437             sub shortcut_test {
3438 0     0 0   my ($self) = @_;
3439              
3440 0 0         $self->debug("checking badtestcnt[$self->{ID}]") if $CPAN::DEBUG;
3441 0   0       $self->{badtestcnt} ||= 0;
3442 0 0         if ($self->{badtestcnt} > 0) {
3443 0           require Data::Dumper;
3444 0 0         CPAN->debug(sprintf "NOREPEAT[%s]", Data::Dumper::Dumper($self)) if $CPAN::DEBUG;
3445 0           return $self->goodbye("Won't repeat unsuccessful test during this command");
3446             }
3447              
3448 0           for my $slot ( qw/later configure_requires_later/ ) {
3449 0 0         $self->debug("checking $slot slot[$self->{ID}]") if $CPAN::DEBUG;
3450             return $self->success($self->{$slot})
3451 0 0         if $self->{$slot};
3452             }
3453              
3454 0 0         $self->debug("checking if tests passed[$self->{ID}]") if $CPAN::DEBUG;
3455 0 0         if ( $self->{make_test} ) {
3456 0 0         if (
    0          
3457             UNIVERSAL::can($self->{make_test},"failed") ?
3458             $self->{make_test}->failed :
3459             $self->{make_test} =~ /^NO/
3460             ) {
3461 0 0 0       if (
3462             UNIVERSAL::can($self->{make_test},"commandid")
3463             &&
3464             $self->{make_test}->commandid == $CPAN::CurrentCommandId
3465             ) {
3466 0           return $self->goodbye("Has already been tested within this command");
3467             }
3468             } else {
3469             # if global "is_tested" has been cleared, we need to mark this to
3470             # be added to PERL5LIB if not already installed
3471 0 0         if ($self->tested_ok_but_not_installed) {
3472 0           $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME});
3473             }
3474 0           return $self->success("Has already been tested successfully");
3475             }
3476             }
3477              
3478 0 0         if ($self->{notest}) {
3479 0           $self->{make_test} = CPAN::Distrostatus->new("YES");
3480 0           return $self->success("Skipping test because of notest pragma");
3481             }
3482              
3483 0           return undef; # no shortcut
3484             }
3485              
3486             #-> sub CPAN::Distribution::_exe_files ;
3487             sub _exe_files {
3488 0     0     my($self) = @_;
3489             return unless $self->{writemakefile} # no need to have succeeded
3490             # but we must have run it
3491 0 0 0       || $self->{modulebuild};
3492 0 0         unless ($self->{build_dir}) {
3493 0           return;
3494             }
3495             CPAN->debug(sprintf "writemakefile[%s]modulebuild[%s]",
3496             $self->{writemakefile}||"",
3497 0 0 0       $self->{modulebuild}||"",
      0        
3498             ) if $CPAN::DEBUG;
3499 0           my $build_dir;
3500 0 0         unless ( $build_dir = $self->{build_dir} ) {
3501 0           return;
3502             }
3503 0           my $makefile = File::Spec->catfile($build_dir,"Makefile");
3504 0           my $fh;
3505             my @exe_files;
3506 0 0 0       if (-f $makefile
3507             and
3508             $fh = FileHandle->new("<$makefile\0")) {
3509 0 0         CPAN->debug("Getting exefiles from Makefile") if $CPAN::DEBUG;
3510 0           local($/) = "\n";
3511 0           while (<$fh>) {
3512 0 0         last if /MakeMaker post_initialize section/;
3513 0           my($p) = m{^[\#]
3514             \s+EXE_FILES\s+=>\s+\[(.+)\]
3515             }x;
3516 0 0         next unless $p;
3517             # warn "Found exefiles expr[$p]";
3518 0           my @p = split /,\s*/, $p;
3519 0           for my $p2 (@p) {
3520 0 0         if ($p2 =~ /^q\[(.+)\]/) {
3521 0           push @exe_files, $1;
3522             }
3523             }
3524             }
3525             }
3526 0 0         return \@exe_files if @exe_files;
3527 0           my $buildparams = File::Spec->catfile($build_dir,"_build","build_params");
3528 0 0         if (-f $buildparams) {
3529 0 0         CPAN->debug("Found '$buildparams'") if $CPAN::DEBUG;
3530 0           my $x = do $buildparams;
3531 0           for my $sf ($x->[2]{script_files}) {
3532 0 0         if (my $reftype = ref $sf) {
    0          
3533 0 0         if ($reftype eq "ARRAY") {
    0          
3534 0           push @exe_files, @$sf;
3535             }
3536             elsif ($reftype eq "HASH") {
3537 0           push @exe_files, keys %$sf;
3538             }
3539             else {
3540 0           $CPAN::Frontend->mywarn("Invalid reftype $reftype for Build.PL 'script_files'\n");
3541             }
3542             }
3543             elsif (defined $sf) {
3544 0           push @exe_files, $sf;
3545             }
3546             }
3547             }
3548 0           return \@exe_files;
3549             }
3550              
3551             #-> sub CPAN::Distribution::test ;
3552             sub test {
3553 0     0 0   my($self) = @_;
3554              
3555 0           $self->pre_test();
3556              
3557 0 0         if (exists $self->{cleanup_after_install_done}) {
3558 0           return $self->make;
3559             }
3560              
3561 0 0         $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
3562 0 0         if (my $goto = $self->prefs->{goto}) {
3563 0           return $self->goto($goto);
3564             }
3565              
3566             $self->make
3567 0 0         or return;
3568              
3569 0 0         if ( defined( my $sc = $self->shortcut_test ) ) {
3570 0           return $sc;
3571             }
3572              
3573 0 0         if ($CPAN::Signal) {
3574 0           delete $self->{force_update};
3575 0           return;
3576             }
3577             # warn "XDEBUG: checking for notest: $self->{notest} $self";
3578 0 0         my $make = $self->{modulebuild} ? "Build" : "make";
3579              
3580             local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
3581             ? $ENV{PERL5LIB}
3582 0 0 0       : ($ENV{PERLLIB} || "");
3583              
3584 0 0         local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
3585 0 0         local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # test
3586 0           $CPAN::META->set_perl5lib;
3587 0           local $ENV{MAKEFLAGS}; # protect us from outer make calls
3588 0 0         local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
3589 0 0         local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
3590              
3591 0           $CPAN::Frontend->myprint(sprintf "Running %s test for %s\n", $make, $self->pretty_id);
3592              
3593 0 0         my $builddir = $self->dir or
3594             $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n");
3595              
3596 0 0         unless (chdir $builddir) {
3597 0           $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!");
3598 0           return;
3599             }
3600              
3601 0 0         $self->debug("Changed directory to $self->{build_dir}")
3602             if $CPAN::DEBUG;
3603              
3604 0 0         if ($^O eq 'MacOS') {
3605 0           Mac::BuildTools::make_test($self);
3606 0           return;
3607             }
3608              
3609 0 0         if ($self->{modulebuild}) {
3610 0           my $thm = CPAN::Shell->expand("Module","Test::Harness");
3611 0           my $v = $thm->inst_version;
3612 0 0         if (CPAN::Version->vlt($v,2.62)) {
3613             # XXX Eric Wilhelm reported this as a bug: klapperl:
3614             # Test::Harness 3.0 self-tests, so that should be 'unless
3615             # installing Test::Harness'
3616 0 0         unless ($self->id eq $thm->distribution->id) {
3617 0           $CPAN::Frontend->mywarn(qq{The version of your Test::Harness is only
3618             '$v', you need at least '2.62'. Please upgrade your Test::Harness.\n});
3619 0           $self->{make_test} = CPAN::Distrostatus->new("NO Test::Harness too old");
3620 0           return;
3621             }
3622             }
3623             }
3624              
3625 0 0         if ( ! $self->{force_update} ) {
3626             # bypass actual tests if "trust_test_report_history" and have a report
3627 0           my $have_tested_fcn;
3628 0 0 0       if ( $CPAN::Config->{trust_test_report_history}
      0        
3629             && $CPAN::META->has_inst("CPAN::Reporter::History")
3630             && ( $have_tested_fcn = CPAN::Reporter::History->can("have_tested" ))) {
3631 0 0         if ( my @reports = $have_tested_fcn->( dist => $self->base_id ) ) {
3632             # Do nothing if grade was DISCARD
3633 0 0         if ( $reports[-1]->{grade} =~ /^(?:PASS|UNKNOWN)$/ ) {
    0          
3634 0           $self->{make_test} = CPAN::Distrostatus->new("YES");
3635             # if global "is_tested" has been cleared, we need to mark this to
3636             # be added to PERL5LIB if not already installed
3637 0 0         if ($self->tested_ok_but_not_installed) {
3638 0           $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME});
3639             }
3640 0           $CPAN::Frontend->myprint("Found prior test report -- OK\n");
3641 0           return;
3642             }
3643             elsif ( $reports[-1]->{grade} =~ /^(?:FAIL|NA)$/ ) {
3644 0           $self->{make_test} = CPAN::Distrostatus->new("NO");
3645 0           $self->{badtestcnt}++;
3646 0           $CPAN::Frontend->mywarn("Found prior test report -- NOT OK\n");
3647 0           return;
3648             }
3649             }
3650             }
3651             }
3652              
3653 0           my $system;
3654 0           my $prefs_test = $self->prefs->{test};
3655 0 0         if (my $commandline
    0          
    0          
3656             = exists $prefs_test->{commandline} ? $prefs_test->{commandline} : "") {
3657 0           $system = $commandline;
3658 0           $ENV{PERL} = CPAN::find_perl();
3659             } elsif ($self->{modulebuild}) {
3660 0           $system = sprintf "%s test", $self->_build_command();
3661 0 0 0       unless (-e "Build" || ($^O eq 'VMS' && -e "Build.com")) {
      0        
3662 0           my $id = $self->pretty_id;
3663 0           $CPAN::Frontend->mywarn("Alert: no 'Build' file found while trying to test '$id'");
3664             }
3665             } else {
3666 0           $system = join " ", $self->_make_command(), "test";
3667             }
3668 0           my $make_test_arg = $self->_make_phase_arg("test");
3669 0 0         $system = sprintf("%s%s",
3670             $system,
3671             $make_test_arg ? " $make_test_arg" : "",
3672             );
3673 0           my($tests_ok);
3674             my $test_env;
3675 0 0         if ($self->prefs->{test}) {
3676 0           $test_env = $self->prefs->{test}{env};
3677             }
3678 0 0         local @ENV{keys %$test_env} = values %$test_env if $test_env;
3679 0           my $expect_model = $self->_prefs_with_expect("test");
3680 0           my $want_expect = 0;
3681 0 0 0       if ( $expect_model && @{$expect_model->{talk}} ) {
  0            
3682 0           my $can_expect = $CPAN::META->has_inst("Expect");
3683 0 0         if ($can_expect) {
3684 0           $want_expect = 1;
3685             } else {
3686 0           $CPAN::Frontend->mywarn("Expect not installed, falling back to ".
3687             "testing without\n");
3688             }
3689             }
3690 0 0         if ($want_expect) {
    0          
3691 0 0         if ($self->_should_report('test')) {
3692 0           $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is currently ".
3693             "not supported when distroprefs specify ".
3694             "an interactive test\n");
3695             }
3696 0           $tests_ok = $self->_run_via_expect($system,'test',$expect_model) == 0;
3697             } elsif ( $self->_should_report('test') ) {
3698 0           $tests_ok = CPAN::Reporter::test($self, $system);
3699             } else {
3700 0           $tests_ok = system($system) == 0;
3701             }
3702 0           $self->introduce_myself;
3703 0           my $but = $self->_make_test_illuminate_prereqs();
3704 0 0         if ( $tests_ok ) {
3705 0 0         if ($but) {
3706 0           $CPAN::Frontend->mywarn("Tests succeeded but $but\n");
3707 0           $self->{make_test} = CPAN::Distrostatus->new("NO $but");
3708 0           $self->store_persistent_state;
3709 0           return $self->goodbye("[dependencies] -- NA");
3710             }
3711 0           $CPAN::Frontend->myprint(" $system -- OK\n");
3712 0           $self->{make_test} = CPAN::Distrostatus->new("YES");
3713 0           $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME});
3714             # probably impossible to need the next line because badtestcnt
3715             # has a lifespan of one command
3716 0           delete $self->{badtestcnt};
3717             } else {
3718 0 0         if ($but) {
    0          
3719 0           $but .= "; additionally test harness failed";
3720 0           $CPAN::Frontend->mywarn("$but\n");
3721 0           $self->{make_test} = CPAN::Distrostatus->new("NO $but");
3722             } elsif ( $self->{force_update} ) {
3723 0           $self->{make_test} = CPAN::Distrostatus->new(
3724             "NO but failure ignored because 'force' in effect"
3725             );
3726             } else {
3727 0           $self->{make_test} = CPAN::Distrostatus->new("NO");
3728             }
3729 0           $self->{badtestcnt}++;
3730 0           $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
3731 0           CPAN::Shell->optprint
3732             ("hint",
3733             sprintf
3734             ("//hint// to see the cpan-testers results for installing this module, try:
3735             reports %s\n",
3736             $self->pretty_id));
3737             }
3738 0           $self->store_persistent_state;
3739              
3740 0           $self->post_test();
3741              
3742 0 0         return $self->{force_update} ? 1 : !! $tests_ok;
3743             }
3744              
3745             sub _make_test_illuminate_prereqs {
3746 0     0     my($self) = @_;
3747 0           my @prereq;
3748              
3749             # local $CPAN::DEBUG = 16; # Distribution
3750 0           for my $m (sort keys %{$self->{sponsored_mods}}) {
  0            
3751 0 0         next unless $self->{sponsored_mods}{$m} > 0;
3752 0 0         my $m_obj = CPAN::Shell->expand("Module",$m) or next;
3753             # XXX we need available_version which reflects
3754             # $ENV{PERL5LIB} so that already tested but not yet
3755             # installed modules are counted.
3756 0           my $available_version = $m_obj->available_version;
3757 0           my $available_file = $m_obj->available_file;
3758 0 0 0       if ($available_version &&
    0 0        
      0        
3759             !CPAN::Version->vlt($available_version,$self->{prereq_pm}{$m})
3760             ) {
3761 0 0         CPAN->debug("m[$m] good enough available_version[$available_version]")
3762             if $CPAN::DEBUG;
3763             } elsif ($available_file
3764             && (
3765             !$self->{prereq_pm}{$m}
3766             ||
3767             $self->{prereq_pm}{$m} == 0
3768             )
3769             ) {
3770             # lex Class::Accessor::Chained::Fast which has no $VERSION
3771 0 0         CPAN->debug("m[$m] have available_file[$available_file]")
3772             if $CPAN::DEBUG;
3773             } else {
3774             push @prereq, $m
3775 0 0         if $m_obj->{mandatory};
3776             }
3777             }
3778 0           my $but;
3779 0 0         if (@prereq) {
3780 0           my $cnt = @prereq;
3781 0           my $which = join ",", @prereq;
3782 0 0         $but = $cnt == 1 ? "one dependency not OK ($which)" :
3783             "$cnt dependencies missing ($which)";
3784             }
3785 0           $but;
3786             }
3787              
3788             sub _prefs_with_expect {
3789 0     0     my($self,$where) = @_;
3790 0 0         return unless my $prefs = $self->prefs;
3791 0 0         return unless my $where_prefs = $prefs->{$where};
3792 0 0         if ($where_prefs->{expect}) {
    0          
3793             return {
3794             mode => "deterministic",
3795             timeout => 15,
3796             talk => $where_prefs->{expect},
3797 0           };
3798             } elsif ($where_prefs->{"eexpect"}) {
3799 0           return $where_prefs->{"eexpect"};
3800             }
3801 0           return;
3802             }
3803              
3804             #-> sub CPAN::Distribution::clean ;
3805             sub clean {
3806 0     0 0   my($self) = @_;
3807 0 0         my $make = $self->{modulebuild} ? "Build" : "make";
3808 0           $CPAN::Frontend->myprint(sprintf "Running %s clean for %s\n", $make, $self->pretty_id);
3809 0 0         unless (exists $self->{archived}) {
3810 0           $CPAN::Frontend->mywarn("Distribution seems to have never been unzipped".
3811             "/untarred, nothing done\n");
3812 0           return 1;
3813             }
3814 0 0         unless (exists $self->{build_dir}) {
3815 0           $CPAN::Frontend->mywarn("Distribution has no own directory, nothing to do.\n");
3816 0           return 1;
3817             }
3818 0 0 0       if (exists $self->{writemakefile}
3819             and $self->{writemakefile}->failed
3820             ) {
3821 0           $CPAN::Frontend->mywarn("No Makefile, don't know how to 'make clean'\n");
3822 0           return 1;
3823             }
3824             EXCUSE: {
3825 0           my @e;
  0            
3826 0 0 0       exists $self->{make_clean} and $self->{make_clean} eq "YES" and
3827             push @e, "make clean already called once";
3828 0 0 0       $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
  0            
3829             }
3830 0 0         chdir "$self->{build_dir}" or
3831             Carp::confess("Couldn't chdir to $self->{build_dir}: $!");
3832 0 0         $self->debug("Changed directory to $self->{build_dir}") if $CPAN::DEBUG;
3833              
3834 0 0         if ($^O eq 'MacOS') {
3835 0           Mac::BuildTools::make_clean($self);
3836 0           return;
3837             }
3838              
3839 0           my $system;
3840 0 0         if ($self->{modulebuild}) {
3841 0 0         unless (-f "Build") {
3842 0           my $cwd = CPAN::anycwd();
3843 0           $CPAN::Frontend->mywarn("Alert: no Build file available for 'clean $self->{id}".
3844             " in cwd[$cwd]. Danger, Will Robinson!");
3845 0           $CPAN::Frontend->mysleep(5);
3846             }
3847 0           $system = sprintf "%s clean", $self->_build_command();
3848             } else {
3849 0           $system = join " ", $self->_make_command(), "clean";
3850             }
3851 0           my $system_ok = system($system) == 0;
3852 0           $self->introduce_myself;
3853 0 0         if ( $system_ok ) {
3854 0           $CPAN::Frontend->myprint(" $system -- OK\n");
3855              
3856             # $self->force;
3857              
3858             # Jost Krieger pointed out that this "force" was wrong because
3859             # it has the effect that the next "install" on this distribution
3860             # will untar everything again. Instead we should bring the
3861             # object's state back to where it is after untarring.
3862              
3863 0           for my $k (qw(
3864             force_update
3865             install
3866             writemakefile
3867             make
3868             make_test
3869             )) {
3870 0           delete $self->{$k};
3871             }
3872 0           $self->{make_clean} = CPAN::Distrostatus->new("YES");
3873              
3874             } else {
3875             # Hmmm, what to do if make clean failed?
3876              
3877 0           $self->{make_clean} = CPAN::Distrostatus->new("NO");
3878 0           $CPAN::Frontend->mywarn(qq{ $system -- NOT OK\n});
3879              
3880             # 2006-02-27: seems silly to me to force a make now
3881             # $self->force("make"); # so that this directory won't be used again
3882              
3883             }
3884 0           $self->store_persistent_state;
3885             }
3886              
3887             #-> sub CPAN::Distribution::check_disabled ;
3888             sub check_disabled {
3889 0     0 0   my ($self) = @_;
3890 0 0         $self->debug("checking disabled id[$self->{ID}]") if $CPAN::DEBUG;
3891 0 0 0       if ($self->prefs->{disabled} && ! $self->{force_update}) {
3892             return sprintf(
3893             "Disabled via prefs file '%s' doc %d",
3894             $self->{prefs_file},
3895             $self->{prefs_file_doc},
3896 0           );
3897             }
3898 0           return;
3899             }
3900              
3901             #-> sub CPAN::Distribution::goto ;
3902             sub goto {
3903 0     0 0   my($self,$goto) = @_;
3904 0           $goto = $self->normalize($goto);
3905             my $why = sprintf(
3906             "Goto '$goto' via prefs file '%s' doc %d",
3907             $self->{prefs_file},
3908             $self->{prefs_file_doc},
3909 0           );
3910 0           $self->{unwrapped} = CPAN::Distrostatus->new("NO $why");
3911             # 2007-07-16 akoenig : Better than NA would be if we could inherit
3912             # the status of the $goto distro but given the exceptional nature
3913             # of 'goto' I feel reluctant to implement it
3914 0           my $goodbye_message = "[goto] -- NA $why";
3915 0           $self->goodbye($goodbye_message);
3916              
3917             # inject into the queue
3918              
3919 0           CPAN::Queue->delete($self->id);
3920 0           CPAN::Queue->jumpqueue({qmod => $goto, reqtype => $self->{reqtype}});
3921              
3922             # and run where we left off
3923              
3924 0           my($method) = (caller(1))[3];
3925 0           my $goto_do = CPAN->instance("CPAN::Distribution",$goto);
3926 0 0         $goto_do->called_for($self->called_for) unless $goto_do->called_for;
3927 0   0       $goto_do->{mandatory} ||= $self->{mandatory};
3928 0   0       $goto_do->{reqtype} ||= $self->{reqtype};
3929 0           $goto_do->{coming_from} = $self->pretty_id;
3930 0           $goto_do->$method();
3931 0           CPAN::Queue->delete_first($goto);
3932             # XXX delete_first returns undef; is that what this should return
3933             # up the call stack, eg. return $sefl->goto($goto) -- xdg, 2012-04-04
3934             }
3935              
3936             #-> sub CPAN::Distribution::shortcut_install ;
3937             # return values: undef means don't shortcut; 0 means shortcut as fail;
3938             # and 1 means shortcut as success
3939             sub shortcut_install {
3940 0     0 0   my ($self) = @_;
3941              
3942 0 0         $self->debug("checking previous install results[$self->{ID}]") if $CPAN::DEBUG;
3943 0 0         if (exists $self->{install}) {
3944             my $text = UNIVERSAL::can($self->{install},"text") ?
3945             $self->{install}->text :
3946 0 0         $self->{install};
3947 0 0         if ($text =~ /^YES/) {
    0          
3948 0           $CPAN::META->is_installed($self->{build_dir});
3949 0           return $self->success("Already done");
3950             } elsif ($text =~ /is only/) {
3951             # e.g. 'is only build_requires': may be overruled later
3952 0           return $self->goodbye($text);
3953             } else {
3954             # comment in Todo on 2006-02-11; maybe retry?
3955 0           return $self->goodbye("Already tried without success");
3956             }
3957             }
3958              
3959 0           for my $slot ( qw/later configure_requires_later/ ) {
3960             return $self->success($self->{$slot})
3961 0 0         if $self->{$slot};
3962             }
3963              
3964 0           return undef;
3965             }
3966              
3967             #-> sub CPAN::Distribution::is_being_sponsored ;
3968              
3969             # returns true if we find a distro object in the queue that has
3970             # sponsored this one
3971             sub is_being_sponsored {
3972 0     0 0   my($self) = @_;
3973 0           my $iterator = CPAN::Queue->iterator;
3974 0           QITEM: while (my $q = $iterator->()) {
3975 0           my $s = $q->as_string;
3976 0 0         my $obj = CPAN::Shell->expandany($s) or next QITEM;
3977 0           my $type = ref $obj;
3978 0 0         if ( $type eq 'CPAN::Distribution' ){
3979 0 0         for my $module (sort keys %{$obj->{sponsored_mods} || {}}) {
  0            
3980 0 0         return 1 if grep { $_ eq $module } $self->containsmods;
  0            
3981             }
3982             }
3983             }
3984 0           return 0;
3985             }
3986              
3987             #-> sub CPAN::Distribution::install ;
3988             sub install {
3989 0     0 0   my($self) = @_;
3990              
3991 0           $self->pre_install();
3992              
3993 0 0         if (exists $self->{cleanup_after_install_done}) {
3994 0           return $self->test;
3995             }
3996              
3997 0 0         $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
3998 0 0         if (my $goto = $self->prefs->{goto}) {
3999 0           $self->goto($goto);
4000 0           $self->post_install();
4001 0           return;
4002             }
4003              
4004 0 0         unless ($self->test) {
4005 0           $self->post_install();
4006 0           return;
4007             }
4008              
4009 0 0         if ( defined( my $sc = $self->shortcut_install ) ) {
4010 0           $self->post_install();
4011 0           return $sc;
4012             }
4013              
4014 0 0         if ($CPAN::Signal) {
4015 0           delete $self->{force_update};
4016 0           $self->post_install();
4017 0           return;
4018             }
4019              
4020 0 0         my $builddir = $self->dir or
4021             $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n");
4022              
4023 0 0         unless (chdir $builddir) {
4024 0           $CPAN::Frontend->mywarn("Couldn't chdir to '$builddir': $!");
4025 0           $self->post_install();
4026 0           return;
4027             }
4028              
4029 0 0         $self->debug("Changed directory to $self->{build_dir}")
4030             if $CPAN::DEBUG;
4031              
4032 0 0         my $make = $self->{modulebuild} ? "Build" : "make";
4033 0           $CPAN::Frontend->myprint(sprintf "Running %s install for %s\n", $make, $self->pretty_id);
4034              
4035 0 0         if ($^O eq 'MacOS') {
4036 0           Mac::BuildTools::make_install($self);
4037 0           $self->post_install();
4038 0           return;
4039             }
4040              
4041 0           my $system;
4042 0 0         if (my $commandline = $self->prefs->{install}{commandline}) {
    0          
4043 0           $system = $commandline;
4044 0           $ENV{PERL} = CPAN::find_perl();
4045             } elsif ($self->{modulebuild}) {
4046             my($mbuild_install_build_command) =
4047             exists $CPAN::HandleConfig::keys{mbuild_install_build_command} &&
4048             $CPAN::Config->{mbuild_install_build_command} ?
4049             $CPAN::Config->{mbuild_install_build_command} :
4050 0 0 0       $self->_build_command();
4051 0 0         my $install_directive = $^O eq 'VMS' ? '"install"' : 'install';
4052             $system = sprintf("%s %s %s",
4053             $mbuild_install_build_command,
4054             $install_directive,
4055             $CPAN::Config->{mbuild_install_arg},
4056 0           );
4057             } else {
4058 0           my($make_install_make_command) = $self->_make_install_make_command();
4059             $system = sprintf("%s install %s",
4060             $make_install_make_command,
4061             $CPAN::Config->{make_install_arg},
4062 0           );
4063             }
4064              
4065 0 0 0       my($stderr) = $^O eq "MSWin32" || $^O eq 'VMS' ? "" : " 2>&1 ";
4066 0           my $brip = CPAN::HandleConfig->prefs_lookup($self,
4067             q{build_requires_install_policy});
4068 0   0       $brip ||="ask/yes";
4069 0           my $id = $self->id;
4070 0   0       my $reqtype = $self->{reqtype} ||= "c"; # in doubt it was a command
4071 0           my $want_install = "yes";
4072 0 0         if ($reqtype eq "b") {
4073 0 0         if ($brip eq "no") {
    0          
4074 0           $want_install = "no";
4075             } elsif ($brip =~ m|^ask/(.+)|) {
4076 0           my $default = $1;
4077 0 0         $default = "yes" unless $default =~ /^(y|n)/i;
4078 0           $want_install =
4079             CPAN::Shell::colorable_makemaker_prompt
4080             ("$id is just needed temporarily during building or testing. ".
4081             "Do you want to install it permanently?",
4082             $default);
4083             }
4084             }
4085 0 0         unless ($want_install =~ /^y/i) {
4086 0           my $is_only = "is only 'build_requires'";
4087 0           $self->{install} = CPAN::Distrostatus->new("NO -- $is_only");
4088 0           delete $self->{force_update};
4089 0           $self->goodbye("Not installing because $is_only");
4090 0           $self->post_install();
4091 0           return;
4092             }
4093             local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
4094             ? $ENV{PERL5LIB}
4095 0 0 0       : ($ENV{PERLLIB} || "");
4096              
4097 0 0         local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
4098 0 0         local $ENV{PERL_USE_UNSAFE_INC} = exists $ENV{PERL_USE_UNSAFE_INC} ? $ENV{PERL_USE_UNSAFE_INC} : 1; # install
4099 0           $CPAN::META->set_perl5lib;
4100 0 0         local $ENV{PERL_MM_USE_DEFAULT} = 1 if $CPAN::Config->{use_prompt_default};
4101 0 0         local $ENV{NONINTERACTIVE_TESTING} = 1 if $CPAN::Config->{use_prompt_default};
4102              
4103 0           my $install_env;
4104 0 0         if ($self->prefs->{install}) {
4105 0           $install_env = $self->prefs->{install}{env};
4106             }
4107 0 0         local @ENV{keys %$install_env} = values %$install_env if $install_env;
4108              
4109 0           my($pipe) = FileHandle->new("$system $stderr |");
4110 0 0         unless ($pipe) {
4111 0           $CPAN::Frontend->mywarn("Can't execute $system: $!");
4112 0           $self->introduce_myself;
4113 0           $self->{install} = CPAN::Distrostatus->new("NO");
4114 0           $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
4115 0           delete $self->{force_update};
4116 0           $self->post_install();
4117 0           return;
4118             }
4119 0           my($makeout) = "";
4120 0           while (<$pipe>) {
4121 0           print $_; # intentionally NOT use Frontend->myprint because it
4122             # looks irritating when we markup in color what we
4123             # just pass through from an external program
4124 0           $makeout .= $_;
4125             }
4126 0           $pipe->close;
4127 0           my $close_ok = $? == 0;
4128 0           $self->introduce_myself;
4129 0 0         if ( $close_ok ) {
4130 0           $CPAN::Frontend->myprint(" $system -- OK\n");
4131 0           $CPAN::META->is_installed($self->{build_dir});
4132 0           $self->{install} = CPAN::Distrostatus->new("YES");
4133 0 0 0       if ($CPAN::Config->{'cleanup_after_install'}
      0        
4134             && ! $self->is_dot_dist
4135             && ! $self->is_being_sponsored) {
4136 0           my $parent = File::Spec->catdir( $self->{build_dir}, File::Spec->updir );
4137 0 0         chdir $parent or $CPAN::Frontend->mydie("Couldn't chdir to $parent: $!\n");
4138 0           File::Path::rmtree($self->{build_dir});
4139 0           my $yml = "$self->{build_dir}.yml";
4140 0 0         if (-e $yml) {
4141 0 0         unlink $yml or $CPAN::Frontend->mydie("Couldn't unlink $yml: $!\n");
4142             }
4143 0           $self->{cleanup_after_install_done}=1;
4144             }
4145             } else {
4146 0           $self->{install} = CPAN::Distrostatus->new("NO");
4147 0           $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
4148 0           my $mimc =
4149             CPAN::HandleConfig->prefs_lookup($self,
4150             q{make_install_make_command});
4151 0 0 0       if (
      0        
      0        
4152             $makeout =~ /permission/s
4153             && $> > 0
4154             && (
4155             ! $mimc
4156             || $mimc eq (CPAN::HandleConfig->prefs_lookup($self,
4157             q{make}))
4158             )
4159             ) {
4160 0           $CPAN::Frontend->myprint(
4161             qq{----\n}.
4162             qq{ You may have to su }.
4163             qq{to root to install the package\n}.
4164             qq{ (Or you may want to run something like\n}.
4165             qq{ o conf make_install_make_command 'sudo make'\n}.
4166             qq{ to raise your permissions.}
4167             );
4168             }
4169             }
4170 0           delete $self->{force_update};
4171 0 0         unless ($CPAN::Config->{'cleanup_after_install'}) {
4172 0           $self->store_persistent_state;
4173             }
4174              
4175 0           $self->post_install();
4176              
4177 0           return !! $close_ok;
4178             }
4179              
4180             sub introduce_myself {
4181 0     0 0   my($self) = @_;
4182 0           $CPAN::Frontend->myprint(sprintf(" %s\n",$self->pretty_id));
4183             }
4184              
4185             #-> sub CPAN::Distribution::dir ;
4186             sub dir {
4187 0     0 0   shift->{build_dir};
4188             }
4189              
4190             #-> sub CPAN::Distribution::perldoc ;
4191             sub perldoc {
4192 0     0 0   my($self) = @_;
4193              
4194 0           my($dist) = $self->id;
4195 0           my $package = $self->called_for;
4196              
4197 0 0         if ($CPAN::META->has_inst("Pod::Perldocs")) {
4198 0 0         my($perl) = $self->perl
4199             or $CPAN::Frontend->mydie("Couldn't find executable perl\n");
4200 0           my @args = ($perl, q{-MPod::Perldocs}, q{-e},
4201             q{Pod::Perldocs->run()}, $package);
4202 0           my($wstatus);
4203 0 0         unless ( ($wstatus = system(@args)) == 0 ) {
4204 0           my $estatus = $wstatus >> 8;
4205 0           $CPAN::Frontend->myprint(qq{
4206             Function system("@args")
4207             returned status $estatus (wstat $wstatus)
4208             });
4209             }
4210             }
4211             else {
4212 0           $self->_display_url( $CPAN::Defaultdocs . $package );
4213             }
4214             }
4215              
4216             #-> sub CPAN::Distribution::_check_binary ;
4217             sub _check_binary {
4218 0     0     my ($dist,$shell,$binary) = @_;
4219 0           my ($pid,$out);
4220              
4221 0 0         $CPAN::Frontend->myprint(qq{ + _check_binary($binary)\n})
4222             if $CPAN::DEBUG;
4223              
4224 0 0         if ($CPAN::META->has_inst("File::Which")) {
4225 0           return File::Which::which($binary);
4226             } else {
4227 0           local *README;
4228 0 0         $pid = open README, "which $binary|"
4229             or $CPAN::Frontend->mywarn(qq{Could not fork 'which $binary': $!\n});
4230 0 0         return unless $pid;
4231 0           while () {
4232 0           $out .= $_;
4233             }
4234 0 0 0       close README
4235             or $CPAN::Frontend->mywarn("Could not run 'which $binary': $!\n")
4236             and return;
4237             }
4238              
4239 0 0 0       $CPAN::Frontend->myprint(qq{ + $out \n})
4240             if $CPAN::DEBUG && $out;
4241              
4242 0           return $out;
4243             }
4244              
4245             #-> sub CPAN::Distribution::_display_url ;
4246             sub _display_url {
4247 0     0     my($self,$url) = @_;
4248 0           my($res,$saved_file,$pid,$out);
4249              
4250 0 0         $CPAN::Frontend->myprint(qq{ + _display_url($url)\n})
4251             if $CPAN::DEBUG;
4252              
4253             # should we define it in the config instead?
4254 0           my $html_converter = "html2text.pl";
4255              
4256 0   0       my $web_browser = $CPAN::Config->{'lynx'} || undef;
4257 0 0         my $web_browser_out = $web_browser
4258             ? CPAN::Distribution->_check_binary($self,$web_browser)
4259             : undef;
4260              
4261 0 0         if ($web_browser_out) {
4262             # web browser found, run the action
4263 0           my $browser = CPAN::HandleConfig->safe_quote($CPAN::Config->{'lynx'});
4264 0 0         $CPAN::Frontend->myprint(qq{system[$browser $url]})
4265             if $CPAN::DEBUG;
4266 0           $CPAN::Frontend->myprint(qq{
4267             Displaying URL
4268             $url
4269             with browser $browser
4270             });
4271 0           $CPAN::Frontend->mysleep(1);
4272 0           system("$browser $url");
4273 0 0         if ($saved_file) { 1 while unlink($saved_file) }
  0            
4274             } else {
4275             # web browser not found, let's try text only
4276 0           my $html_converter_out =
4277             CPAN::Distribution->_check_binary($self,$html_converter);
4278 0           $html_converter_out = CPAN::HandleConfig->safe_quote($html_converter_out);
4279              
4280 0 0         if ($html_converter_out ) {
4281             # html2text found, run it
4282 0           $saved_file = CPAN::Distribution->_getsave_url( $self, $url );
4283 0 0         $CPAN::Frontend->mydie(qq{ERROR: problems while getting $url\n})
4284             unless defined($saved_file);
4285              
4286 0           local *README;
4287 0 0         $pid = open README, "$html_converter $saved_file |"
4288             or $CPAN::Frontend->mydie(qq{
4289             Could not fork '$html_converter $saved_file': $!});
4290 0           my($fh,$filename);
4291 0 0         if ($CPAN::META->has_usable("File::Temp")) {
4292 0           $fh = File::Temp->new(
4293             dir => File::Spec->tmpdir,
4294             template => 'cpan_htmlconvert_XXXX',
4295             suffix => '.txt',
4296             unlink => 0,
4297             );
4298 0           $filename = $fh->filename;
4299             } else {
4300 0           $filename = "cpan_htmlconvert_$$.txt";
4301 0           $fh = FileHandle->new();
4302 0 0         open $fh, ">$filename" or die;
4303             }
4304 0           while () {
4305 0           $fh->print($_);
4306             }
4307 0 0         close README or
4308             $CPAN::Frontend->mydie(qq{Could not run '$html_converter $saved_file': $!});
4309 0           my $tmpin = $fh->filename;
4310 0 0         $CPAN::Frontend->myprint(sprintf(qq{
4311             Run '%s %s' and
4312             saved output to %s\n},
4313             $html_converter,
4314             $saved_file,
4315             $tmpin,
4316             )) if $CPAN::DEBUG;
4317 0           close $fh;
4318 0           local *FH;
4319 0 0         open FH, $tmpin
4320             or $CPAN::Frontend->mydie(qq{Could not open "$tmpin": $!});
4321 0           my $fh_pager = FileHandle->new;
4322 0           local($SIG{PIPE}) = "IGNORE";
4323 0   0       my $pager = $CPAN::Config->{'pager'} || "cat";
4324 0 0         $fh_pager->open("|$pager")
4325             or $CPAN::Frontend->mydie(qq{
4326             Could not open pager '$pager': $!});
4327 0           $CPAN::Frontend->myprint(qq{
4328             Displaying URL
4329             $url
4330             with pager "$pager"
4331             });
4332 0           $CPAN::Frontend->mysleep(1);
4333 0           $fh_pager->print();
4334 0           $fh_pager->close;
4335             } else {
4336             # coldn't find the web browser or html converter
4337 0           $CPAN::Frontend->myprint(qq{
4338             You need to install lynx or $html_converter to use this feature.});
4339             }
4340             }
4341             }
4342              
4343             #-> sub CPAN::Distribution::_getsave_url ;
4344             sub _getsave_url {
4345 0     0     my($dist, $shell, $url) = @_;
4346              
4347 0 0         $CPAN::Frontend->myprint(qq{ + _getsave_url($url)\n})
4348             if $CPAN::DEBUG;
4349              
4350 0           my($fh,$filename);
4351 0 0         if ($CPAN::META->has_usable("File::Temp")) {
4352 0           $fh = File::Temp->new(
4353             dir => File::Spec->tmpdir,
4354             template => "cpan_getsave_url_XXXX",
4355             suffix => ".html",
4356             unlink => 0,
4357             );
4358 0           $filename = $fh->filename;
4359             } else {
4360 0           $fh = FileHandle->new;
4361 0           $filename = "cpan_getsave_url_$$.html";
4362             }
4363 0           my $tmpin = $filename;
4364 0 0         if ($CPAN::META->has_usable('LWP')) {
4365 0           $CPAN::Frontend->myprint("Fetching with LWP:
4366             $url
4367             ");
4368 0           my $Ua;
4369 0           CPAN::LWP::UserAgent->config;
4370 0           eval { $Ua = CPAN::LWP::UserAgent->new; };
  0            
4371 0 0         if ($@) {
4372 0           $CPAN::Frontend->mywarn("ERROR: CPAN::LWP::UserAgent->new dies with $@\n");
4373 0           return;
4374             } else {
4375 0           my($var);
4376             $Ua->proxy('http', $var)
4377 0 0 0       if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy};
4378             $Ua->no_proxy($var)
4379 0 0 0       if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy};
4380             }
4381              
4382 0           my $req = HTTP::Request->new(GET => $url);
4383 0           $req->header('Accept' => 'text/html');
4384 0           my $res = $Ua->request($req);
4385 0 0         if ($res->is_success) {
4386 0 0         $CPAN::Frontend->myprint(" + request successful.\n")
4387             if $CPAN::DEBUG;
4388 0           print $fh $res->content;
4389 0           close $fh;
4390 0 0         $CPAN::Frontend->myprint(qq{ + saved content to $tmpin \n})
4391             if $CPAN::DEBUG;
4392 0           return $tmpin;
4393             } else {
4394 0           $CPAN::Frontend->myprint(sprintf(
4395             "LWP failed with code[%s], message[%s]\n",
4396             $res->code,
4397             $res->message,
4398             ));
4399 0           return;
4400             }
4401             } else {
4402 0           $CPAN::Frontend->mywarn(" LWP not available\n");
4403 0           return;
4404             }
4405             }
4406              
4407             #-> sub CPAN::Distribution::_build_command
4408             sub _build_command {
4409 0     0     my($self) = @_;
4410 0 0         if ($^O eq "MSWin32") { # special code needed at least up to
    0          
4411             # Module::Build 0.2611 and 0.2706; a fix
4412             # in M:B has been promised 2006-01-30
4413 0 0         my($perl) = $self->perl or $CPAN::Frontend->mydie("Couldn't find executable perl\n");
4414 0           return "$perl ./Build";
4415             }
4416             elsif ($^O eq 'VMS') {
4417 0           return "$^X Build.com";
4418             }
4419 0           return "./Build";
4420             }
4421              
4422             #-> sub CPAN::Distribution::_should_report
4423             sub _should_report {
4424 0     0     my($self, $phase) = @_;
4425 0 0         die "_should_report() requires a 'phase' argument"
4426             if ! defined $phase;
4427              
4428 0 0         return unless $CPAN::META->has_usable("CPAN::Reporter");
4429              
4430             # configured
4431 0           my $test_report = CPAN::HandleConfig->prefs_lookup($self,
4432             q{test_report});
4433 0 0         return unless $test_report;
4434              
4435             # don't repeat if we cached a result
4436             return $self->{should_report}
4437 0 0         if exists $self->{should_report};
4438              
4439             # don't report if we generated a Makefile.PL
4440 0 0         if ( $self->{had_no_makefile_pl} ) {
4441 0           $CPAN::Frontend->mywarn(
4442             "Will not send CPAN Testers report with generated Makefile.PL.\n"
4443             );
4444 0           return $self->{should_report} = 0;
4445             }
4446              
4447             # available
4448 0 0         if ( ! $CPAN::META->has_inst("CPAN::Reporter")) {
4449 0           $CPAN::Frontend->mywarnonce(
4450             "CPAN::Reporter not installed. No reports will be sent.\n"
4451             );
4452 0           return $self->{should_report} = 0;
4453             }
4454              
4455             # capable
4456 0           my $crv = CPAN::Reporter->VERSION;
4457 0 0         if ( CPAN::Version->vlt( $crv, 0.99 ) ) {
4458             # don't cache $self->{should_report} -- need to check each phase
4459 0 0         if ( $phase eq 'test' ) {
4460 0           return 1;
4461             }
4462             else {
4463 0           $CPAN::Frontend->mywarn(
4464             "Reporting on the '$phase' phase requires CPAN::Reporter 0.99, but \n" .
4465             "you only have version $crv\. Only 'test' phase reports will be sent.\n"
4466             );
4467 0           return;
4468             }
4469             }
4470              
4471             # appropriate
4472 0 0         if ($self->is_dot_dist) {
4473 0           $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ".
4474             "for local directories\n");
4475 0           return $self->{should_report} = 0;
4476             }
4477 0 0 0       if ($self->prefs->{patches}
      0        
4478             &&
4479 0           @{$self->prefs->{patches}}
4480             &&
4481             $self->{patched}
4482             ) {
4483 0           $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ".
4484             "when the source has been patched\n");
4485 0           return $self->{should_report} = 0;
4486             }
4487              
4488             # proceed and cache success
4489 0           return $self->{should_report} = 1;
4490             }
4491              
4492             #-> sub CPAN::Distribution::reports
4493             sub reports {
4494 0     0 0   my($self) = @_;
4495 0           my $pathname = $self->id;
4496 0           $CPAN::Frontend->myprint("Distribution: $pathname\n");
4497              
4498 0 0         unless ($CPAN::META->has_inst("CPAN::DistnameInfo")) {
4499 0           $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue");
4500             }
4501 0 0         unless ($CPAN::META->has_usable("LWP")) {
4502 0           $CPAN::Frontend->mydie("LWP not installed; cannot continue");
4503             }
4504 0 0         unless ($CPAN::META->has_usable("File::Temp")) {
4505 0           $CPAN::Frontend->mydie("File::Temp not installed; cannot continue");
4506             }
4507              
4508 0           my $format;
4509 0 0 0       if ($CPAN::META->has_inst("YAML::XS") || $CPAN::META->has_inst("YAML::Syck")){
    0 0        
4510 0           $format = 'yaml';
4511             }
4512             elsif (!$format && $CPAN::META->has_inst("JSON::PP") ) {
4513 0           $format = 'json';
4514             }
4515             else {
4516 0           $CPAN::Frontend->mydie("JSON::PP not installed, cannot continue");
4517             }
4518              
4519 0           my $d = CPAN::DistnameInfo->new($pathname);
4520              
4521 0           my $dist = $d->dist; # "CPAN-DistnameInfo"
4522 0           my $version = $d->version; # "0.02"
4523 0           my $maturity = $d->maturity; # "released"
4524 0           my $filename = $d->filename; # "CPAN-DistnameInfo-0.02.tar.gz"
4525 0           my $cpanid = $d->cpanid; # "GBARR"
4526 0           my $distvname = $d->distvname; # "CPAN-DistnameInfo-0.02"
4527              
4528 0           my $url = sprintf "http://www.cpantesters.org/show/%s.%s", $dist, $format;
4529              
4530 0           CPAN::LWP::UserAgent->config;
4531 0           my $Ua;
4532 0           eval { $Ua = CPAN::LWP::UserAgent->new; };
  0            
4533 0 0         if ($@) {
4534 0           $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n");
4535             }
4536 0           $CPAN::Frontend->myprint("Fetching '$url'...");
4537 0           my $resp = $Ua->get($url);
4538 0 0         unless ($resp->is_success) {
4539 0           $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code);
4540             }
4541 0           $CPAN::Frontend->myprint("DONE\n\n");
4542 0           my $unserialized;
4543 0 0         if ( $format eq 'yaml' ) {
4544 0           my $yaml = $resp->content;
4545             # what a long way round!
4546 0           my $fh = File::Temp->new(
4547             dir => File::Spec->tmpdir,
4548             template => 'cpan_reports_XXXX',
4549             suffix => '.yaml',
4550             unlink => 0,
4551             );
4552 0           my $tfilename = $fh->filename;
4553 0           print $fh $yaml;
4554 0 0         close $fh or $CPAN::Frontend->mydie("Could not close '$tfilename': $!");
4555 0           $unserialized = CPAN->_yaml_loadfile($tfilename)->[0];
4556 0 0         unlink $tfilename or $CPAN::Frontend->mydie("Could not unlink '$tfilename': $!");
4557             } else {
4558 0           require JSON::PP;
4559 0           $unserialized = JSON::PP->new->utf8->decode($resp->content);
4560             }
4561 0           my %other_versions;
4562             my $this_version_seen;
4563 0           for my $rep (@$unserialized) {
4564 0           my $rversion = $rep->{version};
4565 0 0         if ($rversion eq $version) {
4566 0 0         unless ($this_version_seen++) {
4567 0           $CPAN::Frontend->myprint ("$rep->{version}:\n");
4568             }
4569 0   0       my $arch = $rep->{archname} || $rep->{platform} || '????';
4570 0   0       my $grade = $rep->{action} || $rep->{status} || '????';
4571 0   0       my $ostext = $rep->{ostext} || ucfirst($rep->{osname}) || '????';
4572             $CPAN::Frontend->myprint
4573             (sprintf("%1s%1s%-4s %s on %s %s (%s)\n",
4574             $arch eq $Config::Config{archname}?"*":"",
4575             $grade eq "PASS"?"+":$grade eq"FAIL"?"-":"",
4576             $grade,
4577             $rep->{perl},
4578             $ostext,
4579             $rep->{osvers},
4580 0 0         $arch,
    0          
    0          
4581             ));
4582             } else {
4583 0           $other_versions{$rep->{version}}++;
4584             }
4585             }
4586 0 0         unless ($this_version_seen) {
4587 0           $CPAN::Frontend->myprint("No reports found for version '$version'
4588             Reports for other versions:\n");
4589 0           for my $v (sort keys %other_versions) {
4590 0           $CPAN::Frontend->myprint(" $v\: $other_versions{$v}\n");
4591             }
4592             }
4593 0           $url = substr($url,0,-4) . 'html';
4594 0           $CPAN::Frontend->myprint("See $url for details\n");
4595             }
4596              
4597             1;