This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
AW: IO::Dir destructor
[perl5.git] / lib / CPANPLUS / Module.pm
CommitLineData
6aaee015
RGS
1package CPANPLUS::Module;
2
3use strict;
4use vars qw[@ISA];
5
6
7use CPANPLUS::Dist;
8use CPANPLUS::Error;
9use CPANPLUS::Module::Signature;
10use CPANPLUS::Module::Checksums;
11use CPANPLUS::Internals::Constants;
12
13use FileHandle;
14
15use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
16use IPC::Cmd qw[can_run run];
17use File::Find qw[find];
18use Params::Check qw[check];
19use Module::Load::Conditional qw[can_load check_install];
20
21$Params::Check::VERBOSE = 1;
22
23@ISA = qw[ CPANPLUS::Module::Signature CPANPLUS::Module::Checksums];
24
25=pod
26
27=head1 NAME
28
29CPANPLUS::Module
30
31=head1 SYNOPSIS
32
33 ### get a module object from the CPANPLUS::Backend object
34 my $mod = $cb->module_tree('Some::Module');
35
36 ### accessors
37 $mod->version;
38 $mod->package;
39
40 ### methods
41 $mod->fetch;
42 $mod->extract;
43 $mod->install;
44
45
46=head1 DESCRIPTION
47
48C<CPANPLUS::Module> creates objects from the information in the
49source files. These can then be used to query and perform actions
50on, like fetching or installing.
51
52These objects should only be created internally. For C<fake> objects,
53there's the C<CPANPLUS::Module::Fake> class. To obtain a module object
54consult the C<CPANPLUS::Backend> documentation.
55
56=cut
57
58my $tmpl = {
59 module => { default => '', required => 1 }, # full module name
60 version => { default => '0.0' }, # version number
61 path => { default => '', required => 1 }, # extended path on the
62 # cpan mirror, like
63 # /author/id/K/KA/KANE
64 comment => { default => ''}, # comment on module
65 package => { default => '', required => 1 }, # package name, like
66 # 'bar-baz-1.03.tgz'
67 description => { default => '' }, # description of the
68 # module
5879cbe1 69 dslip => { default => EMPTY_DSLIP }, # dslip information
6aaee015
RGS
70 _id => { required => 1 }, # id of the Internals
71 # parent object
72 _status => { no_override => 1 }, # stores status object
73 author => { default => '', required => 1,
74 allow => IS_AUTHOBJ }, # module author
75 mtime => { default => '' },
76};
77
5879cbe1
RGS
78### some of these will be resolved by wrapper functions that
79### do Clever Things to find the actual value, so don't create
80### an autogenerated sub for that just here, take an alternate
81### name to allow for a wrapper
82{ my %rename = (
83 dslip => '_dslip'
84 );
85
86 ### autogenerate accessors ###
87 for my $key ( keys %$tmpl ) {
88 no strict 'refs';
89
90 my $sub = $rename{$key} || $key;
91
92 *{__PACKAGE__."::$sub"} = sub {
93 $_[0]->{$key} = $_[1] if @_ > 1;
94 return $_[0]->{$key};
95 }
6aaee015
RGS
96 }
97}
98
5879cbe1 99
6aaee015
RGS
100=pod
101
102=head1 CLASS METHODS
103
104=head2 accessors ()
105
106Returns a list of all accessor methods to the object
107
108=cut
109
110### *name is an alias, include it explicitly
111sub accessors { return ('name', keys %$tmpl) };
112
113=head1 ACCESSORS
114
115An objects of this class has the following accessors:
116
117=over 4
118
119=item name
120
121Name of the module.
122
123=item module
124
125Name of the module.
126
127=item version
128
129Version of the module. Defaults to '0.0' if none was provided.
130
131=item path
132
133Extended path on the mirror.
134
135=item comment
136
137Any comment about the module -- largely unused.
138
139=item package
140
141The name of the package.
142
143=item description
144
145Description of the module -- only registered modules have this.
146
147=item dslip
148
149The five character dslip string, that represents meta-data of the
150module -- again, only registered modules have this.
151
5879cbe1
RGS
152=cut
153
154sub dslip {
155 my $self = shift;
156
157 ### if this module has relevant dslip info, return it
158 return $self->_dslip if $self->_dslip ne EMPTY_DSLIP;
159
160 ### if not, look at other modules in the same package,
161 ### see if *they* have any dslip info
162 for my $mod ( $self->contains ) {
163 return $mod->_dslip if $mod->_dslip ne EMPTY_DSLIP;
164 }
165
166 ### ok, really no dslip info found, return the default
167 return EMPTY_DSLIP;
168}
169
170
171=pod
172
6aaee015
RGS
173=item status
174
175The C<CPANPLUS::Module::Status> object associated with this object.
176(see below).
177
178=item author
179
180The C<CPANPLUS::Module::Author> object associated with this object.
181
182=item parent
183
184The C<CPANPLUS::Internals> object that spawned this module object.
185
186=back
187
188=cut
189
190### Alias ->name to ->module, for human beings.
191*name = *module;
192
193sub parent {
194 my $self = shift;
195 my $obj = CPANPLUS::Internals->_retrieve_id( $self->_id );
196
197 return $obj;
198}
199
200=head1 STATUS ACCESSORS
201
202C<CPANPLUS> caches a lot of results from method calls and saves data
203it collected along the road for later reuse.
204
205C<CPANPLUS> uses this internally, but it is also available for the end
206user. You can get a status object by calling:
207
208 $modobj->status
209
210You can then query the object as follows:
211
212=over 4
213
214=item installer_type
215
216The installer type used for this distribution. Will be one of
217'makemaker' or 'build'. This determines whether C<CPANPLUS::Dist::MM>
218or C<CPANPLUS::Dist::Build> will be used to build this distribution.
219
220=item dist_cpan
221
222The dist object used to do the CPAN-side of the installation. Either
223a C<CPANPLUS::Dist::MM> or C<CPANPLUS::Dist::Build> object.
224
225=item dist
226
227The custom dist object used to do the operating specific side of the
228installation, if you've chosen to use this. For example, if you've
229chosen to install using the C<ports> format, this may be a
230C<CPANPLUS::Dist::Ports> object.
231
232Undefined if you didn't specify a separate format to install through.
233
234=item prereqs
235
236A hashref of prereqs this distribution was found to have. Will look
237something like this:
238
239 { Carp => 0.01, strict => 0 }
240
241Might be undefined if the distribution didn't have any prerequisites.
242
243=item signature
244
245Flag indicating, if a signature check was done, whether it was OK or
246not.
247
248=item extract
249
250The directory this distribution was extracted to.
251
252=item fetch
253
254The location this distribution was fetched to.
255
256=item readme
257
258The text of this distributions README file.
259
260=item uninstall
261
262Flag indicating if an uninstall call was done successfully.
263
264=item created
265
266Flag indicating if the C<create> call to your dist object was done
267successfully.
268
269=item installed
270
271Flag indicating if the C<install> call to your dist object was done
272successfully.
273
274=item checksums
275
276The location of this distributions CHECKSUMS file.
277
278=item checksum_ok
279
280Flag indicating if the checksums check was done successfully.
281
282=item checksum_value
283
284The checksum value this distribution is expected to have
285
286=back
287
288=head1 METHODS
289
290=head2 $self = CPANPLUS::Module::new( OPTIONS )
291
292This method returns a C<CPANPLUS::Module> object. Normal users
293should never call this method directly, but instead use the
294C<CPANPLUS::Backend> to obtain module objects.
295
296This example illustrates a C<new()> call with all required arguments:
297
298 CPANPLUS::Module->new(
299 module => 'Foo',
300 path => 'authors/id/A/AA/AAA',
301 package => 'Foo-1.0.tgz',
302 author => $author_object,
303 _id => INTERNALS_OBJECT_ID,
304 );
305
306Every accessor is also a valid option to pass to C<new>.
307
308Returns a module object on success and false on failure.
309
310=cut
311
312
313sub new {
314 my($class, %hash) = @_;
315
316 ### don't check the template for sanity
317 ### -- we know it's good and saves a lot of performance
318 local $Params::Check::SANITY_CHECK_TEMPLATE = 0;
319
320 my $object = check( $tmpl, \%hash ) or return;
321
322 bless $object, $class;
323
324 return $object;
325}
326
327### only create status objects when they're actually asked for
328sub status {
329 my $self = shift;
330 return $self->_status if $self->_status;
331
332 my $acc = Object::Accessor->new;
333 $acc->mk_accessors( qw[ installer_type dist_cpan dist prereqs
334 signature extract fetch readme uninstall
335 created installed prepared checksums files
336 checksum_ok checksum_value _fetch_from] );
337
338 $self->_status( $acc );
339
340 return $self->_status;
341}
342
343
344### flush the cache of this object ###
345sub _flush {
346 my $self = shift;
347 $self->status->mk_flush;
348 return 1;
349}
350
351=head2 $mod->package_name
352
353Returns the name of the package a module is in. For C<Acme::Bleach>
354that might be C<Acme-Bleach>.
355
356=head2 $mod->package_version
357
358Returns the version of the package a module is in. For a module
359in the package C<Acme-Bleach-1.1.tar.gz> this would be C<1.1>.
360
361=head2 $mod->package_extension
362
363Returns the suffix added by the compression method of a package a
364certain module is in. For a module in C<Acme-Bleach-1.1.tar.gz>, this
365would be C<tar.gz>.
366
367=head2 $mod->package_is_perl_core
368
369Returns a boolean indicating of the package a particular module is in,
370is actually a core perl distribution.
371
372=head2 $mod->module_is_supplied_with_perl_core( [version => $]] )
373
374Returns a boolean indicating whether C<ANY VERSION> of this module
375was supplied with the current running perl's core package.
376
377=head2 $mod->is_bundle
378
379Returns a boolean indicating if the module you are looking at, is
380actually a bundle. Bundles are identified as modules whose name starts
381with C<Bundle::>.
382
383=head2 $mod->is_third_party
384
385Returns a boolean indicating whether the package is a known third-party
386module (i.e. it's not provided by the standard Perl distribution and
387is not available on the CPAN, but on a third party software provider).
388See L<Module::ThirdParty> for more details.
389
390=head2 $mod->third_party_information
391
392Returns a reference to a hash with more information about a third-party
393module. See the documentation about C<module_information()> in
394L<Module::ThirdParty> for more details.
395
396=cut
397
398{ ### fetches the test reports for a certain module ###
399 my %map = (
400 name => 0,
401 version => 1,
402 extension => 2,
403 );
404
405 while ( my($type, $index) = each %map ) {
406 my $name = 'package_' . $type;
407
408 no strict 'refs';
409 *$name = sub {
410 my $self = shift;
411 my @res = $self->parent->_split_package_string(
412 package => $self->package
413 );
414
415 ### return the corresponding index from the result
416 return $res[$index] if @res;
417 return;
418 };
419 }
420
421 sub package_is_perl_core {
422 my $self = shift;
423
424 ### check if the package looks like a perl core package
425 return 1 if $self->package_name eq PERL_CORE;
426
427 my $core = $self->module_is_supplied_with_perl_core;
428 ### ok, so it's found in the core, BUT it could be dual-lifed
429 if ($core) {
430 ### if the package is newer than installed, then it's dual-lifed
431 return if $self->version > $self->installed_version;
432
433 ### if the package is newer or equal to the corelist,
434 ### then it's dual-lifed
435 return if $self->version >= $core;
436
437 ### otherwise, it's older than corelist, thus unsuitable.
438 return 1;
439 }
440
441 ### not in corelist, not a perl core package.
442 return;
443 }
444
445 sub module_is_supplied_with_perl_core {
446 my $self = shift;
447 my $ver = shift || $];
448
449 ### check Module::CoreList to see if it's a core package
450 require Module::CoreList;
451 my $core = $Module::CoreList::version{ $ver }->{ $self->module };
452
453 return $core;
454 }
455
456 ### make sure Bundle-Foo also gets flagged as bundle
457 sub is_bundle {
458 return shift->module =~ /^bundle(?:-|::)/i ? 1 : 0;
459 }
460
461 sub is_third_party {
462 my $self = shift;
463
464 return unless can_load( modules => { 'Module::ThirdParty' => 0 } );
465
466 return Module::ThirdParty::is_3rd_party( $self->name );
467 }
468
469 sub third_party_information {
470 my $self = shift;
471
472 return unless $self->is_third_party;
473
474 return Module::ThirdParty::module_information( $self->name );
475 }
476}
477
478=pod
479
480=head2 $clone = $self->clone
481
482Clones the current module object for tinkering with.
483It will have a clean C<CPANPLUS::Module::Status> object, as well as
484a fake C<CPANPLUS::Module::Author> object.
485
486=cut
487
488sub clone {
489 my $self = shift;
490
491 ### clone the object ###
492 my %data;
493 for my $acc ( grep !/status/, __PACKAGE__->accessors() ) {
494 $data{$acc} = $self->$acc();
495 }
496
497 my $obj = CPANPLUS::Module::Fake->new( %data );
498
499 return $obj;
500}
501
502=pod
503
504=head2 $where = $self->fetch
505
506Fetches the module from a CPAN mirror.
507Look at L<CPANPLUS::Internals::Fetch::_fetch()> for details on the
508options you can pass.
509
510=cut
511
512sub fetch {
513 my $self = shift;
514 my $cb = $self->parent;
515
516 ### custom args
517 my %args = ( module => $self );
518
519 ### if a custom fetch location got specified before, add that here
520 $args{fetch_from} = $self->status->_fetch_from
521 if $self->status->_fetch_from;
522
523 my $where = $cb->_fetch( @_, %args ) or return;
524
525 ### do an md5 check ###
526 if( !$self->status->_fetch_from and
527 $cb->configure_object->get_conf('md5') and
528 $self->package ne CHECKSUMS
529 ) {
530 unless( $self->_validate_checksum ) {
531 error( loc( "Checksum error for '%1' -- will not trust package",
532 $self->package) );
533 return;
534 }
535 }
536
537 return $where;
538}
539
540=pod
541
542=head2 $path = $self->extract
543
544Extracts the fetched module.
545Look at L<CPANPLUS::Internals::Extract::_extract()> for details on
546the options you can pass.
547
548=cut
549
550sub extract {
551 my $self = shift;
552 my $cb = $self->parent;
553
554 unless( $self->status->fetch ) {
555 error( loc( "You have not fetched '%1' yet -- cannot extract",
556 $self->module) );
557 return;
558 }
559
560 return $cb->_extract( @_, module => $self );
561}
562
563=head2 $type = $self->get_installer_type([prefer_makefile => BOOL])
564
565Gets the installer type for this module. This may either be C<build> or
566C<makemaker>. If C<Module::Build> is unavailable or no installer type
567is available, it will fall back to C<makemaker>. If both are available,
568it will pick the one indicated by your config, or by the
569C<prefer_makefile> option you can pass to this function.
570
571Returns the installer type on success, and false on error.
572
573=cut
574
575sub get_installer_type {
576 my $self = shift;
577 my $cb = $self->parent;
578 my $conf = $cb->configure_object;
579 my %hash = @_;
580
581 my $prefer_makefile;
582 my $tmpl = {
583 prefer_makefile => { default => $conf->get_conf('prefer_makefile'),
584 store => \$prefer_makefile, allow => BOOLEANS },
585 };
586
587 check( $tmpl, \%hash ) or return;
588
589 my $extract = $self->status->extract();
590 unless( $extract ) {
591 error(loc("Cannot determine installer type of unextracted module '%1'",
592 $self->module));
593 return;
594 }
595
596
597 ### check if it's a makemaker or a module::build type dist ###
598 my $found_build = -e BUILD_PL->( $extract );
599 my $found_makefile = -e MAKEFILE_PL->( $extract );
600
601 my $type;
602 $type = INSTALLER_BUILD if !$prefer_makefile && $found_build;
603 $type = INSTALLER_BUILD if $found_build && !$found_makefile;
604 $type = INSTALLER_MM if $prefer_makefile && $found_makefile;
605 $type = INSTALLER_MM if $found_makefile && !$found_build;
606
607 ### ok, so it's a 'build' installer, but you don't /have/ module build
608 if( $type eq INSTALLER_BUILD and (
609 not grep { $_ eq INSTALLER_BUILD } CPANPLUS::Dist->dist_types )
610 ) {
611 error( loc( "This module requires '%1' and '%2' to be installed, ".
612 "but you don't have it! Will fall back to ".
613 "'%3', but might not be able to install!",
614 'Module::Build', INSTALLER_BUILD, INSTALLER_MM ) );
615 $type = INSTALLER_MM;
616
617 ### ok, actually we found neither ###
618 } elsif ( !$type ) {
619 error( loc( "Unable to find '%1' or '%2' for '%3'; ".
620 "Will default to '%4' but might be unable ".
621 "to install!", BUILD_PL->(), MAKEFILE_PL->(),
622 $self->module, INSTALLER_MM ) );
623 $type = INSTALLER_MM;
624 }
625
626 return $self->status->installer_type( $type ) if $type;
627 return;
628}
629
630=pod
631
632=head2 $dist = $self->dist([target => 'prepare|create', format => DISTRIBUTION_TYPE, args => {key => val}]);
633
634Create a distribution object, ready to be installed.
635Distribution type defaults to your config settings
636
637The optional C<args> hashref is passed on to the specific distribution
638types' C<create> method after being dereferenced.
639
640Returns a distribution object on success, false on failure.
641
642See C<CPANPLUS::Dist> for details.
643
644=cut
645
646sub dist {
647 my $self = shift;
648 my $cb = $self->parent;
649 my $conf = $cb->configure_object;
650 my %hash = @_;
651
652 ### have you determined your installer type yet? if not, do it here,
653 ### we need the info
654 $self->get_installer_type unless $self->status->installer_type;
655
656
657 my($type,$args,$target);
658 my $tmpl = {
659 format => { default => $conf->get_conf('dist_type') ||
660 $self->status->installer_type,
661 store => \$type },
662 target => { default => TARGET_CREATE, store => \$target },
663 args => { default => {}, store => \$args },
664 };
665
666 check( $tmpl, \%hash ) or return;
667
668 my $dist = CPANPLUS::Dist->new(
669 format => $type,
670 module => $self
671 ) or return;
672
673 my $dist_cpan = $type eq $self->status->installer_type
674 ? $dist
675 : CPANPLUS::Dist->new(
676 format => $self->status->installer_type,
677 module => $self,
678 );
679
680 ### store the dists
681 $self->status->dist_cpan( $dist_cpan );
682 $self->status->dist( $dist );
683
684 DIST: {
685 ### first prepare the dist
686 $dist->prepare( %$args ) or return;
687 $self->status->prepared(1);
688
689 ### you just wanted us to prepare?
690 last DIST if $target eq TARGET_PREPARE;
691
692 $dist->create( %$args ) or return;
693 $self->status->created(1);
694 }
695
696 return $dist;
697}
698
699=pod
700
701=head2 $bool = $mod->prepare( )
702
703Convenience method around C<install()> that prepares a module
704without actually building it. This is equivalent to invoking C<install>
705with C<target> set to C<prepare>
706
707Returns true on success, false on failure.
708
709=cut
710
711sub prepare {
712 my $self = shift;
713 return $self->install( @_, target => TARGET_PREPARE );
714}
715
716=head2 $bool = $mod->create( )
717
718Convenience method around C<install()> that creates a module.
719This is equivalent to invoking C<install> with C<target> set to
720C<create>
721
722Returns true on success, false on failure.
723
724=cut
725
726sub create {
727 my $self = shift;
728 return $self->install( @_, target => TARGET_CREATE );
729}
730
731=head2 $bool = $mod->test( )
732
733Convenience wrapper around C<install()> that tests a module, without
734installing it.
735It's the equivalent to invoking C<install()> with C<target> set to
736C<create> and C<skiptest> set to C<0>.
737
738Returns true on success, false on failure.
739
740=cut
741
742sub test {
743 my $self = shift;
744 return $self->install( @_, target => TARGET_CREATE, skiptest => 0 );
745}
746
747=pod
748
749=head2 $bool = $self->install([ target => 'prepare|create|install', format => FORMAT_TYPE, extractdir => DIRECTORY, fetchdir => DIRECTORY, prefer_bin => BOOL, force => BOOL, verbose => BOOL, ..... ]);
750
751Installs the current module. This includes fetching it and extracting
752it, if this hasn't been done yet, as well as creating a distribution
753object for it.
754
755This means you can pass it more arguments than described above, which
756will be passed on to the relevant methods as they are called.
757
758See C<CPANPLUS::Internals::Fetch>, C<CPANPLUS::Internals::Extract> and
759C<CPANPLUS::Dist> for details.
760
761Returns true on success, false on failure.
762
763=cut
764
765sub install {
766 my $self = shift;
767 my $cb = $self->parent;
768 my $conf = $cb->configure_object;
769 my %hash = @_;
770
771 my $args; my $target; my $format;
772 { ### so we can use the rest of the args to the create calls etc ###
773 local $Params::Check::NO_DUPLICATES = 1;
774 local $Params::Check::ALLOW_UNKNOWN = 1;
775
776 ### targets 'dist' and 'test' are now completely ignored ###
777 my $tmpl = {
778 ### match this allow list with Dist->_resolve_prereqs
779 target => { default => TARGET_INSTALL, store => \$target,
780 allow => [TARGET_PREPARE, TARGET_CREATE,
781 TARGET_INSTALL] },
782 force => { default => $conf->get_conf('force'), },
783 verbose => { default => $conf->get_conf('verbose'), },
784 format => { default => $conf->get_conf('dist_type'),
785 store => \$format },
786 };
787
788 $args = check( $tmpl, \%hash ) or return;
789 }
790
791
792 ### if this target isn't 'install', we will need to at least 'create'
793 ### every prereq, so it can build
794 ### XXX prereq_target of 'prepare' will do weird things here, and is
795 ### not supported.
796 $args->{'prereq_target'} ||= TARGET_CREATE if $target ne TARGET_INSTALL;
797
798 ### check if it's already upto date ###
799 if( $target eq TARGET_INSTALL and !$args->{'force'} and
800 !$self->package_is_perl_core() and # separate rules apply
801 ( $self->status->installed() or $self->is_uptodate ) and
802 !INSTALL_VIA_PACKAGE_MANAGER->($format)
803 ) {
804 msg(loc("Module '%1' already up to date, won't install without force",
805 $self->module), $args->{'verbose'} );
806 return $self->status->installed(1);
807 }
808
809 # if it's a non-installable core package, abort the install.
810 if( $self->package_is_perl_core() ) {
811 # if the installed is newer, say so.
812 if( $self->installed_version > $self->version ) {
813 error(loc("The core Perl %1 module '%2' (%3) is more ".
814 "recent than the latest release on CPAN (%4). ".
815 "Aborting install.",
816 $], $self->module, $self->installed_version,
817 $self->version ) );
818 # if the installed matches, say so.
819 } elsif( $self->installed_version == $self->version ) {
820 error(loc("The core Perl %1 module '%2' (%3) can only ".
821 "be installed by Perl itself. ".
822 "Aborting install.",
823 $], $self->module, $self->installed_version ) );
824 # otherwise, the installed is older; say so.
825 } else {
826 error(loc("The core Perl %1 module '%2' can only be ".
827 "upgraded from %3 to %4 by Perl itself (%5). ".
828 "Aborting install.",
829 $], $self->module, $self->installed_version,
830 $self->version, $self->package ) );
831 }
832 return;
833
834 ### it might be a known 3rd party module
835 } elsif ( $self->is_third_party ) {
836 my $info = $self->third_party_information;
837 error(loc(
838 "%1 is a known third-party module.\n\n".
839 "As it isn't available on the CPAN, CPANPLUS can't install " .
840 "it automatically. Therefore you need to install it manually " .
841 "before proceeding.\n\n".
842 "%2 is part of %3, published by %4, and should be available ".
843 "for download at the following address:\n\t%5",
844 $self->name, $self->name, $info->{name}, $info->{author},
845 $info->{url}
846 ));
847
848 return;
849 }
850
851 ### fetch it if need be ###
852 unless( $self->status->fetch ) {
853 my $params;
854 for (qw[prefer_bin fetchdir]) {
855 $params->{$_} = $args->{$_} if exists $args->{$_};
856 }
857 for (qw[force verbose]) {
858 $params->{$_} = $args->{$_} if defined $args->{$_};
859 }
860 $self->fetch( %$params ) or return;
861 }
862
863 ### extract it if need be ###
864 unless( $self->status->extract ) {
865 my $params;
866 for (qw[prefer_bin extractdir]) {
867 $params->{$_} = $args->{$_} if exists $args->{$_};
868 }
869 for (qw[force verbose]) {
870 $params->{$_} = $args->{$_} if defined $args->{$_};
871 }
872 $self->extract( %$params ) or return;
873 }
874
875 $format ||= $self->status->installer_type;
876
877 unless( $format ) {
878 error( loc( "Don't know what installer to use; " .
879 "Couldn't find either '%1' or '%2' in the extraction " .
880 "directory '%3' -- will be unable to install",
881 BUILD_PL->(), MAKEFILE_PL->(), $self->status->extract ) );
882
883 $self->status->installed(0);
884 return;
885 }
886
887
888 ### do SIGNATURE checks? ###
889 if( $conf->get_conf('signature') ) {
890 unless( $self->check_signature( verbose => $args->{verbose} ) ) {
891 error( loc( "Signature check failed for module '%1' ".
892 "-- Not trusting this module, aborting install",
893 $self->module ) );
894 $self->status->signature(0);
895
896 ### send out test report on broken sig
897 if( $conf->get_conf('cpantest') ) {
898 $cb->_send_report(
899 module => $self,
900 failed => 1,
901 buffer => CPANPLUS::Error->stack_as_string,
902 verbose => $args->{verbose},
903 force => $args->{force},
904 ) or error(loc("Failed to send test report for '%1'",
905 $self->module ) );
906 }
907
908 return;
909
910 } else {
911 ### signature OK ###
912 $self->status->signature(1);
913 }
914 }
915
916 ### a target of 'create' basically means not to run make test ###
917 ### eh, no it /doesn't/.. skiptest => 1 means skiptest => 1.
918 #$args->{'skiptest'} = 1 if $target eq 'create';
919
920 ### bundle rules apply ###
921 if( $self->is_bundle ) {
922 ### check what we need to install ###
923 my @prereqs = $self->bundle_modules();
924 unless( @prereqs ) {
925 error( loc( "Bundle '%1' does not specify any modules to install",
926 $self->module ) );
927
928 ### XXX mark an error here? ###
929 }
930 }
931
932 my $dist = $self->dist( format => $format,
933 target => $target,
934 args => $args );
935 unless( $dist ) {
936 error( loc( "Unable to create a new distribution object for '%1' " .
937 "-- cannot continue", $self->module ) );
938 return;
939 }
940
941 return 1 if $target ne TARGET_INSTALL;
942
943 my $ok = $dist->install( %$args ) ? 1 : 0;
944
945 $self->status->installed($ok);
946
947 return 1 if $ok;
948 return;
949}
950
951=pod @list = $self->bundle_modules()
952
953Returns a list of module objects the Bundle specifies.
954
955This requires you to have extracted the bundle already, using the
956C<extract()> method.
957
958Returns false on error.
959
960=cut
961
962sub bundle_modules {
963 my $self = shift;
964 my $cb = $self->parent;
965
966 unless( $self->is_bundle ) {
967 error( loc("'%1' is not a bundle", $self->module ) );
968 return;
969 }
970
971 my $dir;
972 unless( $dir = $self->status->extract ) {
973 error( loc("Don't know where '%1' was extracted to", $self->module ) );
974 return;
975 }
976
977 my @files;
978 find( {
979 wanted => sub { push @files, File::Spec->rel2abs($_) if /\.pm/i; },
980 no_chdir => 1,
981 }, $dir );
982
983 my $prereqs = {}; my @list; my $seen = {};
984 for my $file ( @files ) {
985 my $fh = FileHandle->new($file)
986 or( error(loc("Could not open '%1' for reading: %2",
987 $file,$!)), next );
988
989 my $flag;
990 while(<$fh>) {
991 ### quick hack to read past the header of the file ###
992 last if $flag && m|^=head|i;
993
994 ### from perldoc cpan:
995 ### =head1 CONTENTS
996 ### In this pod section each line obeys the format
997 ### Module_Name [Version_String] [- optional text]
998 $flag = 1 if m|^=head1 CONTENTS|i;
999
1000 if ($flag && /^(?!=)(\S+)\s*(\S+)?/) {
1001 my $module = $1;
1002 my $version = $2 || '0';
1003
1004 my $obj = $cb->module_tree($module);
1005
1006 unless( $obj ) {
1007 error(loc("Cannot find bundled module '%1'", $module),
1008 loc("-- it does not seem to exist") );
1009 next;
1010 }
1011
1012 ### make sure we list no duplicates ###
1013 unless( $seen->{ $obj->module }++ ) {
1014 push @list, $obj;
1015 $prereqs->{ $module } =
1016 $cb->_version_to_number( version => $version );
1017 }
1018 }
1019 }
1020 }
1021
1022 ### store the prereqs we just found ###
1023 $self->status->prereqs( $prereqs );
1024
1025 return @list;
1026}
1027
1028=pod
1029
1030=head2 $text = $self->readme
1031
1032Fetches the readme belonging to this module and stores it under
1033C<< $obj->status->readme >>. Returns the readme as a string on
1034success and returns false on failure.
1035
1036=cut
1037
1038sub readme {
1039 my $self = shift;
1040 my $conf = $self->parent->configure_object;
1041
1042 ### did we already dl the readme once? ###
1043 return $self->status->readme() if $self->status->readme();
1044
1045 ### this should be core ###
1046 return unless can_load( modules => { FileHandle => '0.0' },
1047 verbose => 1,
1048 );
1049
1050 ### get a clone of the current object, with a fresh status ###
1051 my $obj = $self->clone or return;
1052
1053 ### munge the package name
1054 my $pkg = README->( $obj );
1055 $obj->package($pkg);
1056
1057 my $file;
1058 { ### disable checksum fetches on readme downloads
1059
1060 my $tmp = $conf->get_conf( 'md5' );
1061 $conf->set_conf( md5 => 0 );
1062
1063 $file = $obj->fetch;
1064
1065 $conf->set_conf( md5 => $tmp );
1066
1067 return unless $file;
1068 }
1069
1070 ### read the file into a scalar, to store in the original object ###
1071 my $fh = new FileHandle;
1072 unless( $fh->open($file) ) {
1073 error( loc( "Could not open file '%1': %2", $file, $! ) );
1074 return;
1075 }
1076
1077 my $in;
1078 { local $/; $in = <$fh> };
1079 $fh->close;
1080
1081 return $self->status->readme( $in );
1082}
1083
1084=pod
1085
1086=head2 $version = $self->installed_version()
1087
1088Returns the currently installed version of this module, if any.
1089
1090=head2 $where = $self->installed_file()
1091
1092Returns the location of the currently installed file of this module,
1093if any.
1094
1095=head2 $bool = $self->is_uptodate([version => VERSION_NUMBER])
1096
1097Returns a boolean indicating if this module is uptodate or not.
1098
1099=cut
1100
1101### uptodate/installed functions
1102{ my $map = { # hashkey, alternate rv
1103 installed_version => ['version', 0 ],
1104 installed_file => ['file', ''],
1105 is_uptodate => ['uptodate', 0 ],
1106 };
1107
1108 while( my($method, $aref) = each %$map ) {
1109 my($key,$alt_rv) = @$aref;
1110
1111 no strict 'refs';
1112 *$method = sub {
1113 ### never use the @INC hooks to find installed versions of
1114 ### modules -- they're just there in case they're not on the
1115 ### perl install, but the user shouldn't trust them for *other*
1116 ### modules!
1117 ### XXX CPANPLUS::inc is now obsolete, so this should not
1118 ### be needed anymore
1119 #local @INC = CPANPLUS::inc->original_inc;
1120
1121 my $self = shift;
1122
1123 ### make sure check_install is not looking in %INC, as
1124 ### that may contain some of our sneakily loaded modules
1125 ### that aren't installed as such. -- kane
1126 local $Module::Load::Conditional::CHECK_INC_HASH = 0;
1127 my $href = check_install(
1128 module => $self->module,
1129 version => $self->version,
1130 @_,
1131 );
1132
1133 return $href->{$key} || $alt_rv;
1134 }
1135 }
1136}
1137
1138
1139
1140=pod
1141
1142=head2 $href = $self->details()
1143
1144Returns a hashref with key/value pairs offering more information about
1145a particular module. For example, for C<Time::HiRes> it might look like
1146this:
1147
1148 Author Jarkko Hietaniemi (jhi@iki.fi)
1149 Description High resolution time, sleep, and alarm
1150 Development Stage Released
1151 Installed File /usr/local/perl/lib/Time/Hires.pm
1152 Interface Style plain Functions, no references used
1153 Language Used C and perl, a C compiler will be needed
1154 Package Time-HiRes-1.65.tar.gz
1155 Public License Unknown
1156 Support Level Developer
1157 Version Installed 1.52
1158 Version on CPAN 1.65
1159
1160=cut
1161
1162sub details {
1163 my $self = shift;
1164 my $conf = $self->parent->configure_object();
1165 my $cb = $self->parent;
1166 my %hash = @_;
1167
1168 my $res = {
1169 Author => loc("%1 (%2)", $self->author->author(),
1170 $self->author->email() ),
1171 Package => $self->package,
1172 Description => $self->description || loc('None given'),
1173 'Version on CPAN' => $self->version,
1174 };
1175
1176 ### check if we have the module installed
1177 ### if so, add version have and version on cpan
1178 $res->{'Version Installed'} = $self->installed_version
1179 if $self->installed_version;
1180 $res->{'Installed File'} = $self->installed_file if $self->installed_file;
1181
1182 my $i = 0;
1183 for my $item( split '', $self->dslip ) {
1184 $res->{ $cb->_dslip_defs->[$i]->[0] } =
1185 $cb->_dslip_defs->[$i]->[1]->{$item} || loc('Unknown');
1186 $i++;
1187 }
1188
1189 return $res;
1190}
1191
1192=head2 @list = $self->contains()
1193
1194Returns a list of module objects that represent the modules also
1195present in the package of this module.
1196
1197For example, for C<Archive::Tar> this might return:
1198
1199 Archive::Tar
1200 Archive::Tar::Constant
1201 Archive::Tar::File
1202
1203=cut
1204
1205sub contains {
1206 my $self = shift;
1207 my $cb = $self->parent;
1208 my $pkg = $self->package;
5879cbe1 1209
6aaee015
RGS
1210 my @mods = $cb->search( type => 'package', allow => [qr/^$pkg$/] );
1211
1212 return @mods;
1213}
1214
1215=pod
1216
1217=head2 @list_of_hrefs = $self->fetch_report()
1218
1219This function queries the CPAN testers database at
1220I<http://testers.cpan.org/> for test results of specified module
1221objects, module names or distributions.
1222
1223Look at L<CPANPLUS::Internals::Report::_query_report()> for details on
1224the options you can pass and the return value to expect.
1225
1226=cut
1227
1228sub fetch_report {
1229 my $self = shift;
1230 my $cb = $self->parent;
1231
1232 return $cb->_query_report( @_, module => $self );
1233}
1234
1235=pod
1236
1237=head2 $bool = $self->uninstall([type => [all|man|prog])
1238
1239This function uninstalls the specified module object.
1240
1241You can install 2 types of files, either C<man> pages or C<prog>ram
1242files. Alternately you can specify C<all> to uninstall both (which
1243is the default).
1244
1245Returns true on success and false on failure.
1246
1247Do note that this does an uninstall via the so-called C<.packlist>,
1248so if you used a module installer like say, C<ports> or C<apt>, you
1249should not use this, but use your package manager instead.
1250
1251=cut
1252
1253sub uninstall {
1254 my $self = shift;
1255 my $conf = $self->parent->configure_object();
1256 my %hash = @_;
1257
1258 my ($type,$verbose);
1259 my $tmpl = {
1260 type => { default => 'all', allow => [qw|man prog all|],
1261 store => \$type },
1262 verbose => { default => $conf->get_conf('verbose'),
1263 store => \$verbose },
1264 force => { default => $conf->get_conf('force') },
1265 };
1266
1267 ### XXX add a warning here if your default install dist isn't
1268 ### makefile or build -- that means you are using a package manager
1269 ### and this will not do what you think!
1270
1271 my $args = check( $tmpl, \%hash ) or return;
1272
1273 if( $conf->get_conf('dist_type') and (
1274 ($conf->get_conf('dist_type') ne INSTALLER_BUILD) or
1275 ($conf->get_conf('dist_type') ne INSTALLER_MM))
1276 ) {
1277 msg(loc("You have a default installer type set (%1) ".
1278 "-- you should probably use that package manager to " .
1279 "uninstall modules", $conf->get_conf('dist_type')), $verbose);
1280 }
1281
1282 ### check if we even have the module installed -- no point in continuing
1283 ### otherwise
1284 unless( $self->installed_version ) {
1285 error( loc( "Module '%1' is not installed, so cannot uninstall",
1286 $self->module ) );
1287 return;
1288 }
1289
1290 ### nothing to uninstall ###
1291 my $files = $self->files( type => $type ) or return;
1292 my $dirs = $self->directory_tree( type => $type ) or return;
1293 my $sudo = $conf->get_program('sudo');
1294
1295 ### just in case there's no file; M::B doensn't provide .packlists yet ###
1296 my $pack = $self->packlist;
1297 $pack = $pack->[0]->packlist_file() if $pack;
1298
1299 ### first remove the files, then the dirs if they are empty ###
1300 my $flag = 0;
1301 for my $file( @$files, $pack ) {
1302 next unless defined $file && -f $file;
1303
1304 msg(loc("Unlinking '%1'", $file), $verbose);
1305
1306 my @cmd = ($^X, "-eunlink+q[$file]");
1307 unshift @cmd, $sudo if $sudo;
1308
1309 my $buffer;
1310 unless ( run( command => \@cmd,
1311 verbose => $verbose,
1312 buffer => \$buffer )
1313 ) {
1314 error(loc("Failed to unlink '%1': '%2'",$file, $buffer));
1315 $flag++;
1316 }
1317 }
1318
1319 for my $dir ( sort @$dirs ) {
1320 local *DIR;
1321 open DIR, $dir or next;
1322 my @count = readdir(DIR);
1323 close DIR;
1324
1325 next unless @count == 2; # . and ..
1326
1327 msg(loc("Removing '%1'", $dir), $verbose);
1328
1329 ### this fails on my win2k machines.. it indeed leaves the
1330 ### dir, but it's not a critical error, since the files have
1331 ### been removed. --kane
1332 #unless( rmdir $dir ) {
1333 # error( loc( "Could not remove '%1': %2", $dir, $! ) )
1334 # unless $^O eq 'MSWin32';
1335 #}
1336
1337 my @cmd = ($^X, "-ermdir+q[$dir]");
1338 unshift @cmd, $sudo if $sudo;
1339
1340 my $buffer;
1341 unless ( run( command => \@cmd,
1342 verbose => $verbose,
1343 buffer => \$buffer )
1344 ) {
1345 error(loc("Failed to rmdir '%1': %2",$dir,$buffer));
1346 $flag++;
1347 }
1348 }
1349
1350 $self->status->uninstall(!$flag);
1351 $self->status->installed( $flag ? 1 : undef);
1352
1353 return !$flag;
1354}
1355
1356=pod
1357
1358=head2 @modobj = $self->distributions()
1359
1360Returns a list of module objects representing all releases for this
1361module on success, false on failure.
1362
1363=cut
1364
1365sub distributions {
1366 my $self = shift;
1367 my %hash = @_;
1368
1369 my @list = $self->author->distributions( %hash, module => $self ) or return;
1370
1371 ### it's another release then by the same author ###
1372 return grep { $_->package_name eq $self->package_name } @list;
1373}
1374
1375=pod
1376
1377=head2 @list = $self->files ()
1378
1379Returns a list of files used by this module, if it is installed.
1380
1381=cut
1382
1383sub files {
1384 return shift->_extutils_installed( @_, method => 'files' );
1385}
1386
1387=pod
1388
1389=head2 @list = $self->directory_tree ()
1390
1391Returns a list of directories used by this module.
1392
1393=cut
1394
1395sub directory_tree {
1396 return shift->_extutils_installed( @_, method => 'directory_tree' );
1397}
1398
1399=pod
1400
1401=head2 @list = $self->packlist ()
1402
1403Returns the C<ExtUtils::Packlist> object for this module.
1404
1405=cut
1406
1407sub packlist {
1408 return shift->_extutils_installed( @_, method => 'packlist' );
1409}
1410
1411=pod
1412
1413=head2 @list = $self->validate ()
1414
1415Returns a list of files that are missing for this modules, but
1416are present in the .packlist file.
1417
1418=cut
1419
1420sub validate {
1421 return shift->_extutils_installed( method => 'validate' );
1422}
1423
1424### generic method to call an ExtUtils::Installed method ###
1425sub _extutils_installed {
1426 my $self = shift;
1427 my $conf = $self->parent->configure_object();
1428 my %hash = @_;
1429
1430 my ($verbose,$type,$method);
1431 my $tmpl = {
1432 verbose => { default => $conf->get_conf('verbose'),
1433 store => \$verbose, },
1434 type => { default => 'all',
1435 allow => [qw|prog man all|],
1436 store => \$type, },
1437 method => { required => 1,
1438 store => \$method,
1439 allow => [qw|files directory_tree packlist
1440 validate|],
1441 },
1442 };
1443
1444 my $args = check( $tmpl, \%hash ) or return;
1445
1446 ### old versions of cygwin + perl < 5.8 are buggy here. bail out if we
1447 ### find we're being used by them
1448 { my $err = ON_OLD_CYGWIN;
1449 if($err) { error($err); return };
1450 }
1451
1452 return unless can_load(
1453 modules => { 'ExtUtils::Installed' => '0.0' },
1454 verbose => $verbose,
1455 );
1456
1457 my $inst;
1458 unless( $inst = ExtUtils::Installed->new() ) {
1459 error( loc("Could not create an '%1' object", 'ExtUtils::Installed' ) );
1460
1461 ### in case it's being used directly... ###
1462 return;
1463 }
1464
1465
1466 { ### EU::Installed can die =/
1467 my @files;
1468 eval { @files = $inst->$method( $self->module, $type ) };
1469
1470 if( $@ ) {
1471 chomp $@;
1472 error( loc("Could not get '%1' for '%2': %3",
1473 $method, $self->module, $@ ) );
1474 return;
1475 }
1476
1477 return wantarray ? @files : \@files;
1478 }
1479}
1480
1481=head2 $bool = $self->add_to_includepath;
1482
1483Adds the current modules path to C<@INC> and C<$PERL5LIB>. This allows
1484you to add the module from it's build dir to your path.
1485
1486You can reset C<@INC> and C<$PERL5LIB> to it's original state when you
1487started the program, by calling:
1488
1489 $self->parent->flush('lib');
1490
1491=cut
1492
1493sub add_to_includepath {
1494 my $self = shift;
1495 my $cb = $self->parent;
1496
1497 if( my $dir = $self->status->extract ) {
1498
1499 $cb->_add_to_includepath(
1500 directories => [
1501 File::Spec->catdir(BLIB->($dir), LIB),
1502 File::Spec->catdir(BLIB->($dir), ARCH),
1503 BLIB->($dir),
1504 ]
1505 ) or return;
1506
1507 } else {
1508 error(loc( "No extract dir registered for '%1' -- can not add ".
1509 "add builddir to search path!", $self->module ));
1510 return;
1511 }
1512
1513 return 1;
1514
1515}
1516
1517=pod
1518
1519=head2 $path = $self->best_path_to_module_build();
1520
1521B<OBSOLETE>
1522
1523If a newer version of Module::Build is found in your path, it will
1524return this C<special> path. If the newest version of C<Module::Build>
1525is found in your regular C<@INC>, the method will return false. This
1526indicates you do not need to add a special directory to your C<@INC>.
1527
1528Note that this is only relevant if you're building your own
1529C<CPANPLUS::Dist::*> plugin -- the built-in dist types already have
1530this taken care of.
1531
1532=cut
1533
1534### make sure we're always running 'perl Build.PL' and friends
1535### against the highest version of module::build available
1536sub best_path_to_module_build {
1537 my $self = shift;
1538
1539 ### Since M::B will actually shell out and run the Build.PL, we must
1540 ### make sure it refinds the proper version of M::B in the path.
1541 ### that may be either in our cp::inc or in site_perl, or even a
1542 ### new M::B being installed.
1543 ### don't add anything else here, as that might screw up prereq checks
1544
1545 ### XXX this might be needed for Dist::MM too, if a makefile.pl is
1546 ### masquerading as a Build.PL
1547
1548 ### did we find the most recent module::build in our installer path?
1549
1550 ### XXX can't do changes to @INC, they're being ignored by
1551 ### new_from_context when writing a Build script. see ticket:
1552 ### #8826 Module::Build ignores changes to @INC when writing Build
1553 ### from new_from_context
1554 ### XXX applied schwern's patches (as seen on CPANPLUS::Devel 10/12/04)
1555 ### and upped the version to 0.26061 of the bundled version, and things
1556 ### work again
1557
1558 ### this functionality is now obsolete -- prereqs should be installed
1559 ### and we no longer use the CPANPLUS::inc magic.. so comment this out.
1560# require Module::Build;
1561# if( CPANPLUS::inc->path_to('Module::Build') and (
1562# CPANPLUS::inc->path_to('Module::Build') eq
1563# CPANPLUS::inc->installer_path )
1564# ) {
1565#
1566# ### if the module being installed is *not* Module::Build
1567# ### itself -- as that would undoubtedly be newer -- add
1568# ### the path to the installers to @INC
1569# ### if it IS module::build itself, add 'lib' to its path,
1570# ### as the Build.PL would do as well, but the API doesn't.
1571# ### this makes self updates possible
1572# return $self->module eq 'Module::Build'
1573# ? 'lib'
1574# : CPANPLUS::inc->installer_path;
1575# }
1576
1577 ### otherwise, the path was found through a 'normal' way of
1578 ### scanning @INC.
1579 return;
1580}
1581
1582=pod
1583
1584=head1 BUG REPORTS
1585
1586Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
1587
1588=head1 AUTHOR
1589
1590This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
1591
1592=head1 COPYRIGHT
1593
1594The CPAN++ interface (of which this module is a part of) is copyright (c)
15952001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
1596
1597This library is free software; you may redistribute and/or modify it
1598under the same terms as Perl itself.
1599
1600=cut
1601
1602# Local variables:
1603# c-indentation-style: bsd
1604# c-basic-offset: 4
1605# indent-tabs-mode: nil
1606# End:
1607# vim: expandtab shiftwidth=4:
1608
16091;
1610
1611__END__
1612
1613todo:
1614reports();