File Coverage

lib/CPANPLUS/Dist.pm
Criterion Covered Total %
statement 262 291 90.0
branch 75 110 68.1
condition 33 49 67.3
subroutine 26 26 100.0
pod 6 7 85.7
total 402 483 83.2


line stmt bran cond sub pod time code
1             package CPANPLUS::Dist;
2              
3 20     20   140 use strict;
  20         71  
  20         707  
4              
5 20     20   132 use CPANPLUS::Error;
  20         42  
  20         1543  
6 20     20   172 use CPANPLUS::Internals::Constants;
  20         53  
  20         6630  
7              
8 20     20   157 use Cwd ();
  20         45  
  20         433  
9 20     20   122 use Object::Accessor;
  20         54  
  20         576  
10 20     20   10256 use Parse::CPAN::Meta;
  20         31709  
  20         955  
11              
12 20     20   146 use IPC::Cmd qw[run];
  20         44  
  20         877  
13 20     20   130 use Params::Check qw[check];
  20         40  
  20         795  
14 20     20   123 use Module::Load::Conditional qw[can_load check_install];
  20         37  
  20         901  
15 20     20   108 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
  20         39  
  20         125  
16              
17 20     20   5156 use vars qw[$VERSION];
  20         38  
  20         1116  
18             $VERSION = "0.9912";
19              
20 20     20   144 use base 'Object::Accessor';
  20         43  
  20         69414  
21              
22             local $Params::Check::VERBOSE = 1;
23              
24             =pod
25              
26             =head1 NAME
27              
28             CPANPLUS::Dist - base class for plugins
29              
30             =head1 SYNOPSIS
31              
32             my $dist = CPANPLUS::Dist::YOUR_DIST_TYPE_HERE->new(
33             module => $modobj,
34             );
35              
36             =head1 DESCRIPTION
37              
38             C<CPANPLUS::Dist> is a base class for C<CPANPLUS::Dist::MM>
39             and C<CPANPLUS::Dist::Build>. Developers of other C<CPANPLUS::Dist::*>
40             plugins should look at C<CPANPLUS::Dist::Base>.
41              
42             =head1 ACCESSORS
43              
44             =over 4
45              
46             =item parent()
47              
48             Returns the C<CPANPLUS::Module> object that parented this object.
49              
50             =item status()
51              
52             Returns the C<Object::Accessor> object that keeps the status for
53             this module.
54              
55             =back
56              
57             =head1 STATUS ACCESSORS
58              
59             All accessors can be accessed as follows:
60             $deb->status->ACCESSOR
61              
62             =over 4
63              
64             =item created()
65              
66             Boolean indicating whether the dist was created successfully.
67             Explicitly set to C<0> when failed, so a value of C<undef> may be
68             interpreted as C<not yet attempted>.
69              
70             =item installed()
71              
72             Boolean indicating whether the dist was installed successfully.
73             Explicitly set to C<0> when failed, so a value of C<undef> may be
74             interpreted as C<not yet attempted>.
75              
76             =item uninstalled()
77              
78             Boolean indicating whether the dist was uninstalled successfully.
79             Explicitly set to C<0> when failed, so a value of C<undef> may be
80             interpreted as C<not yet attempted>.
81              
82             =item dist()
83              
84             The location of the final distribution. This may be a file or
85             directory, depending on how your distribution plug in of choice
86             works. This will be set upon a successful create.
87              
88             =cut
89              
90             =back
91              
92             =head2 $dist = CPANPLUS::Dist::YOUR_DIST_TYPE_HERE->new( module => MODOBJ );
93              
94             Create a new C<CPANPLUS::Dist::YOUR_DIST_TYPE_HERE> object based on the
95             provided C<MODOBJ>.
96              
97             *** DEPRECATED ***
98             The optional argument C<format> is used to indicate what type of dist
99             you would like to create (like C<CPANPLUS::Dist::MM> or
100             C<CPANPLUS::Dist::Build> and so on ).
101              
102             C<< CPANPLUS::Dist->new >> is exclusively meant as a method to be
103             inherited by C<CPANPLUS::Dist::MM|Build>.
104              
105             Returns a C<CPANPLUS::Dist::YOUR_DIST_TYPE_HERE> object on success
106             and false on failure.
107              
108             =cut
109              
110             sub new {
111 44     44 1 4752 my $self = shift;
112 44   33     482 my $class = ref $self || $self;
113 44         269 my %hash = @_;
114              
115             ### first verify we got a module object ###
116 44         111 my( $mod, $format );
117 44         705 my $tmpl = {
118             module => { required => 1, allow => IS_MODOBJ, store => \$mod },
119             ### for backwards compatibility
120             format => { default => $class, store => \$format,
121             allow => [ __PACKAGE__->dist_types ],
122             },
123             };
124 44 50       287 check( $tmpl, \%hash ) or return;
125              
126 44 50       1679 unless( can_load( modules => { $format => '0.0' }, verbose => 1 ) ) {
127 0         0 error(loc("'%1' not found -- you need '%2' version '%3' or higher ".
128             "to detect plugins", $format, 'Module::Pluggable','2.4'));
129 0         0 return;
130             }
131              
132             ### get an empty o::a object for this class
133 44         55368 my $obj = $format->SUPER::new;
134              
135 44         975 $obj->mk_accessors( qw[parent status] );
136              
137             ### set the parent
138 44         2466 $obj->parent( $mod );
139              
140             ### create a status object ###
141 44         6802 { my $acc = Object::Accessor->new;
  44         200  
142 44         517 $obj->status($acc);
143              
144             ### add minimum supported accessors
145 44         5055 $acc->mk_accessors( qw[prepared created installed uninstalled
146             distdir dist _metadata] );
147             }
148              
149             ### get the conf object ###
150 44         3813 my $conf = $mod->parent->configure_object();
151              
152             ### check if the format is available in this environment ###
153 44 100 100     372 if( $conf->_get_build('sanity_check') and not $obj->format_available ) {
154 1         12 error( loc( "Format '%1' is not available", $format) );
155 1         14 return;
156             }
157              
158             ### now initialize it or admit failure
159 43 100       396 unless( $obj->init ) {
160 1         154 error(loc("Dist initialization of '%1' failed for '%2'",
161             $format, $mod->module));
162 1         14 return;
163             }
164              
165             ### return the object
166 42         4926 return $obj;
167             }
168              
169             =head2 @dists = CPANPLUS::Dist->dist_types;
170              
171             Returns a list of the CPANPLUS::Dist::* classes available
172              
173             =cut
174              
175             ### returns a list of dist_types we support
176             ### will get overridden by Module::Pluggable if loaded
177             ### XXX add support for 'plugin' dir in config as well
178             { my $Loaded;
179             my @Dists = (INSTALLER_MM);
180             my @Ignore = ();
181              
182             ### backdoor method to add more dist types
183 1     1   3815 sub _add_dist_types { my $self = shift; push @Dists, @_ };
  1         24  
184              
185             ### backdoor method to exclude dist types
186 1     1   97 sub _ignore_dist_types { my $self = shift; push @Ignore, @_ };
  1         5  
187 1     1   49 sub _reset_dist_ignore { @Ignore = () };
188              
189             ### locally add the plugins dir to @INC, so we can find extra plugins
190             #local @INC = @INC, File::Spec->catdir(
191             # $conf->get_conf('base'),
192             # $conf->_get_build('plugins') );
193              
194             ### load any possible plugins
195             sub dist_types {
196              
197 99 100 66 99 1 9731 if ( !$Loaded++ and check_install( module => 'Module::Pluggable',
198             version => '2.4')
199             ) {
200 5         33974 require Module::Pluggable;
201              
202 5         60998 my $only_re = __PACKAGE__ . '::\w+$';
203 5         49 my %except = map { $_ => 1 }
  10         78  
204             INSTALLER_SAMPLE,
205             INSTALLER_BASE;
206              
207 5         187 Module::Pluggable->import(
208             sub_name => '_dist_types',
209             search_path => __PACKAGE__,
210             only => qr/$only_re/,
211             require => 1,
212             except => [ keys %except ]
213             );
214 5         888 my %ignore = map { $_ => $_ } @Ignore;
  1         10  
215              
216 5   66     41 push @Dists, grep { not $ignore{$_} and not $except{$_} }
  13         28479  
217             __PACKAGE__->_dist_types;
218             }
219              
220 99         1817 return @Dists;
221             }
222              
223             =head2 $bool = CPANPLUS::Dist->rescan_dist_types;
224              
225             Rescans C<@INC> for available dist types. Useful if you've installed new
226             C<CPANPLUS::Dist::*> classes and want to make them available to the
227             current process.
228              
229             =cut
230              
231             sub rescan_dist_types {
232 1     1 1 19 my $dist = shift;
233 1         3 $Loaded = 0; # reset the flag;
234 1         5 return $dist->dist_types;
235             }
236             }
237              
238             =head2 $bool = CPANPLUS::Dist->has_dist_type( $type )
239              
240             Returns true if distribution type C<$type> is loaded/supported.
241              
242             =cut
243              
244             sub has_dist_type {
245 21     21 1 75 my $dist = shift;
246 21 50       87 my $type = shift or return;
247              
248 21         150 return scalar grep { $_ eq $type } CPANPLUS::Dist->dist_types;
  82         265  
249             }
250              
251             =head2 $bool = $dist->prereq_satisfied( modobj => $modobj, version => $version_spec )
252              
253             Returns true if this prereq is satisfied. Returns false if it's not.
254             Also issues an error if it seems "unsatisfiable," i.e. if it can't be
255             found on CPAN or the latest CPAN version doesn't satisfy it.
256              
257             =cut
258              
259             sub prereq_satisfied {
260 30     30 1 194 my $dist = shift;
261 30         702 my $cb = $dist->parent->parent;
262 30         547 my %hash = @_;
263              
264 30         132 my($mod,$ver);
265 30         1023 my $tmpl = {
266             version => { required => 1, store => \$ver },
267             modobj => { required => 1, store => \$mod, allow => IS_MODOBJ },
268             };
269              
270 30 50       560 check( $tmpl, \%hash ) or return;
271              
272 30 100       1712 return 1 if $mod->is_uptodate( version => $ver );
273              
274 19 100       146 if ( $cb->_vcmp( $ver, $mod->version ) > 0 ) {
275              
276 15         97 error(loc(
277             "This distribution depends on %1, but the latest version".
278             " of %2 on CPAN (%3) doesn't satisfy the specific version".
279             " dependency (%4). You may have to resolve this dependency ".
280             "manually.",
281             $mod->module, $mod->module, $mod->version, $ver ));
282              
283             }
284              
285 19         349 return;
286             }
287              
288             =head2 $configure_requires = $dist->find_configure_requires( [file => /path/to/META.yml] )
289              
290             Reads the configure_requires for this distribution from the META.yml or META.json
291             file in the root directory and returns a hashref with module names
292             and versions required.
293              
294             =cut
295              
296             sub find_configure_requires {
297 10     10 1 890 my $self = shift;
298 10         267 my $mod = $self->parent;
299 10         2666 my %hash = @_;
300              
301 10         35 my ($meta);
302 10         32 my $href = {};
303              
304 10         94 my $tmpl = {
305             file => { store => \$meta },
306             };
307              
308 10         155 $self->_stash_metadata(); # Okay hacks.
309              
310 10 50       68 check( $tmpl, \%hash ) or return;
311              
312 10         830 my $meth = 'configure_requires';
313              
314             {
315              
316             ### the prereqs as we have them now
317 10   100     37 my @args = (
  10         59  
318             defaults => $mod->status->$meth || {},
319             );
320              
321 10 100       1164 my @possibles = do { defined $mod->status->extract
  10         67  
322             ? ( META_JSON->( $mod->status->extract ),
323             META_YML->( $mod->status->extract ) )
324             : ()
325             };
326              
327 10 100       162 unshift @possibles, $meta if $meta;
328              
329 10         42 META: foreach my $mfile ( grep { -e } @possibles ) {
  19         488  
330 10         72 push @args, ( file => $mfile );
331 10 50       75 if ( $mfile =~ /\.json/ ) {
332 0         0 $href = $self->_prereqs_from_meta_json( @args, keys => [ 'configure' ] );
333             }
334             else {
335 10         132 $href = $self->_prereqs_from_meta_file( @args, keys => [ $meth ] );
336             }
337 10         66 last META;
338             }
339              
340             }
341              
342             ### and store it in the module
343 10         59 $mod->status->$meth( $href );
344              
345 10         1099 return { %$href };
346             }
347              
348             sub find_mymeta_requires {
349 3     3 0 21 my $self = shift;
350 3         49 my $mod = $self->parent;
351 3         379 my %hash = @_;
352              
353 3         17 my ($meta);
354 3         12 my $href = {};
355              
356 3         19 my $tmpl = {
357             file => { store => \$meta },
358             };
359              
360 3 50       28 check( $tmpl, \%hash ) or return;
361              
362 3         200 my $meth = 'prereqs';
363              
364             {
365              
366             ### the prereqs as we have them now
367 3   50     20 my @args = (
  3         28  
368             defaults => $mod->status->$meth || {},
369             );
370              
371 3 50       416 my @possibles = do { defined $mod->status->extract
  3         44  
372             ? ( MYMETA_JSON->( $mod->status->extract ),
373             MYMETA_YML->( $mod->status->extract ) )
374             : ()
375             };
376              
377 3 50       38 unshift @possibles, $meta if $meta;
378              
379 3         22 META: foreach my $mfile ( grep { -e } @possibles ) {
  6         124  
380 3         35 push @args, ( file => $mfile );
381 3 50       96 if ( $mfile =~ /\.json/ ) {
382 3         75 $href = $self->_prereqs_from_meta_json( @args,
383             keys => [ qw|build test runtime| ] );
384             }
385             else {
386 0         0 $href = $self->_prereqs_from_meta_file( @args,
387             keys => [ qw|build_requires requires| ] );
388             }
389 3         20 last META;
390             }
391              
392             }
393              
394             ### and store it in the module
395 3         34 $mod->status->$meth( $href );
396              
397 3         333 return { %$href };
398             }
399              
400             sub _prereqs_from_meta_file {
401 10     10   35 my $self = shift;
402 10         110 my $mod = $self->parent;
403 10         1336 my %hash = @_;
404              
405 10         53 my( $meta, $defaults, $keys );
406             my $tmpl = { ### check if we have an extract path. if not, we
407             ### get 'undef value' warnings from file::spec
408 10 100       75 file => { default => do { defined $mod->status->extract
  10         51  
409             ? META_YML->( $mod->status->extract )
410             : '' },
411             store => \$meta,
412             },
413             defaults => { required => 1, default => {}, strict_type => 1,
414             store => \$defaults },
415             keys => { required => 1, default => [], strict_type => 1,
416             store => \$keys },
417             };
418              
419 10 50       169 check( $tmpl, \%hash ) or return;
420              
421             ### if there's a meta file, we read it;
422 10 50       2018 if( -e $meta ) {
423              
424             ### Parse::CPAN::Meta uses exceptions for errors
425             ### hash returned in list context!!!
426              
427 10         77 local $ENV{PERL_YAML_BACKEND};
428              
429 10         39 my ($doc) = eval { Parse::CPAN::Meta::LoadFile( $meta ) };
  10         52  
430              
431 10 50       16300 unless( $doc ) {
432 0         0 error(loc( "Could not read %1: '%2'", $meta, $@ ));
433 0         0 return $defaults;
434             }
435              
436             ### read the keys now, make sure not to throw
437             ### away anything that was already added
438 10         86 for my $key ( @$keys ) {
439             $defaults = {
440             %$defaults,
441 10         175 %{ $doc->{$key} },
442 10 50       103 } if $doc->{ $key };
443             }
444             }
445              
446             ### and return a copy
447 10         41 return \%{ $defaults };
  10         77  
448             }
449              
450             sub _prereqs_from_meta_json {
451 3     3   18 my $self = shift;
452 3         47 my $mod = $self->parent;
453 3         509 my %hash = @_;
454              
455 3         18 my( $meta, $defaults, $keys );
456             my $tmpl = { ### check if we have an extract path. if not, we
457             ### get 'undef value' warnings from file::spec
458 3 50       15 file => { default => do { defined $mod->status->extract
  3         42  
459             ? META_JSON->( $mod->status->extract )
460             : '' },
461             store => \$meta,
462             },
463             defaults => { required => 1, default => {}, strict_type => 1,
464             store => \$defaults },
465             keys => { required => 1, default => [], strict_type => 1,
466             store => \$keys },
467             };
468              
469 3 50       33 check( $tmpl, \%hash ) or return;
470              
471             ### if there's a meta file, we read it;
472 3 50       568 if( -e $meta ) {
473              
474             ### Parse::CPAN::Meta uses exceptions for errors
475             ### hash returned in list context!!!
476              
477 3         46 local $ENV{PERL_JSON_BACKEND};
478              
479 3         21 my ($doc) = eval { Parse::CPAN::Meta->load_file( $meta ) };
  3         89  
480              
481 3 50       58729 unless( $doc ) {
482 0         0 error(loc( "Could not read %1: '%2'", $meta, $@ ));
483 0         0 return $defaults;
484             }
485              
486             ### read the keys now, make sure not to throw
487             ### away anything that was already added
488             #for my $key ( @$keys ) {
489             # $defaults = {
490             # %$defaults,
491             # %{ $doc->{$key} },
492             # } if $doc->{ $key };
493             #}
494 3   50     28 my $prereqs = $doc->{prereqs} || {};
495 3         17 for my $key ( @$keys ) {
496             $defaults = {
497             %$defaults,
498 3         19 %{ $prereqs->{$key}->{requires} },
499 9 100       91 } if $prereqs->{ $key }->{requires};
500             }
501             }
502              
503             ### and return a copy
504 3         8 return \%{ $defaults };
  3         27  
505             }
506              
507             sub _stash_metadata {
508 10     10   40 my $self = shift;
509 10         87 my $mod = $self->parent;
510              
511 10 100       1228 my @possibles = do { defined $mod->status->extract
  10         210  
512             ? ( META_JSON->( $mod->status->extract ),
513             META_YML->( $mod->status->extract ) )
514             : ()
515             };
516              
517 10         261 $self->mk_accessors( qw[_metadata] );
518 10         584 $self->status->_metadata( {} );
519              
520 10         2217 META: foreach my $mfile ( grep { -e } @possibles ) {
  18         406  
521 9 50       140 if ( $mfile =~ /\.json/ ) {
522 0         0 local $ENV{PERL_JSON_BACKEND};
523 0         0 my ($doc) = eval { Parse::CPAN::Meta->load_file( $mfile ) };
  0         0  
524 0 0       0 unless( $doc ) {
525 0         0 error(loc( "Could not read %1: '%2'", $mfile, $@ ));
526 0         0 return;
527             }
528 0         0 $self->status->_metadata( $doc );
529 0         0 return $doc;
530             }
531             else {
532 9         127 local $ENV{PERL_YAML_BACKEND};
533 9         52 my ($doc) = eval { Parse::CPAN::Meta->load_file( $mfile ) };
  9         262  
534 9 50       32097 unless( $doc ) {
535 0         0 error(loc( "Could not read %1: '%2'", $mfile, $@ ));
536 0         0 return;
537             }
538 9         94 $self->status->_metadata( $doc );
539 9         1886 return $doc;
540             }
541             }
542 1         5 return;
543             }
544              
545              
546             =head2 $bool = $dist->_resolve_prereqs( ... )
547              
548             Makes sure prerequisites are resolved
549              
550             format The dist class to use to make the prereqs
551             (ie. CPANPLUS::Dist::MM)
552              
553             prereqs Hash of the prerequisite modules and their versions
554              
555             target What to do with the prereqs.
556             create => Just build them
557             install => Install them
558             ignore => Ignore them
559              
560             prereq_build If true, always build the prereqs even if already
561             resolved
562              
563             verbose Be verbose
564              
565             force Force the prereq to be built, even if already resolved
566              
567             =cut
568              
569             sub _resolve_prereqs {
570 31     31   2468 my $dist = shift;
571 31         250 my $self = $dist->parent;
572 31         3600 my $cb = $self->parent;
573 31         359 my $conf = $cb->configure_object;
574 31         640 my %hash = @_;
575              
576 31         229 my ($prereqs, $format, $verbose, $target, $force, $prereq_build,$tolerant);
577 31         425 my $tmpl = {
578             ### XXX perhaps this should not be required, since it may not be
579             ### packaged, just installed...
580             ### Let it be empty as well -- that means the $modobj->install
581             ### routine will figure it out, which is fine if we didn't have any
582             ### very specific wishes (it will even detect the favourite
583             ### dist_type).
584             format => { required => 1, store => \$format,
585             allow => ['',__PACKAGE__->dist_types], },
586             prereqs => { required => 1, default => { },
587             strict_type => 1, store => \$prereqs },
588             verbose => { default => $conf->get_conf('verbose'),
589             store => \$verbose },
590             force => { default => $conf->get_conf('force'),
591             store => \$force },
592             ### make sure allow matches with $mod->install's list
593             target => { default => '', store => \$target,
594             allow => ['',qw[create ignore install]] },
595             prereq_build => { default => 0, store => \$prereq_build },
596             tolerant => { default => $conf->get_conf('allow_unknown_prereqs'),
597             store => \$tolerant },
598             };
599              
600 31 50       280 check( $tmpl, \%hash ) or return;
601              
602             ### so there are no prereqs? then don't even bother
603 31 50       11506 return 1 unless keys %$prereqs;
604              
605             ### Make sure we wound up where we started.
606 31         163753 my $original_wd = Cwd::cwd;
607              
608             ### so you didn't provide an explicit target.
609             ### maybe your config can tell us what to do.
610             $target ||= {
611             PREREQ_ASK, TARGET_INSTALL, # we'll bail out if the user says no
612             PREREQ_BUILD, TARGET_CREATE,
613             PREREQ_IGNORE, TARGET_IGNORE,
614             PREREQ_INSTALL, TARGET_INSTALL,
615 31   50     2311 }->{ $conf->get_conf('prereqs') } || '';
      66        
616              
617             ### XXX BIG NASTY HACK XXX FIXME at some point.
618             ### when installing Bundle::CPANPLUS::Dependencies, we want to
619             ### install all packages matching 'cpanplus' to be installed last,
620             ### as all CPANPLUS' prereqs are being installed as well, but are
621             ### being loaded for bootstrapping purposes. This means CPANPLUS
622             ### can find them, but for example cpanplus::dist::build won't,
623             ### which gets messy FAST. So, here we sort our prereqs only IF
624             ### the parent module is Bundle::CPANPLUS::Dependencies.
625             ### Really, we would want some sort of sorted prereq mechanism,
626             ### but Bundle:: doesn't support it, and we flatten everything
627             ### to a hash internally. A sorted hash *might* do the trick if
628             ### we got a transparent implementation.. that would mean we would
629             ### just have to remove the 'sort' here, and all will be well
630 31         205 my @sorted_prereqs;
631              
632             ### use regex, could either be a module name, or a package name
633 31 50       935 if( $self->module =~ /^Bundle(::|-)CPANPLUS(::|-)Dependencies/ ) {
634 0         0 my (@first, @last);
635 0         0 for my $mod ( sort keys %$prereqs ) {
636 0 0       0 $mod =~ /CPANPLUS/
637             ? push @last, $mod
638             : push @first, $mod;
639             }
640 0         0 @sorted_prereqs = (@first, @last);
641             } else {
642 31         622 @sorted_prereqs = sort keys %$prereqs;
643             }
644              
645             ### first, transfer this key/value pairing into a
646             ### list of module objects + desired versions
647 31         320 my @install_me;
648              
649             my $flag;
650              
651 31         289 for my $mod ( @sorted_prereqs ) {
652 31         585 ( my $version = $prereqs->{$mod} ) =~ s#[^0-9\._]+##g;
653              
654             ### 'perl' is a special case, there's no mod object for it
655 31 100       248 if( $mod eq PERL_CORE ) {
656              
657 2 100       117 unless( $cb->_vcmp( sprintf('v%vd',$^V), $version ) >= 0 ) {
658 1         26 error(loc( "Module '%1' needs perl version '%2', but you ".
659             "only have version '%3' -- can not proceed",
660             $self->module, $version,
661             $cb->_perl_version( perl => $^X ) ) );
662 1         140 return;
663             }
664              
665 1         21 next;
666             }
667              
668 29         636 my $modobj = $cb->module_tree($mod);
669              
670             #### XXX we ignore the version, and just assume that the latest
671             #### version from cpan will meet your requirements... dodgy =/
672 29 100       232 unless( $modobj ) {
673             # Check if it is a core module
674 3         141 my $sub = CPANPLUS::Module->can(
675             'module_is_supplied_with_perl_core' );
676 3         108 my $core = $sub->( $mod );
677 3 50       52 unless ( defined $core ) {
678 0         0 error( loc( "No such module '%1' found on CPAN", $mod ) );
679 0 0       0 $flag++ unless $tolerant;
680 0         0 next;
681             }
682 3 50       134 if ( $cb->_vcmp( $version, $core ) > 0 ) {
683 0         0 error(loc( "Version of core module '%1' ('%2') is too low for ".
684             "'%3' (needs '%4') -- carrying on but this may be a problem",
685             $mod, $core,
686             $self->module, $version ));
687             }
688 3         23 next;
689             }
690              
691             ### it's not uptodate, we need to install it
692 26 100 33     591 if( !$dist->prereq_satisfied(modobj => $modobj, version => $version)) {
    50 33        
693 15         111 msg(loc("Module '%1' requires '%2' version '%3' to be installed ",
694             $self->module, $modobj->module, $version), $verbose );
695              
696 15         297 push @install_me, [$modobj, $version];
697              
698             ### it's not an MM or Build format, that means it's a package
699             ### manager... we'll need to install it as well, via the PM
700             } elsif ( INSTALL_VIA_PACKAGE_MANAGER->($format) and
701             !$modobj->package_is_perl_core and
702             ($target ne TARGET_IGNORE)
703             ) {
704 0         0 msg(loc("Module '%1' depends on '%2', may need to build a '%3' ".
705             "package for it as well", $self->module, $modobj->module,
706             $format));
707 0         0 push @install_me, [$modobj, $version];
708             }
709             }
710              
711              
712              
713             ### so you just want to ignore prereqs? ###
714 30 100       188 if( $target eq TARGET_IGNORE ) {
715              
716             ### but you have modules you need to install
717 2 50       28 if( @install_me ) {
718 2         38 msg(loc("Ignoring prereqs, this may mean your install will fail"),
719             $verbose);
720 2         58 msg(loc("'%1' listed the following dependencies:", $self->module),
721             $verbose);
722              
723 2         31 for my $aref (@install_me) {
724 2         33 my ($mod,$version) = @$aref;
725              
726 2         34 my $str = sprintf "\t%-35s %8s\n", $mod->module, $version;
727 2         60 msg($str,$verbose);
728             }
729              
730 2         187 return;
731              
732             ### ok, no problem, you have all needed prereqs anyway
733             } else {
734 0         0 return 1;
735             }
736             }
737              
738 28         152 for my $aref (@install_me) {
739 13         85 my($modobj,$version) = @$aref;
740              
741             ### another prereq may have already installed this one...
742             ### so don't ask again if the module turns out to be uptodate
743             ### see bug [#11840]
744             ### if either force or prereq_build are given, the prereq
745             ### should be built anyway
746 13 50 66     171 next if (!$force and !$prereq_build) &&
      66        
747             $dist->prereq_satisfied(modobj => $modobj, version => $version);
748              
749             ### either we're told to ignore the prereq,
750             ### or the user wants us to ask him
751 13 100 100     144 if( ( $conf->get_conf('prereqs') == PREREQ_ASK and not
752             $cb->_callbacks->install_prerequisite->($self, $modobj)
753             )
754             ) {
755 1         120 msg(loc("Will not install prerequisite '%1' -- Note " .
756             "that the overall install may fail due to this",
757             $modobj->module), $verbose);
758 1         25 next;
759             }
760              
761             ### value set and false -- means failure ###
762 12 100 66     250 if( defined $modobj->status->installed
763             && !$modobj->status->installed
764             ) {
765 1         84 error( loc( "Prerequisite '%1' failed to install before in " .
766             "this session", $modobj->module ) );
767 1         11 $flag++;
768 1         3 last;
769             }
770              
771             ### part of core?
772 11 100       1229 if( $modobj->package_is_perl_core ) {
773 1         19 error(loc("Prerequisite '%1' is perl-core (%2) -- not ".
774             "installing that. -- Note that the overall ".
775             "install may fail due to this.",
776             $modobj->module, $modobj->package ) );
777 1         24 next;
778             }
779              
780             ### circular dependency code ###
781 10   100     166 my $pending = $cb->_status->pending_prereqs || {};
782              
783             ### recursive dependency ###
784 10 100       1216 if ( $pending->{ $modobj->module } ) {
785 1         27 error( loc( "Recursive dependency detected (%1) -- skipping",
786             $modobj->module ) );
787 1         24 next;
788             }
789              
790             ### register this dependency as pending ###
791 9         45 $pending->{ $modobj->module } = $modobj;
792 9         57 $cb->_status->pending_prereqs( $pending );
793              
794             ### call $modobj->install rather than doing
795             ### CPANPLUS::Dist->new and the like ourselves,
796             ### since ->install will take care of fetch &&
797             ### extract as well
798 9   100     1029 my $pa = $dist->status->_prepare_args || {};
799 9   100     1962 my $ca = $dist->status->_create_args || {};
800 9   50     1882 my $ia = $dist->status->_install_args || {};
801              
802 9 100       2060 unless( $modobj->install( %$pa, %$ca, %$ia,
803             force => $force,
804             verbose => $verbose,
805             format => $format,
806             target => $target )
807             ) {
808 3         26 error(loc("Failed to install '%1' as prerequisite " .
809             "for '%2'", $modobj->module, $self->module ) );
810 3         50 $flag++;
811             }
812              
813             ### unregister the pending dependency ###
814 9         101 $pending->{ $modobj->module } = 0;
815 9         131 $cb->_status->pending_prereqs( $pending );
816              
817 9 100       875 last if $flag;
818              
819             ### don't want us to install? ###
820 6 100       125 if( $target ne TARGET_INSTALL ) {
821 3 50       46 my $dir = $modobj->status->extract
822             or error(loc("No extraction dir for '%1' found ".
823             "-- weird", $modobj->module));
824              
825 3         336 $modobj->add_to_includepath();
826              
827 3         74 next;
828             }
829             }
830              
831             ### reset the $prereqs iterator, in case we bailed out early ###
832 28         142 keys %$prereqs;
833              
834             ### chdir back to where we started
835 28         660 $cb->_chdir( dir => $original_wd );
836              
837 28 100       1927 return 1 unless $flag;
838 4         250 return;
839             }
840              
841             1;
842              
843             # Local variables:
844             # c-indentation-style: bsd
845             # c-basic-offset: 4
846             # indent-tabs-mode: nil
847             # End:
848             # vim: expandtab shiftwidth=4: