1 # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
2 package CPAN::Mirrored::By;
5 $VERSION = sprintf "%.2f", substr(q$Rev: 338 $,4)/100;
11 sub continent { shift->[0] }
12 sub country { shift->[1] }
13 sub url { shift->[2] }
15 package CPAN::FirstTime;
18 use ExtUtils::MakeMaker ();
20 use File::Basename ();
23 use vars qw($VERSION);
24 $VERSION = sprintf "%.2f", substr(q$Rev: 338 $,4)/100;
28 CPAN::FirstTime - Utility for CPAN::Config file Initialization
32 CPAN::FirstTime::init()
36 The init routine asks a few questions and writes a CPAN::Config
37 file. Nothing special.
42 my($configpm, %args) = @_;
46 unless ($CPAN::VERSION) {
49 eval {require CPAN::Config;};
63 CPAN is the world-wide archive of perl resources. It consists of about
64 100 sites that all replicate the same contents all around the globe.
65 Many countries have at least one CPAN site already. The resources
66 found on CPAN are easily accessible with the CPAN.pm module. If you
67 want to use CPAN.pm, you have to configure it properly.
69 If you do not want to enter a dialog now, you can answer 'no' to this
70 question and I\'ll try to autoconfigure. (Note: you can revisit this
71 dialog anytime later by typing 'o conf init' at the cpan prompt.)
77 local *_real_prompt = \&ExtUtils::MakeMaker::prompt;
78 if ( $args{autoconfig} ) {
81 $manual_conf = prompt("Are you ready for manual configuration?", "yes");
85 if ($manual_conf =~ /^y/i) {
89 $CPAN::Config->{urllist} ||= [];
92 # prototype should match that of &MakeMaker::prompt
93 *_real_prompt = sub ($;$) {
95 my($ret) = defined $a ? $a : "";
96 $CPAN::Frontend->myprint(sprintf qq{%s [%s]\n\n}, $q, $ret);
97 eval { require Time::HiRes };
99 Time::HiRes::sleep(0.1);
105 $CPAN::Frontend->myprint(qq{
107 The following questions are intended to help you with the
108 configuration. The CPAN module needs a directory of its own to cache
109 important index files and maybe keep a temporary mirror of CPAN files.
110 This may be a site-wide directory or a personal directory.
114 my $cpan_home = $CPAN::Config->{cpan_home} || File::Spec->catdir($ENV{HOME}, ".cpan");
116 $CPAN::Frontend->myprint(qq{
118 I see you already have a directory
120 Shall we use it as the general CPAN build and cache directory?
124 $CPAN::Frontend->myprint(qq{
126 First of all, I\'d like to create this directory. Where?
131 $default = $cpan_home;
132 while ($ans = prompt("CPAN build and cache directory?",$default)) {
133 unless (File::Spec->file_name_is_absolute($ans)) {
135 my $cwd = Cwd::cwd();
136 my $absans = File::Spec->catdir($cwd,$ans);
137 warn "The path '$ans' is not an absolute path. Please specify an absolute path\n";
141 eval { File::Path::mkpath($ans); }; # dies if it can't
143 warn "Couldn't create directory $ans.
147 if (-d $ans && -w _) {
150 warn "Couldn't find directory $ans
151 or directory is not writable. Please retry.\n";
154 $CPAN::Config->{cpan_home} = $ans;
156 $CPAN::Frontend->myprint( qq{
158 If you like, I can cache the source files after I build them. Doing
159 so means that, if you ever rebuild that module in the future, the
160 files will be taken from the cache. The tradeoff is that it takes up
161 space. How much space would you like to allocate to this cache? (If
162 you don\'t want me to keep a cache, answer 0.)
166 $CPAN::Config->{keep_source_where} = File::Spec->catdir($CPAN::Config->{cpan_home},"sources");
167 $CPAN::Config->{build_dir} = File::Spec->catdir($CPAN::Config->{cpan_home},"build");
170 # Cache size, Index expire
173 $CPAN::Frontend->myprint( qq{
175 How big should the disk cache be for keeping the build directories
176 with all the intermediate files\?
180 $default = $CPAN::Config->{build_cache} || 100; # large enough to
183 $ans = prompt("Cache size for build directory (in MB)?", $default);
184 $CPAN::Config->{build_cache} = $ans;
186 # XXX This the time when we refetch the index files (in days)
187 $CPAN::Config->{'index_expire'} = 1;
189 $CPAN::Frontend->myprint( qq{
191 By default, each time the CPAN module is started, cache scanning is
192 performed to keep the cache size in sync. To prevent this, answer
197 $default = $CPAN::Config->{scan_cache} || 'atstart';
199 $ans = prompt("Perform cache scanning (atstart or never)?", $default);
200 } while ($ans ne 'atstart' && $ans ne 'never');
201 $CPAN::Config->{scan_cache} = $ans;
206 $CPAN::Frontend->myprint( qq{
208 To considerably speed up the initial CPAN shell startup, it is
209 possible to use Storable to create a cache of metadata. If Storable
210 is not available, the normal index mechanism will be used.
214 defined($default = $CPAN::Config->{cache_metadata}) or $default = 1;
216 $ans = prompt("Cache metadata (yes/no)?", ($default ? 'yes' : 'no'));
217 } while ($ans !~ /^[yn]/i);
218 $CPAN::Config->{cache_metadata} = ($ans =~ /^y/i ? 1 : 0);
223 $CPAN::Frontend->myprint( qq{
225 The next option deals with the charset (aka character set) your
226 terminal supports. In general, CPAN is English speaking territory, so
227 the charset does not matter much, but some of the aliens out there who
228 upload their software to CPAN bear names that are outside the ASCII
229 range. If your terminal supports UTF-8, you should say no to the next
230 question. If it supports ISO-8859-1 (also known as LATIN1) then you
231 should say yes. If it supports neither, your answer does not matter
232 because you will not be able to read the names of some authors
233 anyway. If you answer no, names will be output in UTF-8.
237 defined($default = $CPAN::Config->{term_is_latin}) or $default = 1;
239 $ans = prompt("Your terminal expects ISO-8859-1 (yes/no)?",
240 ($default ? 'yes' : 'no'));
241 } while ($ans !~ /^[yn]/i);
242 $CPAN::Config->{term_is_latin} = ($ans =~ /^y/i ? 1 : 0);
245 # save history in file histfile
247 $CPAN::Frontend->myprint( qq{
249 If you have one of the readline packages (Term::ReadLine::Perl,
250 Term::ReadLine::Gnu, possibly others) installed, the interactive CPAN
251 shell will have history support. The next two questions deal with the
252 filename of the history file and with its size. If you do not want to
253 set this variable, please hit SPACE RETURN to the following question.
257 defined($default = $CPAN::Config->{histfile}) or
258 $default = File::Spec->catfile($CPAN::Config->{cpan_home},"histfile");
259 $ans = prompt("File to save your history?", $default);
260 $CPAN::Config->{histfile} = $ans;
262 if ($CPAN::Config->{histfile}) {
263 defined($default = $CPAN::Config->{histsize}) or $default = 100;
264 $ans = prompt("Number of lines to save?", $default);
265 $CPAN::Config->{histsize} = $ans;
269 # do an ls on the m or the d command
271 $CPAN::Frontend->myprint( qq{
273 The 'd' and the 'm' command normally only show you information they
274 have in their in-memory database and thus will never connect to the
275 internet. If you set the 'show_upload_date' variable to true, 'm' and
276 'd' will additionally show you the upload date of the module or
277 distribution. Per default this feature is off because it may require a
278 net connection to get at the upload date.
282 defined($default = $CPAN::Config->{show_upload_date}) or
284 $ans = prompt("Always try to show upload date with 'd' and 'm' command?", $default);
285 $CPAN::Config->{show_upload_date} = $ans;
288 # prerequisites_policy
289 # Do we follow PREREQ_PM?
291 $CPAN::Frontend->myprint( qq{
293 The CPAN module can detect when a module which you are trying to build
294 depends on prerequisites. If this happens, it can build the
295 prerequisites for you automatically ('follow'), ask you for
296 confirmation ('ask'), or just ignore them ('ignore'). Please set your
297 policy to one of the three values.
301 $default = $CPAN::Config->{prerequisites_policy} || 'ask';
304 prompt("Policy on building prerequisites (follow, ask or ignore)?",
306 } while ($ans ne 'follow' && $ans ne 'ask' && $ans ne 'ignore');
307 $CPAN::Config->{prerequisites_policy} = $ans;
313 $CPAN::Frontend->myprint(qq{
315 The CPAN module will need a few external programs to work properly.
316 Please correct me, if I guess the wrong path for a program. Don\'t
317 panic if you do not have some of them, just press ENTER for those. To
318 disable the use of a download program, you can type a space followed
324 local $^W if $^O eq 'MacOS';
325 my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
326 local $^W = $old_warn;
328 for $progname (qw/bzip2 gzip tar unzip make
329 curl lynx wget ncftpget ncftp ftp
332 if ($^O eq 'MacOS') {
333 $CPAN::Config->{$progname} = 'not_here';
336 my $progcall = $progname;
337 # we don't need ncftp if we have ncftpget
338 next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
339 my $path = $CPAN::Config->{$progname}
340 || $Config::Config{$progname}
342 if (File::Spec->file_name_is_absolute($path)) {
343 # testing existence is not good enough, some have these exe
346 # warn "Warning: configured $path does not exist\n" unless -e $path;
353 $progcall = $Config::Config{$progname} if $Config::Config{$progname};
356 $path ||= find_exe($progcall,[@path]);
357 $CPAN::Frontend->mywarn("Warning: $progcall not found in PATH\n") unless
358 $path; # not -e $path, because find_exe already checked that
359 $ans = prompt("Where is your $progname program?",$path) || $path;
360 $CPAN::Config->{$progname} = $ans;
362 my $path = $CPAN::Config->{'pager'} ||
363 $ENV{PAGER} || find_exe("less",[@path]) ||
364 find_exe("more",[@path]) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 )
366 $ans = prompt("What is your favorite pager program?",$path);
367 $CPAN::Config->{'pager'} = $ans;
368 $path = $CPAN::Config->{'shell'};
369 if (File::Spec->file_name_is_absolute($path)) {
370 warn "Warning: configured $path does not exist\n" unless -e $path;
373 $path ||= $ENV{SHELL};
374 if ($^O eq 'MacOS') {
375 $CPAN::Config->{'shell'} = 'not_here';
377 $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only
378 $ans = prompt("What is your favorite shell?",$path);
379 $CPAN::Config->{'shell'} = $ans;
383 # Arguments to make etc.
386 $CPAN::Frontend->myprint( qq{
388 When you have Module::Build installed and a module comes with both a
389 Makefile.PL and a Build.PL, which shall have precedence? The two
390 installer modules we have are the old and well established
391 ExtUtils::MakeMaker (for short: EUMM) understands the Makefile.PL and
392 the next generation installer Module::Build (MB) works with the
397 $default = $CPAN::Config->{prefer_installer} || "EUMM";
400 prompt("In case you could choose, which installer would you prefer (EUMM or MB)?",
402 } while (uc $ans ne 'MB' && uc $ans ne 'EUMM');
403 $CPAN::Config->{prefer_installer} = $ans;
405 $CPAN::Frontend->myprint( qq{
407 Every Makefile.PL is run by perl in a separate process. Likewise we
408 run \'make\' and \'make install\' in separate processes. If you have
409 any parameters \(e.g. PREFIX, LIB, UNINST or the like\) you want to
410 pass to the calls, please specify them here.
412 If you don\'t understand this question, just press ENTER.
416 $default = $CPAN::Config->{makepl_arg} || "";
417 $CPAN::Config->{makepl_arg} =
418 prompt("Parameters for the 'perl Makefile.PL' command?
419 Typical frequently used settings:
421 PREFIX=~/perl # non-root users (please see manual for more hints)
423 Your choice: ",$default);
424 $default = $CPAN::Config->{make_arg} || "";
425 $CPAN::Config->{make_arg} = prompt("Parameters for the 'make' command?
426 Typical frequently used setting:
428 -j3 # dual processor system
430 Your choice: ",$default);
432 $default = $CPAN::Config->{make_install_make_command} || $CPAN::Config->{make} || "";
433 $CPAN::Config->{make_install_make_command} =
434 prompt("Do you want to use a different make command for 'make install'?
435 Cautious people will probably prefer:
441 /path1/to/sudo -u admin_account /path2/to/make
443 or some such. Your choice: ",$default);
445 $default = $CPAN::Config->{make_install_arg} || $CPAN::Config->{make_arg} || "";
446 $CPAN::Config->{make_install_arg} =
447 prompt("Parameters for the 'make install' command?
448 Typical frequently used setting:
450 UNINST=1 # to always uninstall potentially conflicting files
452 Your choice: ",$default);
454 $CPAN::Frontend->myprint( qq{
456 The next questions deal with Module::Build support.
458 A Build.PL is run by perl in a separate process. Likewise we run
459 './Build' and './Build install' in separate processes. If you have any
460 parameters you want to pass to the calls, please specify them here.
464 $default = $CPAN::Config->{mbuildpl_arg} || "";
465 $CPAN::Config->{mbuildpl_arg} =
466 prompt("Parameters for the 'perl Build.PL' command?
467 Typical frequently used settings:
469 --install_base /home/xxx # different installation directory
471 Your choice: ",$default);
472 $default = $CPAN::Config->{mbuild_arg} || "";
473 $CPAN::Config->{mbuild_arg} = prompt("Parameters for the './Build' command?
476 --extra_linker_flags -L/usr/foo/lib # non-standard library location
478 Your choice: ",$default);
480 $default = $CPAN::Config->{mbuild_install_build_command} || "./Build";
481 $CPAN::Config->{mbuild_install_build_command} =
482 prompt("Do you want to use a different command for './Build install'?
483 Sudo users will probably prefer:
489 /path1/to/sudo -u admin_account ./Build
491 or some such. Your choice: ",$default);
493 $default = $CPAN::Config->{mbuild_install_arg} || "";
494 $CPAN::Config->{mbuild_install_arg} =
495 prompt("Parameters for the './Build install' command?
496 Typical frequently used setting:
498 --uninst 1 # uninstall conflicting files
500 Your choice: ",$default);
506 $CPAN::Frontend->myprint( qq{
508 Sometimes you may wish to leave the processes run by CPAN alone
509 without caring about them. Because the Makefile.PL sometimes contains
510 question you\'re expected to answer, you can set a timer that will
511 kill a 'perl Makefile.PL' process after the specified time in seconds.
513 If you set this value to 0, these processes will wait forever. This is
514 the default and recommended setting.
518 $default = $CPAN::Config->{inactivity_timeout} || 0;
519 $CPAN::Config->{inactivity_timeout} =
520 prompt("Timeout for inactivity during {Makefile,Build}.PL?",$default);
524 $CPAN::Frontend->myprint( qq{
526 If you\'re accessing the net via proxies, you can specify them in the
527 CPAN configuration or via environment variables. The variable in
528 the \$CPAN::Config takes precedence.
532 for (qw/ftp_proxy http_proxy no_proxy/) {
533 $default = $CPAN::Config->{$_} || $ENV{$_};
534 $CPAN::Config->{$_} = prompt("Your $_?",$default);
537 if ($CPAN::Config->{ftp_proxy} ||
538 $CPAN::Config->{http_proxy}) {
539 $default = $CPAN::Config->{proxy_user} || $CPAN::LWP::UserAgent::USER;
540 $CPAN::Frontend->myprint( qq{
542 If your proxy is an authenticating proxy, you can store your username
543 permanently. If you do not want that, just press RETURN. You will then
544 be asked for your username in every future session.
547 if ($CPAN::Config->{proxy_user} = prompt("Your proxy user id?",$default)) {
548 $CPAN::Frontend->myprint( qq{
550 Your password for the authenticating proxy can also be stored
551 permanently on disk. If this violates your security policy, just press
552 RETURN. You will then be asked for the password in every future
557 if ($CPAN::META->has_inst("Term::ReadKey")) {
558 Term::ReadKey::ReadMode("noecho");
560 $CPAN::Frontend->myprint( qq{
562 Warning: Term::ReadKey seems not to be available, your password will
563 be echoed to the terminal!
567 $CPAN::Config->{proxy_pass} = prompt_no_strip("Your proxy password?");
568 if ($CPAN::META->has_inst("Term::ReadKey")) {
569 Term::ReadKey::ReadMode("restore");
571 $CPAN::Frontend->myprint("\n\n");
579 conf_sites() unless $fastread;
581 # We don't ask that now, it will be noticed in time, won't it?
582 $CPAN::Config->{'inhibit_startup_message'} = 0;
583 $CPAN::Config->{'getcwd'} = 'cwd';
585 $CPAN::Frontend->myprint("\n\n");
586 CPAN::HandleConfig->commit($configpm);
590 my $m = 'MIRRORED.BY';
591 my $mby = File::Spec->catfile($CPAN::Config->{keep_source_where},$m);
592 File::Path::mkpath(File::Basename::dirname($mby));
593 if (-f $mby && -f $m && -M $m < -M $mby) {
595 File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
599 my $overwrite_local = 0;
600 if ($mby && -f $mby && -M _ <= 60 && -s _ > 0) {
601 my $mtime = localtime((stat _)[9]);
602 my $prompt = qq{Found $mby as of $mtime
604 I\'d use that as a database of CPAN sites. If that is OK for you,
605 please answer 'y', but if you want me to get a new database now,
606 please answer 'n' to the following question.
608 Shall I use the local database in $mby?};
609 my $ans = prompt($prompt,"y");
610 $overwrite_local = 1 unless $ans =~ /^y/i;
613 if ($overwrite_local) {
614 print qq{Trying to overwrite $mby
616 $mby = CPAN::FTP->localize($m,$mby,3);
617 $overwrite_local = 0;
618 } elsif ( ! -f $mby ){
619 print qq{You have no $mby
620 I\'m trying to fetch one
622 $mby = CPAN::FTP->localize($m,$mby,3);
623 } elsif (-M $mby > 60 && $loopcount == 0) {
624 print qq{Your $mby is older than 60 days,
625 I\'m trying to fetch one
627 $mby = CPAN::FTP->localize($m,$mby,3);
629 } elsif (-s $mby == 0) {
630 print qq{You have an empty $mby,
631 I\'m trying to fetch one
633 $mby = CPAN::FTP->localize($m,$mby,3);
638 read_mirrored_by($mby);
645 #warn "in find_exe exe[$exe] path[@$path]";
647 my $abs = File::Spec->catfile($dir,$exe);
648 if (($abs = MM->maybe_command($abs))) {
655 my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
663 # display, at most, 15 items at a time
664 my $limit = $#{ $items } - $pos;
665 $limit = 15 if $limit > 15;
667 # show the next $limit items, get the new position
668 $pos = display_some($items, $limit, $pos);
669 $pos = 0 if $pos >= @$items;
671 my $num = prompt($prompt,$default);
673 @nums = split (' ', $num);
674 my $i = scalar @$items;
675 (warn "invalid items entered, try again\n"), next
676 if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
677 if ($require_nonempty) {
678 (warn "$empty_warning\n");
682 # a blank line continues...
691 my ($items, $limit, $pos) = @_;
694 my @displayable = @$items[$pos .. ($pos + $limit)];
695 for my $item (@displayable) {
696 printf "(%d) %s\n", ++$pos, $item;
698 printf("%d more items, hit SPACE RETURN to show them\n",
705 sub read_mirrored_by {
706 my $local = shift or return;
707 my(%all,$url,$expected_size,$default,$ans,$host,$dst,$country,$continent,@location);
708 my $fh = FileHandle->new;
709 $fh->open($local) or die "Couldn't open $local: $!";
712 ($host) = /^([\w\.\-]+)/ unless defined $host;
713 next unless defined $host;
714 next unless /\s+dst_(dst|location)/;
715 /location\s+=\s+\"([^\"]+)/ and @location = (split /\s*,\s*/, $1) and
716 ($continent, $country) = @location[-1,-2];
717 $continent =~ s/\s\(.*//;
718 $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
719 /dst_dst\s+=\s+\"([^\"]+)/ and $dst = $1;
720 next unless $host && $dst && $continent && $country;
721 $all{$continent}{$country}{$dst} = CPAN::Mirrored::By->new($continent,$country,$dst);
723 $dst=$continent=$country="";
726 $CPAN::Config->{urllist} ||= [];
728 if (@previous_urls = @{$CPAN::Config->{urllist}}) {
729 $CPAN::Config->{urllist} = [];
734 Now we need to know where your favorite CPAN sites are located. Push
735 a few sites onto the array (just in case the first on the array won\'t
736 work). If you are mirroring CPAN to your local workstation, specify a
739 First, pick a nearby continent and country (you can pick several of
740 each, separated by spaces, or none if you just want to keep your
741 existing selections). Then, you will be presented with a list of URLs
742 of CPAN mirrors in the countries you selected, along with previously
743 selected URLs. Select some of those URLs, or just keep the old list.
744 Finally, you will be prompted for any extra URLs -- file:, ftp:, or
745 http: -- that host a CPAN mirror.
749 my (@cont, $cont, %cont, @countries, @urls, %seen);
750 my $no_previous_warn =
751 "Sorry! since you don't have any existing picks, you must make a\n" .
752 "geographic selection.";
753 @cont = picklist([sort keys %all],
754 "Select your continent (or several nearby continents)",
760 foreach $cont (@cont) {
761 my @c = sort keys %{$all{$cont}};
762 @cont{@c} = map ($cont, 0..$#c);
763 @c = map ("$_ ($cont)", @c) if @cont > 1;
764 push (@countries, @c);
768 @countries = picklist (\@countries,
769 "Select your country (or several nearby countries)",
773 %seen = map (($_ => 1), @previous_urls);
774 # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
775 foreach $country (@countries) {
776 (my $bare_country = $country) =~ s/ \(.*\)//;
777 my @u = sort keys %{$all{$cont{$bare_country}}{$bare_country}};
778 @u = grep (! $seen{$_}, @u);
779 @u = map ("$_ ($bare_country)", @u)
784 push (@urls, map ("$_ (previous pick)", @previous_urls));
785 my $prompt = "Select as many URLs as you like (by number),
786 put them on one line, separated by blanks, e.g. '1 4 5'";
787 if (@previous_urls) {
788 $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
790 $prompt .= "\n(or just hit RETURN to keep your previous picks)";
793 @urls = picklist (\@urls, $prompt, $default);
794 foreach (@urls) { s/ \(.*\)//; }
795 push @{$CPAN::Config->{urllist}}, @urls;
799 my %seen = map (($_ => 1), @{$CPAN::Config->{urllist}});
802 my $prompt = "Enter another URL or RETURN to quit:";
804 $prompt = qq{CPAN.pm needs at least one URL where it can fetch CPAN files from.
806 Please enter your CPAN site:};
808 $ans = prompt ($prompt, "");
811 $ans =~ s|/?\z|/|; # has to end with one slash
812 $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
813 if ($ans =~ /^\w+:\/./) {
814 push @urls, $ans unless $seen{$ans}++;
816 printf(qq{"%s" doesn\'t look like an URL at first sight.
817 I\'ll ignore it for now.
818 You can add it to your %s
819 later if you\'re sure it\'s right.\n},
821 $INC{'CPAN/MyConfig.pm'} || $INC{'CPAN/Config.pm'} || "configuration file",
825 } while $ans || !%seen;
827 push @{$CPAN::Config->{urllist}}, @urls;
828 # xxx delete or comment these out when you're happy that it works
829 print "New set of picks:\n";
830 map { print " $_\n" } @{$CPAN::Config->{urllist}};
835 $_[0] =~ s/^\s+//; # no leading spaces
836 $_[0] =~ s/\s+\z//; # no trailing spaces
841 my $ans = _real_prompt(@_);
849 sub prompt_no_strip ($;$) {
850 return _real_prompt(@_);