Update to PathTools-3.22.
[p5sagit/p5-mst-13.2.git] / lib / CPAN / HandleConfig.pm
CommitLineData
e82b9348 1package CPAN::HandleConfig;
2use strict;
87892b73 3use vars qw(%can %keys $VERSION);
1a43333d 4
7d97ad34 5$VERSION = sprintf "%.6f", substr(q$Rev: 958 $,4)/1000000 + 5.4;
e82b9348 6
7%can = (
4d1321a7 8 commit => "Commit changes to disk",
9 defaults => "Reload defaults from disk",
10 help => "Short help about 'o conf' usage",
11 init => "Interactive setting of all options",
e82b9348 12);
13
4d1321a7 14%keys = map { $_ => undef } (
ed84aac9 15 # allow_unauthenticated ?? some day...
4d1321a7 16 "build_cache",
17 "build_dir",
135a59c2 18 "build_requires_install_policy",
4d1321a7 19 "bzip2",
20 "cache_metadata",
ed84aac9 21 "check_sigs",
8962fc49 22 "colorize_output",
23 "colorize_print",
24 "colorize_warn",
4d1321a7 25 "commandnumber_in_prompt",
26844e27 26 "commands_quote",
4d1321a7 27 "cpan_home",
28 "curl",
29 "dontload_hash", # deprecated after 1.83_68 (rev. 581)
30 "dontload_list",
31 "ftp",
32 "ftp_passive",
33 "ftp_proxy",
34 "getcwd",
35 "gpg",
36 "gzip",
37 "histfile",
38 "histsize",
39 "http_proxy",
40 "inactivity_timeout",
41 "index_expire",
42 "inhibit_startup_message",
43 "keep_source_where",
44 "lynx",
45 "make",
46 "make_arg",
47 "make_install_arg",
48 "make_install_make_command",
49 "makepl_arg",
50 "mbuild_arg",
51 "mbuild_install_arg",
52 "mbuild_install_build_command",
53 "mbuildpl_arg",
54 "ncftp",
55 "ncftpget",
56 "no_proxy",
57 "pager",
ed84aac9 58 "password",
4d1321a7 59 "prefer_installer",
60 "prerequisites_policy",
8962fc49 61 "proxy_pass",
62 "proxy_user",
4d1321a7 63 "scan_cache",
64 "shell",
65 "show_upload_date",
66 "tar",
67 "term_is_latin",
ed84aac9 68 "term_ornaments",
8962fc49 69 "test_report",
4d1321a7 70 "unzip",
71 "urllist",
ed84aac9 72 "username",
4d1321a7 73 "wait_list",
74 "wget",
75 );
44d21104 76if ($^O eq "MSWin32") {
77 for my $k (qw(
78 mbuild_install_build_command
79 make_install_make_command
80 )) {
81 delete $keys{$k};
82 if (exists $CPAN::Config->{$k}) {
87892b73 83 for ("deleting previously set config variable '$k' => '$CPAN::Config->{$k}'") {
84 $CPAN::Frontend ? $CPAN::Frontend->mywarn($_) : warn $_;
85 }
44d21104 86 delete $CPAN::Config->{$k};
87 }
88 }
89}
e82b9348 90
91# returns true on successful action
92sub edit {
93 my($self,@args) = @_;
94 return unless @args;
95 CPAN->debug("self[$self]args[".join(" | ",@args)."]");
96 my($o,$str,$func,$args,$key_exists);
97 $o = shift @args;
9ddc4ed0 98 $DB::single = 1;
e82b9348 99 if($can{$o}) {
8962fc49 100 $self->$o(args => \@args); # o conf init => sub init => sub load
e82b9348 101 return 1;
102 } else {
103 CPAN->debug("o[$o]") if $CPAN::DEBUG;
104 unless (exists $keys{$o}) {
105 $CPAN::Frontend->mywarn("Warning: unknown configuration variable '$o'\n");
106 }
107 if ($o =~ /list$/) {
108 $func = shift @args;
109 $func ||= "";
110 CPAN->debug("func[$func]") if $CPAN::DEBUG;
111 my $changed;
112 # Let's avoid eval, it's easier to comprehend without.
113 if ($func eq "push") {
114 push @{$CPAN::Config->{$o}}, @args;
115 $changed = 1;
116 } elsif ($func eq "pop") {
117 pop @{$CPAN::Config->{$o}};
118 $changed = 1;
119 } elsif ($func eq "shift") {
120 shift @{$CPAN::Config->{$o}};
121 $changed = 1;
122 } elsif ($func eq "unshift") {
123 unshift @{$CPAN::Config->{$o}}, @args;
124 $changed = 1;
125 } elsif ($func eq "splice") {
126 splice @{$CPAN::Config->{$o}}, @args;
127 $changed = 1;
128 } elsif (@args) {
129 $CPAN::Config->{$o} = [@args];
130 $changed = 1;
131 } else {
132 $self->prettyprint($o);
133 }
4d1321a7 134 if ($changed) {
135 if ($o eq "urllist") {
136 # reset the cached values
137 undef $CPAN::FTP::Thesite;
138 undef $CPAN::FTP::Themethod;
139 } elsif ($o eq "dontload_list") {
140 # empty it, it will be built up again
141 $CPAN::META->{dontload_hash} = {};
142 }
e82b9348 143 }
144 return $changed;
ca79d794 145 } elsif ($o =~ /_hash$/) {
44d21104 146 @args = () if @args==1 && $args[0] eq "";
ca79d794 147 push @args, "" if @args % 2;
148 $CPAN::Config->{$o} = { @args };
149 } else {
e82b9348 150 $CPAN::Config->{$o} = $args[0] if defined $args[0];
7d97ad34 151 $self->prettyprint($o)
152 if exists $keys{$o} or defined $CPAN::Config->{$o};
8962fc49 153 return 1;
e82b9348 154 }
155 }
156}
157
158sub prettyprint {
159 my($self,$k) = @_;
160 my $v = $CPAN::Config->{$k};
161 if (ref $v) {
9ddc4ed0 162 my(@report);
163 if (ref $v eq "ARRAY") {
164 @report = map {"\t[$_]\n"} @$v;
165 } else {
166 @report = map { sprintf("\t%-18s => %s\n",
167 map { "[$_]" } $_,
168 defined $v->{$_} ? $v->{$_} : "UNDEFINED"
169 )} keys %$v;
170 }
e82b9348 171 $CPAN::Frontend->myprint(
172 join(
173 "",
174 sprintf(
175 " %-18s\n",
176 $k
177 ),
9ddc4ed0 178 @report
e82b9348 179 )
180 );
181 } elsif (defined $v) {
182 $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, $v);
183 } else {
184 $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, "UNDEFINED");
185 }
186}
187
188sub commit {
9ddc4ed0 189 my($self,@args) = @_;
190 my $configpm;
191 if (@args) {
192 if ($args[0] eq "args") {
193 # we have not signed that contract
194 } else {
195 $configpm = $args[0];
196 }
197 }
e82b9348 198 unless (defined $configpm){
199 $configpm ||= $INC{"CPAN/MyConfig.pm"};
200 $configpm ||= $INC{"CPAN/Config.pm"};
201 $configpm || Carp::confess(q{
202CPAN::Config::commit called without an argument.
203Please specify a filename where to save the configuration or try
204"o conf init" to have an interactive course through configing.
205});
206 }
207 my($mode);
208 if (-f $configpm) {
209 $mode = (stat $configpm)[2];
210 if ($mode && ! -w _) {
211 Carp::confess("$configpm is not writable");
212 }
213 }
214
215 my $msg;
216 $msg = <<EOF unless $configpm =~ /MyConfig/;
217
218# This is CPAN.pm's systemwide configuration file. This file provides
219# defaults for users, and the values can be changed in a per-user
220# configuration file. The user-config file is being looked for as
221# ~/.cpan/CPAN/MyConfig.pm.
222
223EOF
224 $msg ||= "\n";
225 my($fh) = FileHandle->new;
226 rename $configpm, "$configpm~" if -f $configpm;
227 open $fh, ">$configpm" or
228 $CPAN::Frontend->mydie("Couldn't open >$configpm: $!");
229 $fh->print(qq[$msg\$CPAN::Config = \{\n]);
230 foreach (sort keys %$CPAN::Config) {
44d21104 231 unless (exists $keys{$_}) {
232 $CPAN::Frontend->mywarn("Dropping unknown config variable '$_'\n");
233 delete $CPAN::Config->{$_};
234 next;
235 }
e82b9348 236 $fh->print(
237 " '$_' => ",
ca79d794 238 $self->neatvalue($CPAN::Config->{$_}),
e82b9348 239 ",\n"
240 );
241 }
242
243 $fh->print("};\n1;\n__END__\n");
244 close $fh;
245
246 #$mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
247 #chmod $mode, $configpm;
248###why was that so? $self->defaults;
9ddc4ed0 249 $CPAN::Frontend->myprint("commit: wrote '$configpm'\n");
e82b9348 250 1;
251}
252
ca79d794 253# stolen from MakeMaker; not taking the original because it is buggy;
254# bugreport will have to say: keys of hashes remain unquoted and can
255# produce syntax errors
256sub neatvalue {
257 my($self, $v) = @_;
258 return "undef" unless defined $v;
259 my($t) = ref $v;
260 return "q[$v]" unless $t;
261 if ($t eq 'ARRAY') {
262 my(@m, @neat);
263 push @m, "[";
264 foreach my $elem (@$v) {
265 push @neat, "q[$elem]";
266 }
267 push @m, join ", ", @neat;
268 push @m, "]";
269 return join "", @m;
270 }
271 return "$v" unless $t eq 'HASH';
272 my(@m, $key, $val);
273 while (($key,$val) = each %$v){
274 last unless defined $key; # cautious programming in case (undef,undef) is true
275 push(@m,"q[$key]=>".$self->neatvalue($val)) ;
276 }
277 return "{ ".join(', ',@m)." }";
278}
279
e82b9348 280sub defaults {
281 my($self) = @_;
c9869e1c 282 my $done;
283 for my $config (qw(CPAN/MyConfig.pm CPAN/Config.pm)) {
26844e27 284 if ($INC{$config}) {
285 CPAN::Shell->reload_this($config);
286 $CPAN::Frontend->myprint("'$INC{$config}' reread\n");
287 last;
288 }
c9869e1c 289 }
e82b9348 290 1;
291}
292
ed84aac9 293=head2 C<< CLASS->safe_quote ITEM >>
294
295Quotes an item to become safe against spaces
296in shell interpolation. An item is enclosed
297in double quotes if:
298
299 - the item contains spaces in the middle
300 - the item does not start with a quote
301
302This happens to avoid shell interpolation
303problems when whitespace is present in
304directory names.
305
306This method uses C<commands_quote> to determine
307the correct quote. If C<commands_quote> is
308a space, no quoting will take place.
309
310
311if it starts and ends with the same quote character: leave it as it is
312
313if it contains no whitespace: leave it as it is
314
315if it contains whitespace, then
316
317if it contains quotes: better leave it as it is
318
319else: quote it with the correct quote type for the box we're on
320
321=cut
322
323{
324 # Instead of patching the guess, set commands_quote
325 # to the right value
326 my ($quotes,$use_quote)
327 = $^O eq 'MSWin32'
328 ? ('"', '"')
329 : (q<"'>, "'")
330 ;
331
332 sub safe_quote {
333 my ($self, $command) = @_;
334 # Set up quote/default quote
335 my $quote = $CPAN::Config->{commands_quote} || $quotes;
336
337 if ($quote ne ' '
338 and $command =~ /\s/
339 and $command !~ /[$quote]/) {
340 return qq<$use_quote$command$use_quote>
341 }
342 return $command;
343 }
344}
345
e82b9348 346sub init {
9ddc4ed0 347 my($self,@args) = @_;
e82b9348 348 undef $CPAN::Config->{'inhibit_startup_message'}; # lazy trick to
349 # have the least
350 # important
351 # variable
352 # undefined
9ddc4ed0 353 $self->load(@args);
e82b9348 354 1;
355}
356
357# This is a piece of repeated code that is abstracted here for
358# maintainability. RMB
359#
360sub _configpmtest {
361 my($configpmdir, $configpmtest) = @_;
362 if (-w $configpmtest) {
363 return $configpmtest;
364 } elsif (-w $configpmdir) {
365 #_#_# following code dumped core on me with 5.003_11, a.k.
366 my $configpm_bak = "$configpmtest.bak";
367 unlink $configpm_bak if -f $configpm_bak;
368 if( -f $configpmtest ) {
369 if( rename $configpmtest, $configpm_bak ) {
370 $CPAN::Frontend->mywarn(<<END);
371Old configuration file $configpmtest
372 moved to $configpm_bak
373END
374 }
375 }
376 my $fh = FileHandle->new;
377 if ($fh->open(">$configpmtest")) {
378 $fh->print("1;\n");
379 return $configpmtest;
380 } else {
381 # Should never happen
382 Carp::confess("Cannot open >$configpmtest");
383 }
384 } else { return }
385}
386
87892b73 387sub require_myconfig_or_config () {
388 return if $INC{"CPAN/MyConfig.pm"};
389 local @INC = @INC;
390 my $home = home();
391 unshift @INC, File::Spec->catdir($home,'.cpan');
392 eval { require CPAN::MyConfig };
ed84aac9 393 my $err_myconfig = $@;
394 if ($err_myconfig and $err_myconfig !~ m#locate CPAN/MyConfig\.pm#) {
395 die "Error while requiring CPAN::MyConfig:\n$err_myconfig";
396 }
87892b73 397 unless ($INC{"CPAN/MyConfig.pm"}) { # this guy has settled his needs already
398 eval {require CPAN::Config;}; # not everybody has one
ed84aac9 399 my $err_config = $@;
400 if ($err_config and $err_config !~ m#locate CPAN/Config\.pm#) {
401 die "Error while requiring CPAN::Config:\n$err_config";
402 }
87892b73 403 }
404}
405
406sub home () {
407 my $home;
408 if ($CPAN::META->has_usable("File::HomeDir")) {
409 $home = File::HomeDir->my_data;
410 } else {
411 $home = $ENV{HOME};
412 }
413 $home;
414}
415
e82b9348 416sub load {
417 my($self, %args) = @_;
418 $CPAN::Be_Silent++ if $args{be_silent};
419
420 my(@miss);
421 use Carp;
87892b73 422 require_myconfig_or_config;
e82b9348 423 return unless @miss = $self->missing_config_data;
424
425 require CPAN::FirstTime;
426 my($configpm,$fh,$redo,$theycalled);
427 $redo ||= "";
428 $theycalled++ if @miss==1 && $miss[0] eq 'inhibit_startup_message';
429 if (defined $INC{"CPAN/Config.pm"} && -w $INC{"CPAN/Config.pm"}) {
430 $configpm = $INC{"CPAN/Config.pm"};
431 $redo++;
432 } elsif (defined $INC{"CPAN/MyConfig.pm"} && -w $INC{"CPAN/MyConfig.pm"}) {
433 $configpm = $INC{"CPAN/MyConfig.pm"};
434 $redo++;
435 } else {
436 my($path_to_cpan) = File::Basename::dirname($INC{"CPAN.pm"});
437 my($configpmdir) = File::Spec->catdir($path_to_cpan,"CPAN");
438 my($configpmtest) = File::Spec->catfile($configpmdir,"Config.pm");
c9869e1c 439 my $inc_key;
e82b9348 440 if (-d $configpmdir or File::Path::mkpath($configpmdir)) {
c9869e1c 441 $configpm = _configpmtest($configpmdir,$configpmtest);
442 $inc_key = "CPAN/Config.pm";
e82b9348 443 }
444 unless ($configpm) {
87892b73 445 $configpmdir = File::Spec->catdir(home,".cpan","CPAN");
e82b9348 446 File::Path::mkpath($configpmdir);
447 $configpmtest = File::Spec->catfile($configpmdir,"MyConfig.pm");
c9869e1c 448 $configpm = _configpmtest($configpmdir,$configpmtest);
449 $inc_key = "CPAN/MyConfig.pm";
e82b9348 450 }
c9869e1c 451 if ($configpm) {
452 $INC{$inc_key} = $configpm;
453 } else {
454 my $text = qq{WARNING: CPAN.pm is unable to } .
455 qq{create a configuration file.};
456 output($text, 'confess');
457 }
458
e82b9348 459 }
460 local($") = ", ";
8962fc49 461 if ($redo && ! $theycalled){
462 $CPAN::Frontend->myprint(<<END);
0cf35e6a 463Sorry, we have to rerun the configuration dialog for CPAN.pm due to
464the following indispensable but missing parameters:
e82b9348 465
466@miss
467END
26844e27 468 $args{args} = \@miss;
8962fc49 469 }
7fefbd44 470 if (0) {
471 # where do we need this?
472 $CPAN::Frontend->myprint(qq{
e82b9348 473$configpm initialized.
474});
7fefbd44 475 }
e82b9348 476 CPAN::FirstTime::init($configpm, %args);
477}
478
479sub missing_config_data {
480 my(@miss);
481 for (
0cf35e6a 482 "build_cache",
483 "build_dir",
484 "cache_metadata",
485 "cpan_home",
486 "ftp_proxy",
ed84aac9 487 #"gzip",
0cf35e6a 488 "http_proxy",
489 "index_expire",
490 "inhibit_startup_message",
491 "keep_source_where",
ed84aac9 492 #"make",
0cf35e6a 493 "make_arg",
494 "make_install_arg",
495 "makepl_arg",
496 "mbuild_arg",
497 "mbuild_install_arg",
498 "mbuild_install_build_command",
499 "mbuildpl_arg",
500 "no_proxy",
ed84aac9 501 #"pager",
e82b9348 502 "prerequisites_policy",
0cf35e6a 503 "scan_cache",
ed84aac9 504 #"tar",
505 #"unzip",
0cf35e6a 506 "urllist",
e82b9348 507 ) {
44d21104 508 next unless exists $keys{$_};
e82b9348 509 push @miss, $_ unless defined $CPAN::Config->{$_};
510 }
511 return @miss;
512}
513
e82b9348 514sub help {
515 $CPAN::Frontend->myprint(q[
516Known options:
e82b9348 517 commit commit session changes to disk
4d1321a7 518 defaults reload default config values from disk
519 help this help
26844e27 520 init enter a dialog to set all or a set of parameters
e82b9348 521
4d1321a7 522Edit key values as in the following (the "o" is a literal letter o):
e82b9348 523 o conf build_cache 15
e82b9348 524 o conf build_dir "/foo/bar"
e82b9348 525 o conf urllist shift
e82b9348 526 o conf urllist unshift ftp://ftp.foo.bar/
4d1321a7 527 o conf inhibit_startup_message 1
e82b9348 528
529]);
530 undef; #don't reprint CPAN::Config
531}
532
533sub cpl {
534 my($word,$line,$pos) = @_;
535 $word ||= "";
536 CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
537 my(@words) = split " ", substr($line,0,$pos+1);
538 if (
539 defined($words[2])
540 and
8962fc49 541 $words[2] =~ /list$/
542 and
e82b9348 543 (
8962fc49 544 @words == 3
e82b9348 545 ||
8962fc49 546 @words == 4 && length($word)
e82b9348 547 )
548 ) {
549 return grep /^\Q$word\E/, qw(splice shift unshift pop push);
8962fc49 550 } elsif (defined($words[2])
551 and
552 $words[2] eq "init"
553 and
554 (
555 @words == 3
556 ||
26844e27 557 @words >= 4 && length($word)
8962fc49 558 )) {
559 return sort grep /^\Q$word\E/, keys %keys;
e82b9348 560 } elsif (@words >= 4) {
561 return ();
562 }
563 my %seen;
564 my(@o_conf) = sort grep { !$seen{$_}++ }
565 keys %can,
566 keys %$CPAN::Config,
567 keys %keys;
568 return grep /^\Q$word\E/, @o_conf;
569}
570
9ddc4ed0 571
4d1321a7 572package
573 CPAN::Config; ####::###### #hide from indexer
9ddc4ed0 574# note: J. Nick Koston wrote me that they are using
575# CPAN::Config->commit although undocumented. I suggested
576# CPAN::Shell->o("conf","commit") even when ugly it is at least
577# documented
578
579# that's why I added the CPAN::Config class with autoload and
580# deprecated warning
581
582use strict;
583use vars qw($AUTOLOAD $VERSION);
7d97ad34 584$VERSION = sprintf "%.2f", substr(q$Rev: 958 $,4)/100;
9ddc4ed0 585
586# formerly CPAN::HandleConfig was known as CPAN::Config
587sub AUTOLOAD {
588 my($l) = $AUTOLOAD;
589 $CPAN::Frontend->mywarn("Dispatching deprecated method '$l' to CPAN::HandleConfig");
590 $l =~ s/.*:://;
591 CPAN::HandleConfig->$l(@_);
592}
593
e82b9348 5941;
0cf35e6a 595
596__END__
26844e27 597
598=head1 LICENSE
599
600This program is free software; you can redistribute it and/or
601modify it under the same terms as Perl itself.
602
603=cut
604
0cf35e6a 605# Local Variables:
606# mode: cperl
ca79d794 607# cperl-indent-level: 4
0cf35e6a 608# End: