File Coverage

blib/lib/CPAN/Distribution.pm
Criterion Covered Total %
statement 91 2179 4.1
branch 29 1424 2.0
condition 11 530 2.0
subroutine 15 111 13.5
pod 0 73 0.0
total 146 4317 3.3


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