1 # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
2 package CPAN::Mirrored::By;
8 sub continent { shift->[0] }
9 sub country { shift->[1] }
10 sub url { shift->[2] }
12 package CPAN::FirstTime;
15 use ExtUtils::MakeMaker qw(prompt);
17 use File::Basename ();
20 use vars qw($VERSION);
21 $VERSION = substr q$Revision: 1.56 $, 10;
25 CPAN::FirstTime - Utility for CPAN::Config file Initialization
29 CPAN::FirstTime::init()
33 The init routine asks a few questions and writes a CPAN::Config
34 file. Nothing special.
42 unless ($CPAN::VERSION) {
45 eval {require CPAN::Config;};
51 my($ans,$default,$local,$cont,$url,$expected_size);
59 CPAN is the world-wide archive of perl resources. It consists of about
60 100 sites that all replicate the same contents all around the globe.
61 Many countries have at least one CPAN site already. The resources
62 found on CPAN are easily accessible with the CPAN.pm module. If you
63 want to use CPAN.pm, you have to configure it properly.
65 If you do not want to enter a dialog now, you can answer 'no' to this
66 question and I\'ll try to autoconfigure. (Note: you can revisit this
67 dialog anytime later by typing 'o conf init' at the cpan prompt.)
72 ExtUtils::MakeMaker::prompt("Are you ready for manual configuration?",
77 if ($manual_conf =~ /^\s*y/i) {
79 *prompt = \&ExtUtils::MakeMaker::prompt;
82 $CPAN::Config->{urllist} ||= [];
83 # prototype should match that of &MakeMaker::prompt
86 my($ret) = defined $a ? $a : "";
87 printf qq{%s [%s]\n\n}, $q, $ret;
94 The following questions are intended to help you with the
95 configuration. The CPAN module needs a directory of its own to cache
96 important index files and maybe keep a temporary mirror of CPAN files.
97 This may be a site-wide directory or a personal directory.
101 my $cpan_home = $CPAN::Config->{cpan_home} || File::Spec->catdir($ENV{HOME}, ".cpan");
105 I see you already have a directory
107 Shall we use it as the general CPAN build and cache directory?
113 First of all, I\'d like to create this directory. Where?
118 $default = $cpan_home;
119 while ($ans = prompt("CPAN build and cache directory?",$default)) {
120 eval { File::Path::mkpath($ans); }; # dies if it can't
122 warn "Couldn't create directory $ans.
126 if (-d $ans && -w _) {
129 warn "Couldn't find directory $ans
130 or directory is not writable. Please retry.\n";
133 $CPAN::Config->{cpan_home} = $ans;
137 If you want, I can keep the source files after a build in the cpan
138 home directory. If you choose so then future builds will take the
139 files from there. If you don\'t want to keep them, answer 0 to the
144 $CPAN::Config->{keep_source_where} = File::Spec->catdir($CPAN::Config->{cpan_home},"sources");
145 $CPAN::Config->{build_dir} = File::Spec->catdir($CPAN::Config->{cpan_home},"build");
148 # Cache size, Index expire
153 How big should the disk cache be for keeping the build directories
154 with all the intermediate files\?
158 $default = $CPAN::Config->{build_cache} || 10;
159 $ans = prompt("Cache size for build directory (in MB)?", $default);
160 $CPAN::Config->{build_cache} = $ans;
162 # XXX This the time when we refetch the index files (in days)
163 $CPAN::Config->{'index_expire'} = 1;
167 By default, each time the CPAN module is started, cache scanning
168 is performed to keep the cache size in sync. To prevent from this,
169 disable the cache scanning with 'never'.
173 $default = $CPAN::Config->{scan_cache} || 'atstart';
175 $ans = prompt("Perform cache scanning (atstart or never)?", $default);
176 } while ($ans ne 'atstart' && $ans ne 'never');
177 $CPAN::Config->{scan_cache} = $ans;
184 To considerably speed up the initial CPAN shell startup, it is
185 possible to use Storable to create a cache of metadata. If Storable
186 is not available, the normal index mechanism will be used.
190 defined($default = $CPAN::Config->{cache_metadata}) or $default = 1;
192 $ans = prompt("Cache metadata (yes/no)?", ($default ? 'yes' : 'no'));
193 } while ($ans !~ /^\s*[yn]/i);
194 $CPAN::Config->{cache_metadata} = ($ans =~ /^\s*y/i ? 1 : 0);
201 The next option deals with the charset your terminal supports. In
202 general CPAN is English speaking territory, thus the charset does not
203 matter much, but some of the aliens out there who upload their
204 software to CPAN bear names that are outside the ASCII range. If your
205 terminal supports UTF-8, you say no to the next question, if it
206 supports ISO-8859-1 (also known as LATIN1) then you say yes, and if it
207 supports neither nor, your answer does not matter, you will not be
208 able to read the names of some authors anyway. If you answer no, names
209 will be output in UTF-8.
213 defined($default = $CPAN::Config->{term_is_latin}) or $default = 1;
215 $ans = prompt("Your terminal expects ISO-8859-1 (yes/no)?",
216 ($default ? 'yes' : 'no'));
217 } while ($ans !~ /^\s*[yn]/i);
218 $CPAN::Config->{term_is_latin} = ($ans =~ /^\s*y/i ? 1 : 0);
221 # prerequisites_policy
222 # Do we follow PREREQ_PM?
226 The CPAN module can detect when a module that which you are trying to
227 build depends on prerequisites. If this happens, it can build the
228 prerequisites for you automatically ('follow'), ask you for
229 confirmation ('ask'), or just ignore them ('ignore'). Please set your
230 policy to one of the three values.
234 $default = $CPAN::Config->{prerequisites_policy} || 'ask';
237 prompt("Policy on building prerequisites (follow, ask or ignore)?",
239 } while ($ans ne 'follow' && $ans ne 'ask' && $ans ne 'ignore');
240 $CPAN::Config->{prerequisites_policy} = $ans;
248 The CPAN module will need a few external programs to work properly.
249 Please correct me, if I guess the wrong path for a program. Don\'t
250 panic if you do not have some of them, just press ENTER for those. To
251 disable the use of a download program, you can type a space followed
257 local $^W if $^O eq 'MacOS';
258 my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
259 local $^W = $old_warn;
261 for $progname (qw/gzip tar unzip make lynx wget ncftpget ncftp ftp/){
262 if ($^O eq 'MacOS') {
263 $CPAN::Config->{$progname} = 'not_here';
266 my $progcall = $progname;
267 # we don't need ncftp if we have ncftpget
268 next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
269 my $path = $CPAN::Config->{$progname}
270 || $Config::Config{$progname}
272 if (File::Spec->file_name_is_absolute($path)) {
273 # testing existence is not good enough, some have these exe
276 # warn "Warning: configured $path does not exist\n" unless -e $path;
283 $progcall = $Config::Config{$progname} if $Config::Config{$progname};
286 $path ||= find_exe($progcall,[@path]);
287 warn "Warning: $progcall not found in PATH\n" unless
288 $path; # not -e $path, because find_exe already checked that
289 $ans = prompt("Where is your $progname program?",$path) || $path;
290 $CPAN::Config->{$progname} = $ans;
292 my $path = $CPAN::Config->{'pager'} ||
293 $ENV{PAGER} || find_exe("less",[@path]) ||
294 find_exe("more",[@path]) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 )
296 $ans = prompt("What is your favorite pager program?",$path);
297 $CPAN::Config->{'pager'} = $ans;
298 $path = $CPAN::Config->{'shell'};
299 if (File::Spec->file_name_is_absolute($path)) {
300 warn "Warning: configured $path does not exist\n" unless -e $path;
303 $path ||= $ENV{SHELL};
304 if ($^O eq 'MacOS') {
305 $CPAN::Config->{'shell'} = 'not_here';
307 $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only
308 $ans = prompt("What is your favorite shell?",$path);
309 $CPAN::Config->{'shell'} = $ans;
313 # Arguments to make etc.
318 Every Makefile.PL is run by perl in a separate process. Likewise we
319 run \'make\' and \'make install\' in processes. If you have any
320 parameters \(e.g. PREFIX, LIB, UNINST or the like\) you want to pass
321 to the calls, please specify them here.
323 If you don\'t understand this question, just press ENTER.
327 $default = $CPAN::Config->{makepl_arg} || "";
328 $CPAN::Config->{makepl_arg} =
329 prompt("Parameters for the 'perl Makefile.PL' command?
330 Typical frequently used settings:
332 POLLUTE=1 increasing backwards compatibility
333 LIB=~/perl non-root users (please see manual for more hints)
335 Your choice: ",$default);
336 $default = $CPAN::Config->{make_arg} || "";
337 $CPAN::Config->{make_arg} = prompt("Parameters for the 'make' command?
338 Typical frequently used setting:
340 -j3 dual processor system
342 Your choice: ",$default);
344 $default = $CPAN::Config->{make_install_arg} || $CPAN::Config->{make_arg} || "";
345 $CPAN::Config->{make_install_arg} =
346 prompt("Parameters for the 'make install' command?
347 Typical frequently used setting:
349 UNINST=1 to always uninstall potentially conflicting files
351 Your choice: ",$default);
359 Sometimes you may wish to leave the processes run by CPAN alone
360 without caring about them. As sometimes the Makefile.PL contains
361 question you\'re expected to answer, you can set a timer that will
362 kill a 'perl Makefile.PL' process after the specified time in seconds.
364 If you set this value to 0, these processes will wait forever. This is
365 the default and recommended setting.
369 $default = $CPAN::Config->{inactivity_timeout} || 0;
370 $CPAN::Config->{inactivity_timeout} =
371 prompt("Timeout for inactivity during Makefile.PL?",$default);
377 If you\'re accessing the net via proxies, you can specify them in the
378 CPAN configuration or via environment variables. The variable in
379 the \$CPAN::Config takes precedence.
383 for (qw/ftp_proxy http_proxy no_proxy/) {
384 $default = $CPAN::Config->{$_} || $ENV{$_};
385 $CPAN::Config->{$_} = prompt("Your $_?",$default);
388 if ($CPAN::Config->{ftp_proxy} ||
389 $CPAN::Config->{http_proxy}) {
390 $default = $CPAN::Config->{proxy_user} || $CPAN::LWP::UserAgent::USER;
393 If your proxy is an authenticating proxy, you can store your username
394 permanently. If you do not want that, just press RETURN. You will then
395 be asked for your username in every future session.
398 if ($CPAN::Config->{proxy_user} = prompt("Your proxy user id?",$default)) {
401 Your password for the authenticating proxy can also be stored
402 permanently on disk. If this violates your security policy, just press
403 RETURN. You will then be asked for the password in every future
408 if ($CPAN::META->has_inst("Term::ReadKey")) {
409 Term::ReadKey::ReadMode("noecho");
413 Warning: Term::ReadKey seems not to be available, your password will
414 be echoed to the terminal!
418 $CPAN::Config->{proxy_pass} = prompt("Your proxy password?");
419 if ($CPAN::META->has_inst("Term::ReadKey")) {
420 Term::ReadKey::ReadMode("restore");
422 $CPAN::Frontend->myprint("\n\n");
430 conf_sites() unless $fastread;
432 unless (@{$CPAN::Config->{'wait_list'}||[]}) {
435 WAIT support is available as a Plugin. You need the CPAN::WAIT module
436 to actually use it. But we need to know your favorite WAIT server. If
437 you don\'t know a WAIT server near you, just press ENTER.
440 $default = "wait://ls6-www.informatik.uni-dortmund.de:1404";
441 $ans = prompt("Your favorite WAIT server?\n ",$default);
442 push @{$CPAN::Config->{'wait_list'}}, $ans;
445 # We don't ask that now, it will be noticed in time, won't it?
446 $CPAN::Config->{'inhibit_startup_message'} = 0;
447 $CPAN::Config->{'getcwd'} = 'cwd';
450 CPAN::Config->commit($configpm);
454 my $m = 'MIRRORED.BY';
455 my $mby = File::Spec->catfile($CPAN::Config->{keep_source_where},$m);
456 File::Path::mkpath(File::Basename::dirname($mby));
457 if (-f $mby && -f $m && -M $m < -M $mby) {
459 File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
463 my $overwrite_local = 0;
464 if ($mby && -f $mby && -M _ <= 60 && -s _ > 0) {
465 my $mtime = localtime((stat _)[9]);
466 my $prompt = qq{Found $mby as of $mtime
468 I\'d use that as a database of CPAN sites. If that is OK for you,
469 please answer 'y', but if you want me to get a new database now,
470 please answer 'n' to the following question.
472 Shall I use the local database in $mby?};
473 my $ans = prompt($prompt,"y");
474 $overwrite_local = 1 unless $ans =~ /^y/i;
477 if ($overwrite_local) {
478 print qq{Trying to overwrite $mby
480 $mby = CPAN::FTP->localize($m,$mby,3);
481 $overwrite_local = 0;
482 } elsif ( ! -f $mby ){
483 print qq{You have no $mby
484 I\'m trying to fetch one
486 $mby = CPAN::FTP->localize($m,$mby,3);
487 } elsif (-M $mby > 60 && $loopcount == 0) {
488 print qq{Your $mby is older than 60 days,
489 I\'m trying to fetch one
491 $mby = CPAN::FTP->localize($m,$mby,3);
493 } elsif (-s $mby == 0) {
494 print qq{You have an empty $mby,
495 I\'m trying to fetch one
497 $mby = CPAN::FTP->localize($m,$mby,3);
502 read_mirrored_by($mby);
509 #warn "in find_exe exe[$exe] path[@$path]";
511 my $abs = File::Spec->catfile($dir,$exe);
512 if (($abs = MM->maybe_command($abs))) {
519 my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
527 # display, at most, 15 items at a time
528 my $limit = $#{ $items } - $pos;
529 $limit = 15 if $limit > 15;
531 # show the next $limit items, get the new position
532 $pos = display_some($items, $limit, $pos);
533 $pos = 0 if $pos >= @$items;
535 my $num = prompt($prompt,$default);
537 @nums = split (' ', $num);
538 my $i = scalar @$items;
539 (warn "invalid items entered, try again\n"), next
540 if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
541 if ($require_nonempty) {
542 (warn "$empty_warning\n");
546 # a blank line continues...
555 my ($items, $limit, $pos) = @_;
558 my @displayable = @$items[$pos .. ($pos + $limit)];
559 for my $item (@displayable) {
560 printf "(%d) %s\n", ++$pos, $item;
562 printf "%d more items, hit ENTER\n", (@$items - $pos) if $pos < @$items;
566 sub read_mirrored_by {
567 my $local = shift or return;
568 my(%all,$url,$expected_size,$default,$ans,$host,$dst,$country,$continent,@location);
569 my $fh = FileHandle->new;
570 $fh->open($local) or die "Couldn't open $local: $!";
573 ($host) = /^([\w\.\-]+)/ unless defined $host;
574 next unless defined $host;
575 next unless /\s+dst_(dst|location)/;
576 /location\s+=\s+\"([^\"]+)/ and @location = (split /\s*,\s*/, $1) and
577 ($continent, $country) = @location[-1,-2];
578 $continent =~ s/\s\(.*//;
579 $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
580 /dst_dst\s+=\s+\"([^\"]+)/ and $dst = $1;
581 next unless $host && $dst && $continent && $country;
582 $all{$continent}{$country}{$dst} = CPAN::Mirrored::By->new($continent,$country,$dst);
584 $dst=$continent=$country="";
587 $CPAN::Config->{urllist} ||= [];
589 if (@previous_urls = @{$CPAN::Config->{urllist}}) {
590 $CPAN::Config->{urllist} = [];
595 Now we need to know where your favorite CPAN sites are located. Push
596 a few sites onto the array (just in case the first on the array won\'t
597 work). If you are mirroring CPAN to your local workstation, specify a
600 First, pick a nearby continent and country (you can pick several of
601 each, separated by spaces, or none if you just want to keep your
602 existing selections). Then, you will be presented with a list of URLs
603 of CPAN mirrors in the countries you selected, along with previously
604 selected URLs. Select some of those URLs, or just keep the old list.
605 Finally, you will be prompted for any extra URLs -- file:, ftp:, or
606 http: -- that host a CPAN mirror.
610 my (@cont, $cont, %cont, @countries, @urls, %seen);
611 my $no_previous_warn =
612 "Sorry! since you don't have any existing picks, you must make a\n" .
613 "geographic selection.";
614 @cont = picklist([sort keys %all],
615 "Select your continent (or several nearby continents)",
621 foreach $cont (@cont) {
622 my @c = sort keys %{$all{$cont}};
623 @cont{@c} = map ($cont, 0..$#c);
624 @c = map ("$_ ($cont)", @c) if @cont > 1;
625 push (@countries, @c);
629 @countries = picklist (\@countries,
630 "Select your country (or several nearby countries)",
634 %seen = map (($_ => 1), @previous_urls);
635 # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
636 foreach $country (@countries) {
637 (my $bare_country = $country) =~ s/ \(.*\)//;
638 my @u = sort keys %{$all{$cont{$bare_country}}{$bare_country}};
639 @u = grep (! $seen{$_}, @u);
640 @u = map ("$_ ($bare_country)", @u)
645 push (@urls, map ("$_ (previous pick)", @previous_urls));
646 my $prompt = "Select as many URLs as you like,
647 put them on one line, separated by blanks";
648 if (@previous_urls) {
649 $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
651 $prompt .= "\n(or just hit RETURN to keep your previous picks)";
654 @urls = picklist (\@urls, $prompt, $default);
655 foreach (@urls) { s/ \(.*\)//; }
656 push @{$CPAN::Config->{urllist}}, @urls;
660 my %seen = map (($_ => 1), @{$CPAN::Config->{urllist}});
663 my $prompt = "Enter another URL or RETURN to quit:";
665 $prompt = qq{CPAN.pm needs at least one URL where it can fetch CPAN files from.
667 Please enter your CPAN site:};
669 $ans = prompt ($prompt, "");
672 $ans =~ s|/?\z|/|; # has to end with one slash
673 $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
674 if ($ans =~ /^\w+:\/./) {
675 push @urls, $ans unless $seen{$ans}++;
677 printf(qq{"%s" doesn\'t look like an URL at first sight.
678 I\'ll ignore it for now.
679 You can add it to your %s
680 later if you\'re sure it\'s right.\n},
682 $INC{'CPAN/MyConfig.pm'} || $INC{'CPAN/Config.pm'} || "configuration file",
686 } while $ans || !%seen;
688 push @{$CPAN::Config->{urllist}}, @urls;
689 # xxx delete or comment these out when you're happy that it works
690 print "New set of picks:\n";
691 map { print " $_\n" } @{$CPAN::Config->{urllist}};