[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 package CPANPLUS::Configure; 2 use strict; 3 4 5 use CPANPLUS::Internals::Constants; 6 use CPANPLUS::Error; 7 use CPANPLUS::Config; 8 9 use Log::Message; 10 use Module::Load qw[load]; 11 use Params::Check qw[check]; 12 use File::Basename qw[dirname]; 13 use Module::Loaded (); 14 use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext'; 15 16 use vars qw[$AUTOLOAD $VERSION $MIN_CONFIG_VERSION]; 17 use base qw[CPANPLUS::Internals::Utils]; 18 19 local $Params::Check::VERBOSE = 1; 20 21 ### require, avoid circular use ### 22 require CPANPLUS::Internals; 23 $VERSION = $CPANPLUS::Internals::VERSION = $CPANPLUS::Internals::VERSION; 24 25 ### can't use O::A as we're using our own AUTOLOAD to get to 26 ### the config options. 27 for my $meth ( qw[conf]) { 28 no strict 'refs'; 29 30 *$meth = sub { 31 my $self = shift; 32 $self->{'_'.$meth} = $_[0] if @_; 33 return $self->{'_'.$meth}; 34 } 35 } 36 37 38 =pod 39 40 =head1 NAME 41 42 CPANPLUS::Configure 43 44 =head1 SYNOPSIS 45 46 $conf = CPANPLUS::Configure->new( ); 47 48 $bool = $conf->can_save; 49 $bool = $conf->save( $where ); 50 51 @opts = $conf->options( $type ); 52 53 $make = $conf->get_program('make'); 54 $verbose = $conf->set_conf( verbose => 1 ); 55 56 =head1 DESCRIPTION 57 58 This module deals with all the configuration issues for CPANPLUS. 59 Users can use objects created by this module to alter the behaviour 60 of CPANPLUS. 61 62 Please refer to the C<CPANPLUS::Backend> documentation on how to 63 obtain a C<CPANPLUS::Configure> object. 64 65 =head1 METHODS 66 67 =head2 $Configure = CPANPLUS::Configure->new( load_configs => BOOL ) 68 69 This method returns a new object. Normal users will never need to 70 invoke the C<new> method, but instead retrieve the desired object via 71 a method call on a C<CPANPLUS::Backend> object. 72 73 The C<load_configs> parameter controls wether or not additional 74 user configurations are to be loaded or not. Defaults to C<true>. 75 76 =cut 77 78 ### store teh CPANPLUS::Config object in a closure, so we only 79 ### initialize it once.. otherwise, on a 2nd ->new, settings 80 ### from configs on top of this one will be reset 81 { my $Config; 82 83 sub new { 84 my $class = shift; 85 my %hash = @_; 86 87 ### XXX pass on options to ->init() like rescan? 88 my ($load); 89 my $tmpl = { 90 load_configs => { default => 1, store => \$load }, 91 }; 92 93 check( $tmpl, \%hash ) or ( 94 warn Params::Check->last_error, return 95 ); 96 97 $Config ||= CPANPLUS::Config->new; 98 my $self = bless {}, $class; 99 $self->conf( $Config ); 100 101 ### you want us to load other configs? 102 ### these can override things in the default config 103 $self->init if $load; 104 105 return $self; 106 } 107 } 108 109 =head2 $bool = $Configure->init( [rescan => BOOL]) 110 111 Initialize the configure with other config files than just 112 the default 'CPANPLUS::Config'. 113 114 Called from C<new()> to load user/system configurations 115 116 If the C<rescan> option is provided, your disk will be 117 examined again to see if there are new config files that 118 could be read. Defaults to C<false>. 119 120 Returns true on success, false on failure. 121 122 =cut 123 124 ### move the Module::Pluggable detection to runtime, rather 125 ### than compile time, so that a simple 'require CPANPLUS' 126 ### doesn't start running over your filesystem for no good 127 ### reason. Make sure we only do the M::P call once though. 128 ### we use $loaded to mark it 129 { my $loaded; 130 my $warned; 131 sub init { 132 my $self = shift; 133 my $obj = $self->conf; 134 my %hash = @_; 135 136 my ($rescan); 137 my $tmpl = { 138 rescan => { default => 0, store => \$rescan }, 139 }; 140 141 check( $tmpl, \%hash ) or ( 142 warn Params::Check->last_error, return 143 ); 144 145 ### warn if we find an old style config specified 146 ### via environment variables 147 { my $env = ENV_CPANPLUS_CONFIG; 148 if( $ENV{$env} and not $warned ) { 149 $warned++; 150 error(loc("Specifying a config file in your environment " . 151 "using %1 is obsolete.\nPlease follow the ". 152 "directions outlined in %2 or use the '%3' command\n". 153 "in the default shell to use custom config files.", 154 $env, "CPANPLUS::Configure->save", 's save')); 155 } 156 } 157 158 ### make sure that the homedir is included now 159 local @INC = ( CONFIG_USER_LIB_DIR->(), @INC ); 160 161 ### only set it up once 162 if( !$loaded++ or $rescan ) { 163 ### find plugins & extra configs 164 ### check $home/.cpanplus/lib as well 165 require Module::Pluggable; 166 167 Module::Pluggable->import( 168 search_path => ['CPANPLUS::Config'], 169 search_dirs => [ CONFIG_USER_LIB_DIR ], 170 except => qr/::SUPER$/, 171 sub_name => 'configs' 172 ); 173 } 174 175 176 ### do system config, user config, rest.. in that order 177 ### apparently, on a 2nd invocation of -->configs, a 178 ### ::ISA::CACHE package can appear.. that's bad... 179 my %confs = map { $_ => $_ } 180 grep { $_ !~ /::ISA::/ } __PACKAGE__->configs; 181 my @confs = grep { defined } 182 map { delete $confs{$_} } CONFIG_SYSTEM, CONFIG_USER; 183 push @confs, sort keys %confs; 184 185 for my $plugin ( @confs ) { 186 msg(loc("Found config '%1'", $plugin),0); 187 188 ### if we already did this the /last/ time around dont 189 ### run the setup agian. 190 if( my $loc = Module::Loaded::is_loaded( $plugin ) ) { 191 msg(loc(" Already loaded '%1' (%2)", $plugin, $loc), 0); 192 next; 193 } else { 194 msg(loc(" Loading config '%1'", $plugin),0); 195 196 eval { load $plugin }; 197 msg(loc(" Loaded '%1' (%2)", 198 $plugin, Module::Loaded::is_loaded( $plugin ) ), 0); 199 } 200 201 if( $@ ) { 202 error(loc("Could not load '%1': %2", $plugin, $@)); 203 next; 204 } 205 206 my $sub = $plugin->can('setup'); 207 $sub->( $self ) if $sub; 208 } 209 210 ### clean up the paths once more, just in case 211 $obj->_clean_up_paths; 212 213 return 1; 214 } 215 } 216 =pod 217 218 =head2 can_save( [$config_location] ) 219 220 Check if we can save the configuration to the specified file. 221 If no file is provided, defaults to your personal config. 222 223 Returns true if the file can be saved, false otherwise. 224 225 =cut 226 227 sub can_save { 228 my $self = shift; 229 my $file = shift || CONFIG_USER_FILE->(); 230 231 return 1 unless -e $file; 232 233 chmod 0644, $file; 234 return (-w $file); 235 } 236 237 =pod 238 239 =head2 $file = $conf->save( [$package_name] ) 240 241 Saves the configuration to the package name you provided. 242 If this package is not C<CPANPLUS::Config::System>, it will 243 be saved in your C<.cpanplus> directory, otherwise it will 244 be attempted to be saved in the system wide directory. 245 246 If no argument is provided, it will default to your personal 247 config. 248 249 Returns the full path to the file if the config was saved, 250 false otherwise. 251 252 =cut 253 254 sub _config_pm_to_file { 255 my $self = shift; 256 my $pm = shift or return; 257 my $dir = shift || CONFIG_USER_LIB_DIR->(); 258 259 ### only 3 types of files know: home, system and 'other' 260 ### so figure out where to save them based on their type 261 my $file; 262 if( $pm eq CONFIG_USER ) { 263 $file = CONFIG_USER_FILE->(); 264 265 } elsif ( $pm eq CONFIG_SYSTEM ) { 266 $file = CONFIG_SYSTEM_FILE->(); 267 268 ### third party file 269 } else { 270 my $cfg_pkg = CONFIG . '::'; 271 unless( $pm =~ /^$cfg_pkg/ ) { 272 error(loc( 273 "WARNING: Your config package '%1' is not in the '%2' ". 274 "namespace and will not be automatically detected by %3", 275 $pm, $cfg_pkg, 'CPANPLUS' 276 )); 277 } 278 279 $file = File::Spec->catfile( 280 $dir, 281 split( '::', $pm ) 282 ) . '.pm'; 283 } 284 285 return $file; 286 } 287 288 289 sub save { 290 my $self = shift; 291 my $pm = shift || CONFIG_USER; 292 my $savedir = shift || ''; 293 294 my $file = $self->_config_pm_to_file( $pm, $savedir ) or return; 295 my $dir = dirname( $file ); 296 297 unless( -d $dir ) { 298 $self->_mkdir( dir => $dir ) or ( 299 error(loc("Can not create directory '%1' to save config to",$dir)), 300 return 301 ) 302 } 303 return unless $self->can_save($file); 304 305 ### find only accesors that are not private 306 my @acc = sort grep { $_ !~ /^_/ } $self->conf->ls_accessors; 307 308 ### for dumping the values 309 use Data::Dumper; 310 311 my @lines; 312 for my $acc ( @acc ) { 313 314 push @lines, "### $acc section", $/; 315 316 for my $key ( $self->conf->$acc->ls_accessors ) { 317 my $val = Dumper( $self->conf->$acc->$key ); 318 319 $val =~ s/\$VAR1\s+=\s+//; 320 $val =~ s/;\n//; 321 322 push @lines, '$'. "conf->set_$acc}( $key => $val );", $/; 323 } 324 push @lines, $/,$/; 325 326 } 327 328 my $str = join '', map { " $_" } @lines; 329 330 ### use a variable to make sure the pod parser doesn't snag it 331 my $is = '='; 332 my $time = gmtime; 333 334 335 my $msg = <<_END_OF_CONFIG_; 336 ############################################### 337 ### 338 ### Configuration structure for $pm 339 ### 340 ############################################### 341 342 #last changed: $time GMT 343 344 ### minimal pod, so you can find it with perldoc -l, etc 345 $is}pod 346 347 $is}head1 NAME 348 349 $pm 350 351 $is}head1 DESCRIPTION 352 353 This is a CPANPLUS configuration file. Editing this 354 config changes the way CPANPLUS will behave 355 356 $is}cut 357 358 package $pm; 359 360 use strict; 361 362 sub setup { 363 my \$conf = shift; 364 365 $str 366 367 return 1; 368 } 369 370 1; 371 372 _END_OF_CONFIG_ 373 374 $self->_move( file => $file, to => "$file~" ) if -f $file; 375 376 my $fh = new FileHandle; 377 $fh->open(">$file") 378 or (error(loc("Could not open '%1' for writing: %2", $file, $!)), 379 return ); 380 381 $fh->print($msg); 382 $fh->close; 383 384 return $file; 385 } 386 387 =pod 388 389 =head2 options( type => TYPE ) 390 391 Returns a list of all valid config options given a specific type 392 (like for example C<conf> of C<program>) or false if the type does 393 not exist 394 395 =cut 396 397 sub options { 398 my $self = shift; 399 my $conf = $self->conf; 400 my %hash = @_; 401 402 my $type; 403 my $tmpl = { 404 type => { required => 1, default => '', 405 strict_type => 1, store => \$type }, 406 }; 407 408 check($tmpl, \%hash) or return; 409 410 my %seen; 411 return sort grep { !$seen{$_}++ } 412 map { $_->$type->ls_accessors if $_->can($type) } 413 $self->conf; 414 return; 415 } 416 417 =pod 418 419 =head1 ACCESSORS 420 421 Accessors that start with a C<_> are marked private -- regular users 422 should never need to use these. 423 424 See the C<CPANPLUS::Config> documentation for what items can be 425 set and retrieved. 426 427 =head2 get_SOMETHING( ITEM, [ITEM, ITEM, ... ] ); 428 429 The C<get_*> style accessors merely retrieves one or more desired 430 config options. 431 432 =head2 set_SOMETHING( ITEM => VAL, [ITEM => VAL, ITEM => VAL, ... ] ); 433 434 The C<set_*> style accessors set the current value for one 435 or more config options and will return true upon success, false on 436 failure. 437 438 =head2 add_SOMETHING( ITEM => VAL, [ITEM => VAL, ITEM => VAL, ... ] ); 439 440 The C<add_*> style accessor adds a new key to a config key. 441 442 Currently, the following accessors exist: 443 444 =over 4 445 446 =item set|get_conf 447 448 Simple configuration directives like verbosity and favourite shell. 449 450 =item set|get_program 451 452 Location of helper programs. 453 454 =item _set|_get_build 455 456 Locations of where to put what files for CPANPLUS. 457 458 =item _set|_get_source 459 460 Locations and names of source files locally. 461 462 =item _set|_get_mirror 463 464 Locations and names of source files remotely. 465 466 =item _set|_get_fetch 467 468 Special settings pertaining to the fetching of files. 469 470 =back 471 472 =cut 473 474 sub AUTOLOAD { 475 my $self = shift; 476 my $conf = $self->conf; 477 478 my $name = $AUTOLOAD; 479 $name =~ s/.+:://; 480 481 my ($private, $action, $field) = 482 $name =~ m/^(_)?((?:[gs]et|add))_([a-z]+)$/; 483 484 my $type = ''; 485 $type .= '_' if $private; 486 $type .= $field if $field; 487 488 unless ( $conf->can($type) ) { 489 error( loc("Invalid method type: '%1'", $name) ); 490 return; 491 } 492 493 unless( scalar @_ ) { 494 error( loc("No arguments provided!") ); 495 return; 496 } 497 498 ### retrieve a current value for an existing key ### 499 if( $action eq 'get' ) { 500 for my $key (@_) { 501 my @list = (); 502 503 ### get it from the user config first 504 if( $conf->can($type) and $conf->$type->can($key) ) { 505 push @list, $conf->$type->$key; 506 507 ### XXX EU::AI compatibility hack to provide lookups like in 508 ### cpanplus 0.04x; we renamed ->_get_build('base') to 509 ### ->get_conf('base') 510 } elsif ( $type eq '_build' and $key eq 'base' ) { 511 return $self->get_conf($key); 512 513 } else { 514 error( loc(q[No such key '%1' in field '%2'], $key, $type) ); 515 return; 516 } 517 518 return wantarray ? @list : $list[0]; 519 } 520 521 ### set an existing key to a new value ### 522 } elsif ( $action eq 'set' ) { 523 my %args = @_; 524 525 while( my($key,$val) = each %args ) { 526 527 if( $conf->can($type) and $conf->$type->can($key) ) { 528 $conf->$type->$key( $val ); 529 530 } else { 531 error( loc(q[No such key '%1' in field '%2'], $key, $type) ); 532 return; 533 } 534 } 535 536 return 1; 537 538 ### add a new key to the config ### 539 } elsif ( $action eq 'add' ) { 540 my %args = @_; 541 542 while( my($key,$val) = each %args ) { 543 544 if( $conf->$type->can($key) ) { 545 error( loc( q[Key '%1' already exists for field '%2'], 546 $key, $type)); 547 return; 548 } else { 549 $conf->$type->mk_accessors( $key ); 550 $conf->$type->$key( $val ); 551 } 552 } 553 return 1; 554 555 } else { 556 557 error( loc(q[Unknown action '%1'], $action) ); 558 return; 559 } 560 } 561 562 sub DESTROY { 1 }; 563 564 1; 565 566 =pod 567 568 =head1 BUG REPORTS 569 570 Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>. 571 572 =head1 AUTHOR 573 574 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>. 575 576 =head1 COPYRIGHT 577 578 The CPAN++ interface (of which this module is a part of) is copyright (c) 579 2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved. 580 581 This library is free software; you may redistribute and/or modify it 582 under the same terms as Perl itself. 583 584 =head1 SEE ALSO 585 586 L<CPANPLUS::Backend>, L<CPANPLUS::Configure::Setup>, L<CPANPLUS::Config> 587 588 =cut 589 590 # Local variables: 591 # c-indentation-style: bsd 592 # c-basic-offset: 4 593 # indent-tabs-mode: nil 594 # End: 595 # vim: expandtab shiftwidth=4: 596
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |