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