1 package CPANPLUS::Selfupdate;
4 use Params::Check qw[check];
5 use IPC::Cmd qw[can_run];
6 use CPANPLUS::Error qw[error msg];
7 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
9 use CPANPLUS::Internals::Constants;
11 $Params::Check::VERBOSE = 1;
19 $su = $cb->selfupdate_object;
21 @feats = $su->list_features;
22 @feats = $su->list_enabled_features;
24 @mods = map { $su->modules_for_feature( $_ ) } @feats;
25 @mods = $su->list_core_dependencies;
26 @mods = $su->list_core_modules;
29 print $_->name " should be version " . $_->version_required;
30 print "Installed version is not uptodate!"
31 unless $_->is_installed_version_sufficient;
34 $ok = $su->selfupdate( update => 'all', latest => 0 );
38 ### a config has describing our deps etc
43 'File::Fetch' => '0.08', # win32 ftp support
44 'File::Spec' => '0.82',
45 'IPC::Cmd' => '0.36', # 5.6.2 compat: 2-arg open
46 'Locale::Maketext::Simple' => '0.01',
47 'Log::Message' => '0.01',
48 'Module::Load' => '0.10',
49 'Module::Load::Conditional' => '0.16', # Better parsing: #23995
50 'version' => '0.70', # needed for M::L::C
51 # addresses #24630 and
53 'Params::Check' => '0.22',
54 'Package::Constants' => '0.01',
56 'Test::Harness' => '2.62', # due to bug #19505
57 # only 2.58 and 2.60 are bad
58 'Test::More' => '0.47', # to run our tests
59 'Archive::Extract' => '0.16', # ./Dir bug fix
60 'Archive::Tar' => '1.23',
61 'IO::Zlib' => '1.04', # needed for Archive::Tar
62 'Object::Accessor' => '0.32', # overloaded stringification
63 'Module::CoreList' => '2.09',
64 'Module::Pluggable' => '2.4',
65 'Module::Loaded' => '0.01',
69 # config_key_name => [
70 # sub { } to list module key/value pairs
71 # sub { } to check if feature is enabled
76 $cb->configure_object->get_conf('prefer_makefile')
78 : { 'CPANPLUS::Dist::Build' => '0.04' };
80 sub { return 1 }, # always enabled
85 'LWP::UserAgent' => '0.0',
86 'HTTP::Request' => '0.0',
89 'Test::Reporter' => 1.27,
93 return $cb->configure_object->get_conf('cpantest');
99 my $dist = $cb->configure_object->get_conf('dist_type');
100 return { $dist => '0.0' } if $dist;
105 return $cb->configure_object->get_conf('dist_type');
111 'Digest::MD5' => '0.0',
115 return $cb->configure_object->get_conf('md5');
121 my $dist = $cb->configure_object->get_conf('shell');
123 ### we bundle these shells, so don't bother having a dep
124 ### on them... If we don't do this, CPAN.pm actually detects
125 ### a recursive dependency and breaks (see #26077).
126 ### This is not an issue for CPANPLUS itself, it handles
128 return if $dist eq SHELL_DEFAULT or $dist eq SHELL_CLASSIC;
129 return { $dist => '0.0' } if $dist;
137 return if can_run('gpg');
138 ### leave this out -- Crypt::OpenPGP is fairly
139 ### painful to install, and broken on some platforms
140 ### so we'll just always fall back to gpg. It may
141 ### issue a warning or 2, but that's about it.
142 ### this change due to this ticket: #26914
143 # and $cb->configure_object->get_conf('prefer_bin');
144 return { 'Crypt::OpenPGP' => '0.0' };
148 return $cb->configure_object->get_conf('signature');
152 { 'Storable' => '0.0' },
155 return $cb->configure_object->get_conf('storable');
164 sub _get_config { return $Modules }
169 =head2 $self = CPANPLUS::Selfupdate->new( $backend_object );
171 Sets up a new selfupdate object. Called automatically when
172 a new backend object is created.
178 my $cb = shift or return;
179 return bless sub { $cb }, $class;
184 =head2 $bool = $self->selfupdate( update => "core|dependencies|enabled_features|features|all", latest => BOOL )
186 Selfupdate CPANPLUS. You can update either the core (CPANPLUS itself),
187 the core dependencies, all features you have currently turned on, or
188 all features available, or everything.
190 The C<latest> option determines whether it should update to the latest
191 version on CPAN, or if the minimal required version for CPANPLUS is
194 Returns true on success, false on error.
201 my $conf = $cb->configure_object;
204 ### cache to find the relevant modules
206 core => sub { $self->list_core_modules },
207 dependencies => sub { $self->list_core_dependencies },
208 enabled_features => sub { map { $self->modules_for_feature( $_ ) }
209 $self->list_enabled_features
211 features => sub { map { $self->modules_for_feature( $_ ) }
214 ### make sure to do 'core' first, in case
215 ### we are out of date ourselves
216 all => [ qw|core dependencies enabled_features| ],
219 my($type, $latest, $force);
221 update => { required => 1, store => \$type,
222 allow => [ keys %$cache ], },
223 latest => { default => 0, store => \$latest, allow => BOOLEANS },
224 force => { default => $conf->get_conf('force'), store => \$force },
227 check( $tmpl, \%hash ) or return;
229 my $ref = $cache->{$type};
230 my @mods = UNIVERSAL::isa( $ref, 'ARRAY' )
231 ? map { $cache->{$_}->() } @$ref
234 ### do we need the latest versions?
237 : grep { !$_->is_installed_version_sufficient } @mods;
240 for my $mod ( @mods ) {
241 unless( $mod->install( force => $force ) ) {
243 error(loc("Failed to update module '%1'", $mod->name));
251 =head2 @features = $self->list_features
253 Returns a list of features that are supported by CPANPLUS.
259 return keys %{ $self->_get_config->{'features'} };
262 =head2 @features = $self->list_enabled_features
264 Returns a list of features that are enabled in your current
265 CPANPLUS installation.
269 sub list_enabled_features {
274 for my $feat ( $self->list_features ) {
275 my $ref = $self->_get_config->{'features'}->{$feat}->[1];
276 push @enabled, $feat if $ref->($cb);
282 =head2 @mods = $self->modules_for_feature( FEATURE [,AS_HASH] )
284 Returns a list of C<CPANPLUS::Selfupdate::Module> objects which
285 represent the modules required to support this feature.
287 For a list of features, call the C<list_features> method.
289 If the C<AS_HASH> argument is provided, no module objects are
290 returned, but a hashref where the keys are names of the modules,
291 and values are their minimum versions.
295 sub modules_for_feature {
297 my $feature = shift or return;
298 my $as_hash = shift || 0;
301 unless( exists $self->_get_config->{'features'}->{$feature} ) {
302 error(loc("Unknown feature '%1'", $feature));
306 my $ref = $self->_get_config->{'features'}->{$feature}->[0];
308 ### it's either a list of modules/versions or a subroutine that
309 ### returns a list of modules/versions
310 my $href = UNIVERSAL::isa( $ref, 'HASH' ) ? $ref : $ref->( $cb );
312 return unless $href; # nothing needed for the feature?
314 return $href if $as_hash;
315 return $self->_hashref_to_module( $href );
319 =head2 @mods = $self->list_core_dependencies( [AS_HASH] )
321 Returns a list of C<CPANPLUS::Selfupdate::Module> objects which
322 represent the modules that comprise the core dependencies of CPANPLUS.
324 If the C<AS_HASH> argument is provided, no module objects are
325 returned, but a hashref where the keys are names of the modules,
326 and values are their minimum versions.
330 sub list_core_dependencies {
332 my $as_hash = shift || 0;
334 my $href = $self->_get_config->{'dependencies'};
336 return $href if $as_hash;
337 return $self->_hashref_to_module( $href );
340 =head2 @mods = $self->list_core_modules( [AS_HASH] )
342 Returns a list of C<CPANPLUS::Selfupdate::Module> objects which
343 represent the modules that comprise the core of CPANPLUS.
345 If the C<AS_HASH> argument is provided, no module objects are
346 returned, but a hashref where the keys are names of the modules,
347 and values are their minimum versions.
351 sub list_core_modules {
353 my $as_hash = shift || 0;
355 my $href = $self->_get_config->{'core'};
357 return $href if $as_hash;
358 return $self->_hashref_to_module( $href );
361 sub _hashref_to_module {
364 my $href = shift or return;
367 CPANPLUS::Selfupdate::Module->new(
368 $cb->module_tree($_) => $href->{$_}
374 =head1 CPANPLUS::Selfupdate::Module
376 C<CPANPLUS::Selfupdate::Module> extends C<CPANPLUS::Module> objects
377 by providing accessors to aid in selfupdating CPANPLUS.
379 These objects are returned by all methods of C<CPANPLUS::Selfupdate>
380 that return module objects.
384 { package CPANPLUS::Selfupdate::Module;
385 use base 'CPANPLUS::Module';
387 ### stores module name -> cpanplus required version
388 ### XXX only can deal with 1 pair!
390 my $Acc = 'version_required';
394 my $mod = shift or return;
395 my $ver = shift; return unless defined $ver;
397 my $obj = $mod->clone; # clone the module object
398 bless $obj, $class; # rebless it to our class
405 =head2 $version = $mod->version_required
407 Returns the version of this module required for CPANPLUS.
411 sub version_required {
413 $Cache{ $self->name } = shift() if @_;
414 return $Cache{ $self->name };
417 =head2 $bool = $mod->is_installed_version_sufficient
419 Returns true if the installed version of this module is sufficient
420 for CPANPLUS, or false if it is not.
425 sub is_installed_version_sufficient {
427 return $self->is_uptodate( version => $self->$Acc );
438 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
442 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
446 The CPAN++ interface (of which this module is a part of) is copyright (c)
447 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
449 This library is free software; you may redistribute and/or modify it
450 under the same terms as Perl itself.
455 # c-indentation-style: bsd
457 # indent-tabs-mode: nil
459 # vim: expandtab shiftwidth=4: