This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade to CPAN-1.88_62
[perl5.git] / lib / CPAN / FirstTime.pm
1 # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
2 package CPAN::Mirrored::By;
3 use strict;
4
5 sub new { 
6     my($self,@arg) = @_;
7     bless [@arg], $self;
8 }
9 sub continent { shift->[0] }
10 sub country { shift->[1] }
11 sub url { shift->[2] }
12
13 package CPAN::FirstTime;
14 use strict;
15
16 use ExtUtils::MakeMaker ();
17 use FileHandle ();
18 use File::Basename ();
19 use File::Path ();
20 use File::Spec ();
21 use vars qw($VERSION $urllist);
22 $VERSION = sprintf "%.6f", substr(q$Rev: 1257 $,4)/1000000 + 5.4;
23
24 =head1 NAME
25
26 CPAN::FirstTime - Utility for CPAN::Config file Initialization
27
28 =head1 SYNOPSIS
29
30 CPAN::FirstTime::init()
31
32 =head1 DESCRIPTION
33
34 The init routine asks a few questions and writes a CPAN/Config.pm or
35 CPAN/MyConfig.pm file (depending on what it is currently using).
36
37 =head1 LICENSE
38
39 This program is free software; you can redistribute it and/or
40 modify it under the same terms as Perl itself.
41
42 =cut
43
44 use vars qw( %prompts );
45
46 sub init {
47     my($configpm, %args) = @_;
48     use Config;
49     # extra args after 'o conf init'
50     my $matcher = $args{args} && @{$args{args}} ? $args{args}[0] : '';
51     if ($matcher =~ /^\/(.*)\/$/) {
52         # case /regex/ => take the first, ignore the rest
53         $matcher = $1;
54         shift @{$args{args}};
55         if (@{$args{args}}) {
56             local $" = " ";
57             $CPAN::Frontend->mywarn("Ignoring excessive arguments '@{$args{args}}'");
58             $CPAN::Frontend->mysleep(2);
59         }
60     } elsif (0 == length $matcher) {
61     } else {
62         # case WORD... => all arguments must be valid
63         for my $arg (@{$args{args}}) {
64             unless (exists $CPAN::HandleConfig::keys{$arg}) {
65                 $CPAN::Frontend->mywarn("'$arg' is not a valid configuration variable\n");
66                 return;
67             }
68         }
69         $matcher = "\\b(".join("|",@{$args{args}}).")\\b";
70     }
71     CPAN->debug("matcher[$matcher]") if $CPAN::DEBUG;
72
73     unless ($CPAN::VERSION) {
74         require CPAN::Nox;
75     }
76     require CPAN::HandleConfig;
77     CPAN::HandleConfig::require_myconfig_or_config();
78     $CPAN::Config ||= {};
79     local($/) = "\n";
80     local($\) = "";
81     local($|) = 1;
82
83     my($ans,$default);
84
85     #
86     #= Files, directories
87     #
88
89     unless ($matcher) {
90         $CPAN::Frontend->myprint($prompts{manual_config});
91     }
92
93     my $manual_conf;
94
95     local *_real_prompt;
96     if ( $args{autoconfig} ) {
97         $manual_conf = "no";
98     } elsif ($matcher) {
99         $manual_conf = "yes";
100     } else {
101         my $_conf = prompt("Would you like me to configure as much as possible ".
102                            "automatically?", "yes");
103         $manual_conf = ($_conf and $_conf =~ /^y/i) ? "no" : "yes";
104     }
105     CPAN->debug("manual_conf[$manual_conf]") if $CPAN::DEBUG;
106     my $fastread;
107     {
108       if ($manual_conf =~ /^y/i) {
109         $fastread = 0;
110       } else {
111         $fastread = 1;
112         $CPAN::Config->{urllist} ||= [];
113
114         local $^W = 0;
115         # prototype should match that of &MakeMaker::prompt
116         my $current_second = time;
117         my $current_second_count = 0;
118         my $i_am_mad = 0;
119         *_real_prompt = sub {
120           my($q,$a) = @_;
121           my($ret) = defined $a ? $a : "";
122           $CPAN::Frontend->myprint(sprintf qq{%s [%s]\n\n}, $q, $ret);
123           eval { require Time::HiRes };
124           unless ($@) {
125               if (time == $current_second) {
126                   $current_second_count++;
127                   if ($current_second_count > 20) {
128                       # I don't like more than 20 prompts per second
129                       $i_am_mad++;
130                   }
131               } else {
132                   $current_second = time;
133                   $current_second_count = 0;
134                   $i_am_mad-- if $i_am_mad>0;
135               }
136               if ($i_am_mad>0){
137                   #require Carp;
138                   #Carp::cluck("SLEEEEEEEEPIIIIIIIIIIINGGGGGGGGGGG");
139                   Time::HiRes::sleep(0.1);
140               }
141           }
142           $ret;
143         };
144       }
145     }
146
147     if (!$matcher or q{
148                        build_dir
149                        build_dir_reuse
150                        cpan_home
151                        keep_source_where
152                        prefs_dir
153                       } =~ /$matcher/){
154         $CPAN::Frontend->myprint($prompts{config_intro});
155
156         if (!$matcher or 'cpan_home' =~ /$matcher/) {
157             my $cpan_home = $CPAN::Config->{cpan_home}
158                 || File::Spec->catdir($ENV{HOME}, ".cpan");
159
160             if (-d $cpan_home) {
161                 $CPAN::Frontend->myprint(qq{
162
163 I see you already have a  directory
164     $cpan_home
165 Shall we use it as the general CPAN build and cache directory?
166
167 });
168             } else {
169                 # no cpan-home, must prompt and get one
170                 $CPAN::Frontend->myprint($prompts{cpan_home_where});
171             }
172
173             $default = $cpan_home;
174             my $loop = 0;
175             my $last_ans;
176           PROMPT: while ($ans = prompt("CPAN build and cache directory?",$default)) {
177                 if (File::Spec->file_name_is_absolute($ans)) {
178                     my @cpan_home = split /[\/\\]/, $ans;
179                   DIR: for my $dir (@cpan_home) {
180                         if ($dir =~ /^~/ and (!$last_ans or $ans ne $last_ans)) {
181                             $CPAN::Frontend
182                                 ->mywarn("Warning: a tilde in the path will be ".
183                                          "taken as a literal tilde. Please ".
184                                          "confirm again if you want to keep it\n");
185                             $last_ans = $default = $ans;
186                             next PROMPT;
187                         }
188                     }
189                 } else {
190                     require Cwd;
191                     my $cwd = Cwd::cwd();
192                     my $absans = File::Spec->catdir($cwd,$ans);
193                     $CPAN::Frontend->mywarn("The path '$ans' is not an ".
194                                             "absolute path. Please specify ".
195                                             "an absolute path\n");
196                     $default = $absans;
197                     next;
198                 }
199                 eval { File::Path::mkpath($ans); }; # dies if it can't
200                 if ($@) {
201                     $CPAN::Frontend->mywarn("Couldn't create directory $ans.\n".
202                                             "Please retry.\n");
203                     next;
204                 }
205                 if (-d $ans && -w _) {
206                     last;
207                 } else {
208                     $CPAN::Frontend->mywarn("Couldn't find directory $ans\n".
209                                             "or directory is not writable. Please retry.\n");
210                     if (++$loop > 5) {
211                         $CPAN::Frontend->mydie("Giving up");
212                     }
213                 }
214             }
215             $CPAN::Config->{cpan_home} = $ans;
216         }
217
218         if (!$matcher or 'keep_source_where' =~ /$matcher/) {
219             my_dflt_prompt("keep_source_where",
220                            File::Spec->catdir($CPAN::Config->{cpan_home},"sources"),
221                            $matcher,
222                           );
223         }
224
225         if (!$matcher or 'build_dir' =~ /$matcher/) {
226             my_dflt_prompt("build_dir",
227                            File::Spec->catdir($CPAN::Config->{cpan_home},"build"),
228                            $matcher
229                           );
230         }
231
232         if (!$matcher or 'build_dir_reuse' =~ /$matcher/) {
233             my_yn_prompt(build_dir_reuse => "y", $matcher);
234         }
235
236         if (!$matcher or 'prefs_dir' =~ /$matcher/) {
237             my_dflt_prompt("prefs_dir",
238                            File::Spec->catdir($CPAN::Config->{cpan_home},"prefs"),
239                            $matcher
240                           );
241         }
242     }
243
244     #
245     #= Cache size, Index expire
246     #
247
248     if (!$matcher or 'build_cache' =~ /$matcher/){
249         # large enough to build large dists like Tk
250         my_dflt_prompt(build_cache => 100, $matcher);
251     }
252
253     if (!$matcher or 'index_expire' =~ /$matcher/) {
254         my_dflt_prompt(index_expire => 1, $matcher);
255     }
256
257     if (!$matcher or 'scan_cache' =~ /$matcher/){
258         $CPAN::Frontend->myprint($prompts{scan_cache_intro});
259         my_prompt_loop(scan_cache => 'atstart', $matcher, 'atstart|never');
260     }
261
262     #
263     #= cache_metadata
264     #
265
266     my_yn_prompt(cache_metadata => 1, $matcher);
267
268     #
269     #= Do we follow PREREQ_PM?
270     #
271
272     if (!$matcher or 'prerequisites_policy' =~ /$matcher/){
273         $CPAN::Frontend->myprint($prompts{prerequisites_policy_intro});
274
275         my_prompt_loop(prerequisites_policy => 'ask', $matcher,
276                        'follow|ask|ignore');
277     }
278
279     if (!$matcher or 'build_requires_install_policy' =~ /$matcher/){
280         $CPAN::Frontend->myprint($prompts{build_requires_install_policy_intro});
281
282         my_prompt_loop(build_requires_install_policy => 'ask/yes', $matcher,
283                        'yes|no|ask/yes|ask/no');
284     }
285
286     #
287     #= Module::Signature
288     #
289     if (!$matcher or 'check_sigs' =~ /$matcher/) {
290         my_yn_prompt(check_sigs => 0, $matcher);
291     }
292
293     #
294     #= CPAN::Reporter
295     #
296     if (!$matcher or 'test_report' =~ /$matcher/) {
297         my_yn_prompt(test_report => 0, $matcher);
298         if (
299             $CPAN::Config->{test_report} && 
300             $CPAN::META->has_inst("CPAN::Reporter") &&
301             CPAN::Reporter->can('configure')
302            ) {
303             $CPAN::Frontend->myprint("\nProceeding to configure CPAN::Reporter.\n");
304             CPAN::Reporter::configure();
305             $CPAN::Frontend->myprint("\nReturning to CPAN configuration.\n");
306         }
307     }
308
309     #
310     #= YAML vs. YAML::Syck
311     #
312     if (!$matcher or "yaml_module" =~ /$matcher/) {
313         my_dflt_prompt(yaml_module => "YAML", $matcher);
314     }
315
316     #
317     #= External programs
318     #
319
320     my @external_progs = qw/bzip2 gzip tar unzip make
321                       curl lynx wget ncftpget ncftp ftp
322                       gpg patch/;
323     my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
324     if (!$matcher or "@external_progs" =~ /$matcher/) {
325         $CPAN::Frontend->myprint($prompts{external_progs});
326
327         my $old_warn = $^W;
328         local $^W if $^O eq 'MacOS';
329         local $^W = $old_warn;
330         my $progname;
331         for $progname (@external_progs) {
332             next if $matcher && $progname !~ /$matcher/;
333             if ($^O eq 'MacOS') {
334                 $CPAN::Config->{$progname} = 'not_here';
335                 next;
336             }
337
338             my $progcall = $progname;
339             unless ($matcher) {
340                 # we really don't need ncftp if we have ncftpget, but
341                 # if they chose this dialog via matcher, they shall have it
342                 next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
343             }
344             my $path = $CPAN::Config->{$progname}
345                 || $Config::Config{$progname}
346                     || "";
347             if (File::Spec->file_name_is_absolute($path)) {
348                 # testing existence is not good enough, some have these exe
349                 # extensions
350
351                 # warn "Warning: configured $path does not exist\n" unless -e $path;
352                 # $path = "";
353             } elsif ($path =~ /^\s+$/) {
354                 # preserve disabled programs
355             } else {
356                 $path = '';
357             }
358             unless ($path) {
359                 # e.g. make -> nmake
360                 $progcall = $Config::Config{$progname} if $Config::Config{$progname};
361             }
362
363             $path ||= find_exe($progcall,\@path);
364             {
365                 local $"=";";
366                 $CPAN::Frontend->mywarn("Warning: $progcall not found in PATH[@path]\n") unless
367                     $path; # not -e $path, because find_exe already checked that
368             }
369             $ans = prompt("Where is your $progname program?",$path) || $path;
370             $CPAN::Config->{$progname} = $ans;
371         }
372     }
373
374     if (!$matcher or 'pager' =~ /$matcher/) {
375         my $path = $CPAN::Config->{'pager'} || 
376             $ENV{PAGER} || find_exe("less",\@path) || 
377                 find_exe("more",\@path) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 )
378                     || "more";
379         $ans = prompt("What is your favorite pager program?",$path);
380         $CPAN::Config->{'pager'} = $ans;
381     }
382
383     if (!$matcher or 'shell' =~ /$matcher/) {
384         my $path = $CPAN::Config->{'shell'};
385         if ($path && File::Spec->file_name_is_absolute($path)) {
386             $CPAN::Frontend->mywarn("Warning: configured $path does not exist\n")
387                 unless -e $path;
388             $path = "";
389         }
390         $path ||= $ENV{SHELL};
391         $path ||= $ENV{COMSPEC} if $^O eq "MSWin32";
392         if ($^O eq 'MacOS') {
393             $CPAN::Config->{'shell'} = 'not_here';
394         } else {
395             $path =~ s,\\,/,g if $^O eq 'os2';  # Cosmetic only
396             $ans = prompt("What is your favorite shell?",$path);
397             $CPAN::Config->{'shell'} = $ans;
398         }
399     }
400
401     #
402     #= Installer, arguments to make etc.
403     #
404
405     if (!$matcher or 'prefer_installer' =~ /$matcher/){
406         $CPAN::Frontend->myprint($prompts{prefer_installer_intro});
407
408         my_prompt_loop(prefer_installer => 'EUMM', $matcher, 'MB|EUMM');
409     }
410
411     if (!$matcher or 'makepl_arg make_arg' =~ /$matcher/){
412         my_dflt_prompt(makepl_arg => "", $matcher);
413         my_dflt_prompt(make_arg => "", $matcher);
414     }
415
416     require CPAN::HandleConfig;
417     if (exists $CPAN::HandleConfig::keys{make_install_make_command}) {
418         # as long as Windows needs $self->_build_command, we cannot
419         # support sudo on windows :-)
420         my_dflt_prompt(make_install_make_command => $CPAN::Config->{make} || "",
421                        $matcher);
422     }
423
424     my_dflt_prompt(make_install_arg => $CPAN::Config->{make_arg} || "", 
425                    $matcher);
426
427     if (!$matcher or 'mbuildpl_arg mbuild_arg' =~ /$matcher/){
428         my_dflt_prompt(mbuildpl_arg => "", $matcher);
429         my_dflt_prompt(mbuild_arg => "", $matcher);
430     }
431
432     if (exists $CPAN::HandleConfig::keys{mbuild_install_build_command}) {
433         # as long as Windows needs $self->_build_command, we cannot
434         # support sudo on windows :-)
435         my_dflt_prompt(mbuild_install_build_command => "./Build", $matcher);
436     }
437
438     my_dflt_prompt(mbuild_install_arg => "", $matcher);
439
440     #
441     #= Alarm period
442     #
443
444     if (!$matcher or 'inactivity_timeout' =~ /$matcher/) {
445         $CPAN::Frontend->myprint($prompts{inactivity_timeout_intro});
446         $default = $CPAN::Config->{inactivity_timeout} || 0;
447         $CPAN::Config->{inactivity_timeout} =
448             prompt("Timeout for inactivity during {Makefile,Build}.PL?",$default);
449     }
450
451     #
452     #= Proxies
453     #
454
455     my @proxy_vars = qw/ftp_proxy http_proxy no_proxy/;
456     my @proxy_user_vars = qw/proxy_user proxy_pass/;
457     if (!$matcher or "@proxy_vars @proxy_user_vars" =~ /$matcher/){
458         $CPAN::Frontend->myprint($prompts{proxy_intro});
459
460         for (@proxy_vars) {
461             if (!$matcher or /$matcher/){
462                 $default = $CPAN::Config->{$_} || $ENV{$_} || "";
463                 $CPAN::Config->{$_} = prompt("Your $_?",$default);
464             }
465         }
466
467         if ($CPAN::Config->{ftp_proxy} ||
468             $CPAN::Config->{http_proxy}) {
469
470             $default = $CPAN::Config->{proxy_user} || $CPAN::LWP::UserAgent::USER || "";
471
472             $CPAN::Frontend->myprint($prompts{proxy_user});
473
474             if ($CPAN::Config->{proxy_user} = prompt("Your proxy user id?",$default)) {
475                 $CPAN::Frontend->myprint($prompts{proxy_pass});
476
477                 if ($CPAN::META->has_inst("Term::ReadKey")) {
478                     Term::ReadKey::ReadMode("noecho");
479                 } else {
480                     $CPAN::Frontend->myprint($prompts{password_warn});
481                 }
482                 $CPAN::Config->{proxy_pass} = prompt_no_strip("Your proxy password?");
483                 if ($CPAN::META->has_inst("Term::ReadKey")) {
484                     Term::ReadKey::ReadMode("restore");
485                 }
486                 $CPAN::Frontend->myprint("\n\n");
487             }
488         }
489     }
490
491     #
492     #= how FTP works
493     #
494
495     my_yn_prompt(ftp_passive => 1, $matcher);
496
497     #
498     #= how cwd works
499     #
500
501     if (!$matcher or 'getcwd' =~ /$matcher/){
502         $CPAN::Frontend->myprint($prompts{getcwd_intro});
503
504         my_prompt_loop(getcwd => 'cwd', $matcher,
505                        'cwd|getcwd|fastcwd|backtickcwd');
506     }
507
508     #
509     #= the CPAN shell itself
510     #
511
512     my_yn_prompt(commandnumber_in_prompt => 1, $matcher);
513     my_yn_prompt(term_ornaments => 1, $matcher);
514     if ("colorize_output colorize_print colorize_warn" =~ $matcher) {
515         my_yn_prompt(colorize_output => 0, $matcher);
516         if ($CPAN::Config->{colorize_output}) {
517             for my $tuple (
518                            ["colorize_print", "bold blue on_white"],
519                            ["colorize_warn", "bold red on_white"],
520                           ) {
521                 my_dflt_prompt($tuple->[0] => $tuple->[1], $matcher);
522                 if ($CPAN::META->has_inst("Term::ANSIColor")) {
523                     eval { Term::ANSIColor::color($CPAN::Config->{$tuple->[0]})};
524                     if ($@) {
525                         $CPAN::Config->{$tuple->[0]} = $tuple->[1];
526                         $CPAN::Frontend->mywarn($@."setting to default '$tuple->[1]'\n");
527                     }
528                 }
529             }
530         }
531     }
532
533     #
534     #== term_is_latin
535     #
536
537     if (!$matcher or 'term_is_latin' =~ /$matcher/){
538         $CPAN::Frontend->myprint($prompts{term_is_latin});
539         my_yn_prompt(term_is_latin => 1, $matcher);
540     }
541
542     #
543     #== save history in file 'histfile'
544     #
545
546     if (!$matcher or 'histfile histsize' =~ /$matcher/) {
547         $CPAN::Frontend->myprint($prompts{histfile_intro});
548         defined($default = $CPAN::Config->{histfile}) or
549             $default = File::Spec->catfile($CPAN::Config->{cpan_home},"histfile");
550         $ans = prompt("File to save your history?", $default);
551         $CPAN::Config->{histfile} = $ans;
552
553         if ($CPAN::Config->{histfile}) {
554             defined($default = $CPAN::Config->{histsize}) or $default = 100;
555             $ans = prompt("Number of lines to save?", $default);
556             $CPAN::Config->{histsize} = $ans;
557         }
558     }
559
560     #
561     #== do an ls on the m or the d command
562     #
563     if (!$matcher or 'show_upload_date' =~ /$matcher/) {
564         $CPAN::Frontend->myprint($prompts{show_upload_date_intro});
565
566         defined($default = $CPAN::Config->{show_upload_date}) or
567             $default = 'n';
568         $ans = prompt("Always try to show upload date with 'd' and 'm' command (yes/no)?",
569                       ($default ? 'yes' : 'no'));
570         $CPAN::Config->{show_upload_date} = ($ans =~ /^[y1]/i ? 1 : 0);
571     }
572
573     #
574     #= MIRRORED.BY and conf_sites()
575     #
576
577     if ($matcher){
578         if ("urllist" =~ $matcher) {
579             # conf_sites would go into endless loop with the smash prompt
580             local *_real_prompt;
581             *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt;
582             conf_sites();
583         }
584         if ("randomize_urllist" =~ $matcher) {
585             my_dflt_prompt(randomize_urllist => 0, $matcher);
586         }
587     } elsif ($fastread) {
588         $CPAN::Frontend->myprint("Autoconfigured everything but 'urllist'.\n".
589                                  "Please call 'o conf init urllist' to configure ".
590                                  "your CPAN server(s) now!");
591     } else {
592         conf_sites();
593     }
594
595     # We don't ask this one now, it's plain silly and maybe is not
596     # even used correctly everywhere.
597     $CPAN::Config->{inhibit_startup_message} = 0;
598
599     $CPAN::Frontend->myprint("\n\n");
600     if ($matcher) {
601         $CPAN::Frontend->myprint("Please remember to call 'o conf commit' to ".
602                                  "make the config permanent!\n\n");
603     } else {
604         CPAN::HandleConfig->commit($configpm);
605     }
606 }
607
608 sub my_dflt_prompt {
609     my ($item, $dflt, $m) = @_;
610     my $default = $CPAN::Config->{$item} || $dflt;
611
612     $DB::single = 1;
613     if (!$m || $item =~ /$m/) {
614         if (my $intro = $prompts{$item . "_intro"}) {
615             $CPAN::Frontend->myprint($intro);
616         }
617         $CPAN::Config->{$item} = prompt($prompts{$item}, $default);
618     } else {
619         $CPAN::Config->{$item} = $default;
620     }
621 }
622
623 sub my_yn_prompt {
624     my ($item, $dflt, $m) = @_;
625     my $default;
626     defined($default = $CPAN::Config->{$item}) or $default = $dflt;
627
628     $DB::single = 1;
629     if (!$m || $item =~ /$m/) {
630         if (my $intro = $prompts{$item . "_intro"}) {
631             $CPAN::Frontend->myprint($intro);
632         }
633         my $ans = prompt($prompts{$item}, $default ? 'yes' : 'no');
634         $CPAN::Config->{$item} = ($ans =~ /^[y1]/i ? 1 : 0);
635     } else {
636         $CPAN::Config->{$item} = $default;
637     }
638 }
639
640 sub my_prompt_loop {
641     my ($item, $dflt, $m, $ok) = @_;
642     my $default = $CPAN::Config->{$item} || $dflt;
643     my $ans;
644
645     $DB::single = 1;
646     if (!$m || $item =~ /$m/) {
647         do { $ans = prompt($prompts{$item}, $default);
648         } until $ans =~ /$ok/;
649         $CPAN::Config->{$item} = $ans;
650     } else {
651         $CPAN::Config->{$item} = $default;
652     }
653 }
654
655
656 sub conf_sites {
657   my $m = 'MIRRORED.BY';
658   my $mby = File::Spec->catfile($CPAN::Config->{keep_source_where},$m);
659   File::Path::mkpath(File::Basename::dirname($mby));
660   if (-f $mby && -f $m && -M $m < -M $mby) {
661     require File::Copy;
662     File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
663   }
664   my $loopcount = 0;
665   local $^T = time;
666   my $overwrite_local = 0;
667   if ($mby && -f $mby && -M _ <= 60 && -s _ > 0) {
668       my $mtime = localtime((stat _)[9]);
669       my $prompt = qq{Found $mby as of $mtime
670
671 I\'d use that as a database of CPAN sites. If that is OK for you,
672 please answer 'y', but if you want me to get a new database now,
673 please answer 'n' to the following question.
674
675 Shall I use the local database in $mby?};
676       my $ans = prompt($prompt,"y");
677       $overwrite_local = 1 unless $ans =~ /^y/i;
678   }
679   while ($mby) {
680     if ($overwrite_local) {
681       $CPAN::Frontend->myprint(qq{Trying to overwrite $mby\n});
682       $mby = CPAN::FTP->localize($m,$mby,3);
683       $overwrite_local = 0;
684     } elsif ( ! -f $mby ){
685       $CPAN::Frontend->myprint(qq{You have no $mby\n  I\'m trying to fetch one\n});
686       $mby = CPAN::FTP->localize($m,$mby,3);
687     } elsif (-M $mby > 60 && $loopcount == 0) {
688         $CPAN::Frontend->myprint(qq{Your $mby is older than 60 days,\n  I\'m trying }.
689                                  qq{to fetch one\n});
690         $mby = CPAN::FTP->localize($m,$mby,3);
691         $loopcount++;
692     } elsif (-s $mby == 0) {
693       $CPAN::Frontend->myprint(qq{You have an empty $mby,\n  I\'m trying to fetch one\n});
694       $mby = CPAN::FTP->localize($m,$mby,3);
695     } else {
696       last;
697     }
698   }
699   local $urllist = [];
700   read_mirrored_by($mby);
701   bring_your_own();
702   $CPAN::Config->{urllist} = $urllist;
703 }
704
705 sub find_exe {
706     my($exe,$path) = @_;
707     my($dir);
708     #warn "in find_exe exe[$exe] path[@$path]";
709     for $dir (@$path) {
710         my $abs = File::Spec->catfile($dir,$exe);
711         if (($abs = MM->maybe_command($abs))) {
712             return $abs;
713         }
714     }
715 }
716
717 sub picklist {
718     my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
719     CPAN->debug("picklist('$items','$prompt','$default','$require_nonempty',".
720                 "'$empty_warning')") if $CPAN::DEBUG;
721     $default ||= '';
722
723     my $pos = 0;
724
725     my @nums;
726   SELECTION: while (1) {
727
728         # display, at most, 15 items at a time
729         my $limit = $#{ $items } - $pos;
730         $limit = 15 if $limit > 15;
731
732         # show the next $limit items, get the new position
733         $pos = display_some($items, $limit, $pos, $default);
734         $pos = 0 if $pos >= @$items;
735
736         my $num = prompt($prompt,$default);
737
738         @nums = split (' ', $num);
739         {
740             my %seen;
741             @nums = grep { !$seen{$_}++ } @nums;
742         }
743         my $i = scalar @$items;
744         unrangify(\@nums);
745         if (grep (/\D/ || $_ < 1 || $_ > $i, @nums)){
746             $CPAN::Frontend->mywarn("invalid items entered, try again\n");
747             if ("@nums" =~ /\D/) {
748                 $CPAN::Frontend->mywarn("(we are expecting only numbers between 1 and $i)\n");
749             }
750             next SELECTION;
751         }
752         if ($require_nonempty && !@nums) {
753             $CPAN::Frontend->mywarn("$empty_warning\n");
754         }
755         $CPAN::Frontend->myprint("\n");
756
757         # a blank line continues...
758         next SELECTION unless @nums;
759         last;
760     }
761     for (@nums) { $_-- }
762     @{$items}[@nums];
763 }
764
765 sub unrangify ($) {
766     my($nums) = $_[0];
767     my @nums2 = ();
768     while (@{$nums||[]}) {
769         my $n = shift @$nums;
770         if ($n =~ /^(\d+)-(\d+)$/) {
771             my @range = $1 .. $2;
772             # warn "range[@range]";
773             push @nums2, @range;
774         } else {
775             push @nums2, $n;
776         }
777     }
778     push @$nums, @nums2;
779 }
780
781 sub display_some {
782     my ($items, $limit, $pos, $default) = @_;
783     $pos ||= 0;
784
785     my @displayable = @$items[$pos .. ($pos + $limit)];
786     for my $item (@displayable) {
787         $CPAN::Frontend->myprint(sprintf "(%d) %s\n", ++$pos, $item);
788     }
789     my $hit_what = $default ? "SPACE RETURN" : "RETURN";
790     $CPAN::Frontend->myprint(sprintf("%d more items, hit %s to show them\n",
791                                      (@$items - $pos),
792                                      $hit_what,
793                                     ))
794         if $pos < @$items;
795     return $pos;
796 }
797
798 sub read_mirrored_by {
799     my $local = shift or return;
800     my(%all,$url,$expected_size,$default,$ans,$host,
801        $dst,$country,$continent,@location);
802     my $fh = FileHandle->new;
803     $fh->open($local) or die "Couldn't open $local: $!";
804     local $/ = "\012";
805     while (<$fh>) {
806         ($host) = /^([\w\.\-]+)/ unless defined $host;
807         next unless defined $host;
808         next unless /\s+dst_(dst|location)/;
809         /location\s+=\s+\"([^\"]+)/ and @location = (split /\s*,\s*/, $1) and
810             ($continent, $country) = @location[-1,-2];
811         $continent =~ s/\s\(.*//;
812         $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
813         /dst_dst\s+=\s+\"([^\"]+)/  and $dst = $1;
814         next unless $host && $dst && $continent && $country;
815         $all{$continent}{$country}{$dst} = CPAN::Mirrored::By->new($continent,$country,$dst);
816         undef $host;
817         $dst=$continent=$country="";
818     }
819     $fh->close;
820     $CPAN::Config->{urllist} ||= [];
821     my @previous_urls = @{$CPAN::Config->{urllist}};
822
823     $CPAN::Frontend->myprint($prompts{urls_intro});
824
825     my (@cont, $cont, %cont, @countries, @urls, %seen);
826     my $no_previous_warn =
827         "Sorry! since you don't have any existing picks, you must make a\n" .
828             "geographic selection.";
829     my $offer_cont = [sort keys %all];
830     if (@previous_urls) {
831         push @$offer_cont, "(edit previous picks)";
832         $default = @$offer_cont;
833     }
834     @cont = picklist($offer_cont,
835                      "Select your continent (or several nearby continents)",
836                      $default,
837                      ! @previous_urls,
838                      $no_previous_warn);
839
840
841     foreach $cont (@cont) {
842         my @c = sort keys %{$all{$cont}};
843         @cont{@c} = map ($cont, 0..$#c);
844         @c = map ("$_ ($cont)", @c) if @cont > 1;
845         push (@countries, @c);
846     }
847     if (@previous_urls && @countries) {
848         push @countries, "(edit previous picks)";
849         $default = @countries;
850     }
851
852     if (@countries) {
853         @countries = picklist (\@countries,
854                                "Select your country (or several nearby countries)",
855                                $default,
856                                ! @previous_urls,
857                                $no_previous_warn);
858         %seen = map (($_ => 1), @previous_urls);
859         # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
860         foreach $country (@countries) {
861             next if $country =~ /edit previous picks/;
862             (my $bare_country = $country) =~ s/ \(.*\)//;
863             my @u = sort keys %{$all{$cont{$bare_country}}{$bare_country}};
864             @u = grep (! $seen{$_}, @u);
865             @u = map ("$_ ($bare_country)", @u)
866                 if @countries > 1;
867             push (@urls, @u);
868         }
869     }
870     push (@urls, map ("$_ (previous pick)", @previous_urls));
871     my $prompt = "Select as many URLs as you like (by number),
872 put them on one line, separated by blanks, hyphenated ranges allowed
873  e.g. '1 4 5' or '7 1-4 8'";
874     if (@previous_urls) {
875         $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
876                          (scalar @urls));
877         $prompt .= "\n(or just hit RETURN to keep your previous picks)";
878     }
879
880     @urls = picklist (\@urls, $prompt, $default);
881     foreach (@urls) { s/ \(.*\)//; }
882     push @$urllist, @urls;
883 }
884
885 sub bring_your_own {
886     my %seen = map (($_ => 1), @$urllist);
887     my($ans,@urls);
888     my $eacnt = 0; # empty answers
889     do {
890         my $prompt = "Enter another URL or RETURN to quit:";
891         unless (%seen) {
892             $prompt = qq{CPAN.pm needs at least one URL where it can fetch CPAN files from.
893
894 Please enter your CPAN site:};
895         }
896         $ans = prompt ($prompt, "");
897
898         if ($ans) {
899             $ans =~ s|/?\z|/|; # has to end with one slash
900             $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
901             if ($ans =~ /^\w+:\/./) {
902                 push @urls, $ans unless $seen{$ans}++;
903             } else {
904                 $CPAN::Frontend->
905                     myprint(sprintf(qq{"%s" doesn\'t look like an URL at first sight.
906 I\'ll ignore it for now.
907 You can add it to your %s
908 later if you\'re sure it\'s right.\n},
909                                    $ans,
910                                    $INC{'CPAN/MyConfig.pm'}
911                                    || $INC{'CPAN/Config.pm'}
912                                    || "configuration file",
913                                   ));
914             }
915         } else {
916             if (++$eacnt >= 5) {
917                 $CPAN::Frontend->
918                     mywarn("Giving up.\n");
919                 $CPAN::Frontend->mysleep(5);
920                 return;
921             }
922         }
923     } while $ans || !%seen;
924
925     push @$urllist, @urls;
926     # xxx delete or comment these out when you're happy that it works
927     $CPAN::Frontend->myprint("New set of picks:\n");
928     map { $CPAN::Frontend->myprint("  $_\n") } @$urllist;
929 }
930
931
932 sub _strip_spaces {
933     $_[0] =~ s/^\s+//;  # no leading spaces
934     $_[0] =~ s/\s+\z//; # no trailing spaces
935 }
936
937 sub prompt ($;$) {
938     unless (defined &_real_prompt) {
939         *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt;
940     }
941     my $ans = _real_prompt(@_);
942
943     _strip_spaces($ans);
944
945     return $ans;
946 }
947
948
949 sub prompt_no_strip ($;$) {
950     return _real_prompt(@_);
951 }
952
953
954 BEGIN {
955
956 my @prompts = (
957
958 manual_config => qq[
959
960 CPAN is the world-wide archive of perl resources. It consists of about
961 300 sites that all replicate the same contents around the globe. Many
962 countries have at least one CPAN site already. The resources found on
963 CPAN are easily accessible with the CPAN.pm module. If you want to use
964 CPAN.pm, lots of things have to be configured. Fortunately, most of
965 them can be determined automatically. If you prefer the automatic
966 configuration, answer 'yes' below.
967
968 If you prefer to enter a dialog instead, you can answer 'no' to this
969 question and I'll let you configure in small steps one thing after the
970 other. (Note: you can revisit this dialog anytime later by typing 'o
971 conf init' at the cpan prompt.)
972
973 ],
974
975 config_intro => qq{
976
977 The following questions are intended to help you with the
978 configuration. The CPAN module needs a directory of its own to cache
979 important index files and maybe keep a temporary mirror of CPAN files.
980 This may be a site-wide or a personal directory.
981
982 },
983
984 # cpan_home => qq{ },
985
986 cpan_home_where => qq{
987
988 First of all, I\'d like to create this directory. Where?
989
990 },
991
992 keep_source_where => qq{
993
994 Unless you are accessing the CPAN via the filesystem directly CPAN.pm
995 needs to keep the source files it downloads somewhere. Please supply a
996 directory where the downloaded files are to be kept.},
997
998 build_cache_intro => qq{
999
1000 How big should the disk cache be for keeping the build directories
1001 with all the intermediate files\?
1002
1003 },
1004
1005 build_cache =>
1006 "Cache size for build directory (in MB)?",
1007
1008 build_dir =>
1009
1010 "Directory where the build process takes place?",
1011
1012 build_dir_reuse_intro =>
1013
1014 qq{Until version 1.88 CPAN.pm never trusted the contents of the
1015 build_dir directory between sessions. Since 1.88_58 CPAN.pm has a
1016 YAML-based mechanism that makes it possible to share the contents of
1017 the build_dir/ directory between different sessions with the same
1018 version of perl. People who prefer to test things several days before
1019 installing will like this feature because it safes a lot of time.
1020
1021 If you say yes to the following question, CPAN will try to store
1022 enough information about the build process so that it can pick up in
1023 future sessions at the same state of affairs as it left a previous
1024 session.
1025
1026 },
1027
1028 build_dir_reuse =>
1029
1030 qq{Store and re-use state information about distributions between
1031 CPAN.pm sessions?},
1032
1033 prefs_dir_intro => qq{
1034
1035 CPAN.pm can store customized build environments based on regular
1036 expressions for distribution names. These are YAML files where the
1037 default options for CPAN.pm and the environment can be overridden and
1038 dialog sequences can be stored that can later be executed by an
1039 Expect.pm object. The CPAN.pm distribution comes with some prefab YAML
1040 files that cover sample distributions that can be used as blueprints
1041 to store one own prefs. Please check out the distroprefs/ directory of
1042 the CPAN.pm distribution to get a quick start into the prefs system.
1043
1044 },
1045
1046 prefs_dir =>
1047
1048 "Directory where to store default options/environment/dialogs for
1049 building modules that need some customization?",
1050
1051 scan_cache_intro => qq{
1052
1053 By default, each time the CPAN module is started, cache scanning is
1054 performed to keep the cache size in sync. To prevent this, answer
1055 'never'.
1056
1057 },
1058
1059 scan_cache => "Perform cache scanning (atstart or never)?",
1060
1061 cache_metadata_intro => qq{
1062
1063 To considerably speed up the initial CPAN shell startup, it is
1064 possible to use Storable to create a cache of metadata. If Storable
1065 is not available, the normal index mechanism will be used.
1066
1067 },
1068
1069 cache_metadata => qq{Cache metadata (yes/no)?},
1070
1071 term_is_latin_intro => qq{
1072
1073 The next option deals with the charset (aka character set) your
1074 terminal supports. In general, CPAN is English speaking territory, so
1075 the charset does not matter much, but some of the aliens out there who
1076 upload their software to CPAN bear names that are outside the ASCII
1077 range. If your terminal supports UTF-8, you should say no to the next
1078 question.  If it supports ISO-8859-1 (also known as LATIN1) then you
1079 should say yes.  If it supports neither, your answer does not matter
1080 because you will not be able to read the names of some authors
1081 anyway. If you answer no, names will be output in UTF-8.
1082
1083 },
1084
1085 term_is_latin => qq{Your terminal expects ISO-8859-1 (yes/no)?},
1086
1087 histfile_intro => qq{
1088
1089 If you have one of the readline packages (Term::ReadLine::Perl,
1090 Term::ReadLine::Gnu, possibly others) installed, the interactive CPAN
1091 shell will have history support. The next two questions deal with the
1092 filename of the history file and with its size. If you do not want to
1093 set this variable, please hit SPACE RETURN to the following question.
1094
1095 },
1096
1097 histfile => qq{File to save your history?},
1098
1099 show_upload_date_intro => qq{
1100
1101 The 'd' and the 'm' command normally only show you information they
1102 have in their in-memory database and thus will never connect to the
1103 internet. If you set the 'show_upload_date' variable to true, 'm' and
1104 'd' will additionally show you the upload date of the module or
1105 distribution. Per default this feature is off because it may require a
1106 net connection to get at the upload date.
1107
1108 },
1109
1110 show_upload_date =>
1111 "Always try to show upload date with 'd' and 'm' command (yes/no)?",
1112
1113 prerequisites_policy_intro => qq{
1114
1115 The CPAN module can detect when a module which you are trying to build
1116 depends on prerequisites. If this happens, it can build the
1117 prerequisites for you automatically ('follow'), ask you for
1118 confirmation ('ask'), or just ignore them ('ignore'). Please set your
1119 policy to one of the three values.
1120
1121 },
1122
1123 prerequisites_policy =>
1124 "Policy on building prerequisites (follow, ask or ignore)?",
1125
1126 check_sigs_intro  => qq{
1127
1128 CPAN packages can be digitally signed by authors and thus verified
1129 with the security provided by strong cryptography. The exact mechanism
1130 is defined in the Module::Signature module. While this is generally
1131 considered a good thing, it is not always convenient to the end user
1132 to install modules that are signed incorrectly or where the key of the
1133 author is not available or where some prerequisite for
1134 Module::Signature has a bug and so on.
1135
1136 With the check_sigs parameter you can turn signature checking on and
1137 off. The default is off for now because the whole tool chain for the
1138 functionality is not yet considered mature by some. The author of
1139 CPAN.pm would recommend setting it to true most of the time and
1140 turning it off only if it turns out to be annoying.
1141
1142 Note that if you do not have Module::Signature installed, no signature
1143 checks will be performed at all.
1144
1145 },
1146
1147 check_sigs =>
1148 qq{Always try to check and verify signatures if a SIGNATURE file is in the package
1149 and Module::Signature is installed (yes/no)?},
1150
1151 test_report_intro =>
1152 qq{
1153
1154 The goal of the CPAN Testers project (http://testers.cpan.org/) is to
1155 test as many CPAN packages as possible on as many platforms as
1156 possible.  This provides valuable feedback to module authors and
1157 potential users to identify bugs or platform compatibility issues and
1158 improves the overall quality and value of CPAN.
1159
1160 One way you can contribute is to send test results for each module
1161 that you install.  If you install the CPAN::Reporter module, you have
1162 the option to automatically generate and email test reports to CPAN
1163 Testers whenever you run tests on a CPAN package.
1164
1165 See the CPAN::Reporter documentation for additional details and
1166 configuration settings.  If your firewall blocks outgoing email,
1167 you will need to configure CPAN::Reporter before sending reports.
1168
1169 },
1170
1171 test_report =>
1172 qq{Email test reports if CPAN::Reporter is installed (yes/no)?},
1173
1174 external_progs => qq{
1175
1176 The CPAN module will need a few external programs to work properly.
1177 Please correct me, if I guess the wrong path for a program. Don\'t
1178 panic if you do not have some of them, just press ENTER for those. To
1179 disable the use of a program, you can type a space followed by ENTER.
1180
1181 },
1182
1183 prefer_installer_intro => qq{
1184
1185 When you have Module::Build installed and a module comes with both a
1186 Makefile.PL and a Build.PL, which shall have precedence? The two
1187 installer modules we have are the old and well established
1188 ExtUtils::MakeMaker (for short: EUMM) which uses the Makefile.PL and
1189 the next generation installer Module::Build (MB) works with the
1190 Build.PL.
1191
1192 },
1193
1194 prefer_installer =>
1195 qq{In case you could choose, which installer would you prefer (EUMM or MB)?},
1196
1197 makepl_arg_intro => qq{
1198
1199 Every Makefile.PL is run by perl in a separate process. Likewise we
1200 run \'make\' and \'make install\' in separate processes. If you have
1201 any parameters \(e.g. PREFIX, LIB, UNINST or the like\) you want to
1202 pass to the calls, please specify them here.
1203
1204 If you don\'t understand this question, just press ENTER.
1205 },
1206
1207 makepl_arg => qq{
1208 Parameters for the 'perl Makefile.PL' command?
1209 Typical frequently used settings:
1210
1211     PREFIX=~/perl    # non-root users (please see manual for more hints)
1212
1213 Your choice: },
1214
1215 make_arg => qq{Parameters for the 'make' command?
1216 Typical frequently used setting:
1217
1218     -j3              # dual processor system
1219
1220 Your choice: },
1221
1222
1223 make_install_make_command => qq{Do you want to use a different make command for 'make install'?
1224 Cautious people will probably prefer:
1225
1226     su root -c make
1227 or
1228     sudo make
1229 or
1230     /path1/to/sudo -u admin_account /path2/to/make
1231
1232 or some such. Your choice: },
1233
1234
1235 make_install_arg => qq{Parameters for the 'make install' command?
1236 Typical frequently used setting:
1237
1238     UNINST=1         # to always uninstall potentially conflicting files
1239
1240 Your choice: },
1241
1242
1243 mbuildpl_arg_intro => qq{
1244
1245 The next questions deal with Module::Build support.
1246
1247 A Build.PL is run by perl in a separate process. Likewise we run
1248 './Build' and './Build install' in separate processes. If you have any
1249 parameters you want to pass to the calls, please specify them here.
1250
1251 },
1252
1253 mbuildpl_arg => qq{Parameters for the 'perl Build.PL' command?
1254 Typical frequently used settings:
1255
1256     --install_base /home/xxx             # different installation directory
1257
1258 Your choice: },
1259
1260 mbuild_arg => qq{Parameters for the './Build' command?
1261 Setting might be:
1262
1263     --extra_linker_flags -L/usr/foo/lib  # non-standard library location
1264
1265 Your choice: },
1266
1267
1268 mbuild_install_build_command => qq{Do you want to use a different command for './Build install'?
1269 Sudo users will probably prefer:
1270
1271     su root -c ./Build
1272 or
1273     sudo ./Build
1274 or
1275     /path1/to/sudo -u admin_account ./Build
1276
1277 or some such. Your choice: },
1278
1279
1280 mbuild_install_arg => qq{Parameters for the './Build install' command?
1281 Typical frequently used setting:
1282
1283     --uninst 1                           # uninstall conflicting files
1284
1285 Your choice: },
1286
1287
1288
1289 inactivity_timeout_intro => qq{
1290
1291 Sometimes you may wish to leave the processes run by CPAN alone
1292 without caring about them. Because the Makefile.PL or the Build.PL
1293 sometimes contains question you\'re expected to answer, you can set a
1294 timer that will kill a 'perl Makefile.PL' process after the specified
1295 time in seconds.
1296
1297 If you set this value to 0, these processes will wait forever. This is
1298 the default and recommended setting.
1299
1300 },
1301
1302 inactivity_timeout => 
1303 qq{Timeout for inactivity during {Makefile,Build}.PL? },
1304
1305
1306 proxy_intro => qq{
1307
1308 If you\'re accessing the net via proxies, you can specify them in the
1309 CPAN configuration or via environment variables. The variable in
1310 the \$CPAN::Config takes precedence.
1311
1312 },
1313
1314 proxy_user => qq{
1315
1316 If your proxy is an authenticating proxy, you can store your username
1317 permanently. If you do not want that, just press RETURN. You will then
1318 be asked for your username in every future session.
1319
1320 },
1321
1322 proxy_pass => qq{
1323
1324 Your password for the authenticating proxy can also be stored
1325 permanently on disk. If this violates your security policy, just press
1326 RETURN. You will then be asked for the password in every future
1327 session.
1328
1329 },
1330
1331 urls_intro => qq{
1332
1333 Now we need to know where your favorite CPAN sites are located. Push
1334 a few sites onto the array (just in case the first on the array won\'t
1335 work). If you are mirroring CPAN to your local workstation, specify a
1336 file: URL.
1337
1338 First, pick a nearby continent and country by typing in the number(s)
1339 in front of the item(s) you want to select. You can pick several of
1340 each, separated by spaces. Then, you will be presented with a list of
1341 URLs of CPAN mirrors in the countries you selected, along with
1342 previously selected URLs. Select some of those URLs, or just keep the
1343 old list. Finally, you will be prompted for any extra URLs -- file:,
1344 ftp:, or http: -- that host a CPAN mirror.
1345
1346 },
1347
1348 password_warn => qq{
1349
1350 Warning: Term::ReadKey seems not to be available, your password will
1351 be echoed to the terminal!
1352
1353 },
1354
1355 commandnumber_in_prompt => qq{
1356
1357 The prompt of the cpan shell can contain the current command number
1358 for easier tracking of the session or be a plain string. Do you want
1359 the command number in the prompt (yes/no)?},
1360
1361 ftp_passive => qq{
1362
1363 Shall we always set FTP_PASSIVE envariable when dealing with ftp
1364 download (yes/no)?},
1365
1366 # taken from the manpage:
1367 getcwd_intro => qq{
1368
1369 CPAN.pm changes the current working directory often and needs to
1370 determine its own current working directory. Per default it uses
1371 Cwd::cwd but if this doesn't work on your system for some reason,
1372 alternatives can be configured according to the following table:
1373
1374     cwd         Cwd::cwd
1375     getcwd      Cwd::getcwd
1376     fastcwd     Cwd::fastcwd
1377     backtickcwd external command cwd
1378
1379 },
1380
1381 getcwd => qq{Preferred method for determining the current working directory?},
1382
1383 index_expire_intro => qq{
1384
1385 The CPAN indexes are usually rebuilt once or twice per hour, but the
1386 typical CPAN mirror mirrors only once or twice per day. Depending on
1387 the quality of your mirror and your desire to be on the bleeding edge,
1388 you may want to set the following value to more or less than one day
1389 (which is the default). It determines after how many days CPAN.pm
1390 downloads new indexes.
1391
1392 },
1393
1394 index_expire => qq{Let the index expire after how many days?},
1395
1396 term_ornaments => qq{
1397
1398 When using Term::ReadLine, you can turn ornaments on so that your
1399 input stands out against the output from CPAN.pm. Do you want to turn
1400 ornaments on?},
1401
1402 colorize_output => qq{
1403
1404 When you have Term::ANSIColor installed, you can turn on colorized
1405 output to have some visual differences between normal CPAN.pm output,
1406 warnings, and the output of the modules being installed. Set your
1407 favorite colors after some experimenting with the Term::ANSIColor
1408 module. Do you want to turn on colored output?},
1409
1410 colorize_print => qq{Color for normal output?},
1411
1412 colorize_warn => qq{Color for warnings?},
1413
1414 build_requires_install_policy_intro => qq{
1415
1416 When a module declares another one as a 'build_requires' prerequisite
1417 this means that the other module is only needed for building or
1418 testing the module but need not be installed permanently. In this case
1419 you may wish to install that other module nonetheless or just keep it
1420 in the 'build_dir' directory to have it available only temporarily.
1421 Installing saves time on future installations but makes the perl
1422 installation bigger.
1423
1424 You can choose if you want to always install (yes), never install (no)
1425 or be always asked. In the latter case you can set the default answer
1426 for the question to yes (ask/yes) or no (ask/no).
1427
1428 },
1429
1430 build_requires_install_policy =>
1431 qq{Policy on installing 'build_requires' modules (yes, no, ask/yes,
1432 ask/no)?},
1433
1434 yaml_module_intro => qq{
1435
1436 At the time of this writing there are two competing YAML modules,
1437 YAML.pm and YAML::Syck. The latter is faster but needs a C compiler
1438 installed on your system. There may be more alternative YAML
1439 conforming modules but at the time of writing a potential third
1440 player, YAML::Tiny, is not yet sufficiently similar to the other two.
1441
1442 },
1443
1444 yaml_module => qq{Which YAML implementation would you prefer?},
1445
1446 randomize_urllist_intro => qq{
1447
1448 CPAN.pm can introduce some randomness when using hosts for download
1449 that are configured in the urllist parameter. Enter a numeric value
1450 between 0 and 1 to indicate how often you want to let CPAN.pm try a
1451 random host from the urllist. A value of one specifies to always use a
1452 random host as the first try. A value of zero means no randomness at
1453 all. Anything in between specifies how often, on average, a random
1454 host should be tried first.
1455
1456 },
1457
1458 randomize_urllist => "Randomize parameter",
1459
1460 );
1461
1462 die "Coding error in \@prompts declaration.  Odd number of elements, above"
1463   if (@prompts % 2);
1464
1465 %prompts = @prompts;
1466
1467 if (scalar(keys %prompts) != scalar(@prompts)/2) {
1468     my %already;
1469     for my $item (0..$#prompts) {
1470         next if $item % 2;
1471         die "$prompts[$item] is duplicated\n" if $already{$prompts[$item]}++;
1472     }
1473 }
1474
1475 } # EOBEGIN
1476
1477 1;