small bug in change#6144; remove random \xA0 character that snuck
[p5sagit/p5-mst-13.2.git] / lib / CPAN / FirstTime.pm
CommitLineData
5f05dabc 1package CPAN::Mirrored::By;
2
3sub new {
4 my($self,@arg) = @_;
5 bless [@arg], $self;
6}
da199366 7sub continent { shift->[0] }
8sub country { shift->[1] }
5f05dabc 9sub url { shift->[2] }
10
11package CPAN::FirstTime;
12
13use strict;
14use ExtUtils::MakeMaker qw(prompt);
05454584 15use FileHandle ();
09d9d230 16use File::Basename ();
05454584 17use File::Path ();
5f05dabc 18use vars qw($VERSION);
911a92db 19$VERSION = substr q$Revision: 1.38 $, 10;
5f05dabc 20
21=head1 NAME
22
23CPAN::FirstTime - Utility for CPAN::Config file Initialization
24
25=head1 SYNOPSIS
26
27CPAN::FirstTime::init()
28
29=head1 DESCRIPTION
30
31The init routine asks a few questions and writes a CPAN::Config
32file. Nothing special.
33
34=cut
35
36
37sub init {
38 my($configpm) = @_;
39 use Config;
f610777f 40 unless ($CPAN::VERSION) {
41 require CPAN::Nox;
42 }
5f05dabc 43 eval {require CPAN::Config;};
44 $CPAN::Config ||= {};
da199366 45 local($/) = "\n";
46 local($\) = "";
13bc20ff 47 local($|) = 1;
da199366 48
5f05dabc 49 my($ans,$default,$local,$cont,$url,$expected_size);
f610777f 50
da199366 51 #
52 # Files, directories
53 #
54
2e2b7522 55 print qq[
09d9d230 56
57CPAN is the world-wide archive of perl resources. It consists of about
58100 sites that all replicate the same contents all around the globe.
59Many countries have at least one CPAN site already. The resources
60found on CPAN are easily accessible with the CPAN.pm module. If you
61want to use CPAN.pm, you have to configure it properly.
62
63If you do not want to enter a dialog now, you can answer 'no' to this
64question and I\'ll try to autoconfigure. (Note: you can revisit this
65dialog anytime later by typing 'o conf init' at the cpan prompt.)
66
2e2b7522 67];
09d9d230 68
69 my $manual_conf =
70 ExtUtils::MakeMaker::prompt("Are you ready for manual configuration?",
71 "yes");
72 my $fastread;
73 {
74 local $^W;
75 if ($manual_conf =~ /^\s*y/i) {
76 $fastread = 0;
77 *prompt = \&ExtUtils::MakeMaker::prompt;
78 } else {
79 $fastread = 1;
36263cb3 80 $CPAN::Config->{urllist} ||= [];
c9d9b473 81 # prototype should match that of &MakeMaker::prompt
82 *prompt = sub ($;$) {
09d9d230 83 my($q,$a) = @_;
84 my($ret) = defined $a ? $a : "";
85 printf qq{%s [%s]\n\n}, $q, $ret;
86 $ret;
87 };
88 }
89 }
90 print qq{
91
92The following questions are intended to help you with the
93configuration. The CPAN module needs a directory of its own to cache
94important index files and maybe keep a temporary mirror of CPAN files.
95This may be a site-wide directory or a personal directory.
96
5f05dabc 97};
98
99 my $cpan_home = $CPAN::Config->{cpan_home} || MM->catdir($ENV{HOME}, ".cpan");
100 if (-d $cpan_home) {
101 print qq{
102
103I see you already have a directory
104 $cpan_home
105Shall we use it as the general CPAN build and cache directory?
106
107};
108 } else {
109 print qq{
110
111First of all, I\'d like to create this directory. Where?
112
113};
114 }
115
116 $default = $cpan_home;
05454584 117 while ($ans = prompt("CPAN build and cache directory?",$default)) {
36263cb3 118 eval { File::Path::mkpath($ans); }; # dies if it can't
119 if ($@) {
120 warn "Couldn't create directory $ans.
121Please retry.\n";
122 next;
123 }
124 if (-d $ans && -w _) {
125 last;
126 } else {
127 warn "Couldn't find directory $ans
10b2abe6 128 or directory is not writable. Please retry.\n";
36263cb3 129 }
10b2abe6 130 }
5f05dabc 131 $CPAN::Config->{cpan_home} = $ans;
f610777f 132
5f05dabc 133 print qq{
134
135If you want, I can keep the source files after a build in the cpan
136home directory. If you choose so then future builds will take the
137files from there. If you don\'t want to keep them, answer 0 to the
138next question.
139
140};
141
142 $CPAN::Config->{keep_source_where} = MM->catdir($CPAN::Config->{cpan_home},"sources");
143 $CPAN::Config->{build_dir} = MM->catdir($CPAN::Config->{cpan_home},"build");
144
da199366 145 #
146 # Cache size, Index expire
147 #
148
5f05dabc 149 print qq{
150
151How big should the disk cache be for keeping the build directories
152with all the intermediate files?
153
154};
155
156 $default = $CPAN::Config->{build_cache} || 10;
157 $ans = prompt("Cache size for build directory (in MB)?", $default);
158 $CPAN::Config->{build_cache} = $ans;
159
160 # XXX This the time when we refetch the index files (in days)
161 $CPAN::Config->{'index_expire'} = 1;
162
f610777f 163 print qq{
164
165By default, each time the CPAN module is started, cache scanning
166is performed to keep the cache size in sync. To prevent from this,
167disable the cache scanning with 'never'.
168
169};
170
171 $default = $CPAN::Config->{scan_cache} || 'atstart';
172 do {
173 $ans = prompt("Perform cache scanning (atstart or never)?", $default);
174 } while ($ans ne 'atstart' && $ans ne 'never');
175 $CPAN::Config->{scan_cache} = $ans;
176
177 #
178 # prerequisites_policy
179 # Do we follow PREREQ_PM?
180 #
181 print qq{
182
183The CPAN module can detect when a module that which you are trying to
184build depends on prerequisites. If this happens, it can build the
185prerequisites for you automatically ('follow'), ask you for
186confirmation ('ask'), or just ignore them ('ignore'). Please set your
187policy to one of the three values.
188
189};
190
191 $default = $CPAN::Config->{prerequisites_policy} || 'follow';
192 do {
f14b5cec 193 $ans =
194 prompt("Policy on building prerequisites (follow, ask or ignore)?",
195 $default);
f610777f 196 } while ($ans ne 'follow' && $ans ne 'ask' && $ans ne 'ignore');
197 $CPAN::Config->{prerequisites_policy} = $ans;
198
da199366 199 #
200 # External programs
201 #
202
5f05dabc 203 print qq{
204
205The CPAN module will need a few external programs to work
206properly. Please correct me, if I guess the wrong path for a program.
05454584 207Don\'t panic if you do not have some of them, just press ENTER for
208those.
5f05dabc 209
210};
211
f14b5cec 212 my $old_warn = $^W;
213 local $^W if $^O eq 'MacOS';
55e314ee 214 my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
f14b5cec 215 local $^W = $old_warn;
09d9d230 216 my $progname;
2e2b7522 217 for $progname (qw/gzip tar unzip make lynx ncftpget ncftp ftp/){
f14b5cec 218 if ($^O eq 'MacOS') {
219 $CPAN::Config->{$progname} = 'not_here';
220 next;
221 }
09d9d230 222 my $progcall = $progname;
2e2b7522 223 # we don't need ncftp if we have ncftpget
224 next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
225 my $path = $CPAN::Config->{$progname}
226 || $Config::Config{$progname}
227 || "";
228 if (MM->file_name_is_absolute($path)) {
229 # testing existence is not good enough, some have these exe
230 # extensions
231
232 # warn "Warning: configured $path does not exist\n" unless -e $path;
233 # $path = "";
234 } else {
235 $path = '';
236 }
237 unless ($path) {
238 # e.g. make -> nmake
239 $progcall = $Config::Config{$progname} if $Config::Config{$progname};
240 }
09d9d230 241
2e2b7522 242 $path ||= find_exe($progcall,[@path]);
243 warn "Warning: $progcall not found in PATH\n" unless
244 $path; # not -e $path, because find_exe already checked that
245 $ans = prompt("Where is your $progname program?",$path) || $path;
246 $CPAN::Config->{$progname} = $ans;
5f05dabc 247 }
248 my $path = $CPAN::Config->{'pager'} ||
249 $ENV{PAGER} || find_exe("less",[@path]) ||
f14b5cec 250 find_exe("more",[@path]) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 )
251 || "more";
55e314ee 252 $ans = prompt("What is your favorite pager program?",$path);
5f05dabc 253 $CPAN::Config->{'pager'} = $ans;
55e314ee 254 $path = $CPAN::Config->{'shell'};
255 if (MM->file_name_is_absolute($path)) {
256 warn "Warning: configured $path does not exist\n" unless -e $path;
257 $path = "";
258 }
259 $path ||= $ENV{SHELL};
f14b5cec 260 if ($^O eq 'MacOS') {
261 $CPAN::Config->{'shell'} = 'not_here';
262 } else {
263 $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only
264 $ans = prompt("What is your favorite shell?",$path);
265 $CPAN::Config->{'shell'} = $ans;
266 }
da199366 267
268 #
269 # Arguments to make etc.
270 #
271
5f05dabc 272 print qq{
273
da199366 274Every Makefile.PL is run by perl in a separate process. Likewise we
5f05dabc 275run \'make\' and \'make install\' in processes. If you have any parameters
276\(e.g. PREFIX, INSTALLPRIVLIB, UNINST or the like\) you want to pass to
277the calls, please specify them here.
278
05454584 279If you don\'t understand this question, just press ENTER.
280
5f05dabc 281};
282
283 $default = $CPAN::Config->{makepl_arg} || "";
284 $CPAN::Config->{makepl_arg} =
285 prompt("Parameters for the 'perl Makefile.PL' command?",$default);
286 $default = $CPAN::Config->{make_arg} || "";
287 $CPAN::Config->{make_arg} = prompt("Parameters for the 'make' command?",$default);
288
289 $default = $CPAN::Config->{make_install_arg} || $CPAN::Config->{make_arg} || "";
290 $CPAN::Config->{make_install_arg} =
291 prompt("Parameters for the 'make install' command?",$default);
292
da199366 293 #
294 # Alarm period
295 #
296
10b2abe6 297 print qq{
298
299Sometimes you may wish to leave the processes run by CPAN alone
300without caring about them. As sometimes the Makefile.PL contains
301question you\'re expected to answer, you can set a timer that will
302kill a 'perl Makefile.PL' process after the specified time in seconds.
303
e50380aa 304If you set this value to 0, these processes will wait forever. This is
305the default and recommended setting.
10b2abe6 306
307};
308
309 $default = $CPAN::Config->{inactivity_timeout} || 0;
310 $CPAN::Config->{inactivity_timeout} =
09d9d230 311 prompt("Timeout for inactivity during Makefile.PL?",$default);
10b2abe6 312
09d9d230 313 # Proxies
da199366 314
09d9d230 315 print qq{
10b2abe6 316
09d9d230 317If you\'re accessing the net via proxies, you can specify them in the
318CPAN configuration or via environment variables. The variable in
319the \$CPAN::Config takes precedence.
5f05dabc 320
05454584 321};
09d9d230 322
323 for (qw/ftp_proxy http_proxy no_proxy/) {
324 $default = $CPAN::Config->{$_} || $ENV{$_};
325 $CPAN::Config->{$_} = prompt("Your $_?",$default);
5f05dabc 326 }
327
09d9d230 328 #
329 # MIRRORED.BY
330 #
331
332 conf_sites() unless $fastread;
333
d4fd5c69 334 unless (@{$CPAN::Config->{'wait_list'}||[]}) {
335 print qq{
da199366 336
05454584 337WAIT support is available as a Plugin. You need the CPAN::WAIT module
338to actually use it. But we need to know your favorite WAIT server. If
339you don\'t know a WAIT server near you, just press ENTER.
340
341};
d4fd5c69 342 $default = "wait://ls6.informatik.uni-dortmund.de:1404";
343 $ans = prompt("Your favorite WAIT server?\n ",$default);
344 push @{$CPAN::Config->{'wait_list'}}, $ans;
345 }
05454584 346
e50380aa 347 # We don't ask that now, it will be noticed in time, won't it?
5f05dabc 348 $CPAN::Config->{'inhibit_startup_message'} = 0;
e50380aa 349 $CPAN::Config->{'getcwd'} = 'cwd';
5f05dabc 350
351 print "\n\n";
352 CPAN::Config->commit($configpm);
353}
354
09d9d230 355sub conf_sites {
356 my $m = 'MIRRORED.BY';
357 my $mby = MM->catfile($CPAN::Config->{keep_source_where},$m);
358 File::Path::mkpath(File::Basename::dirname($mby));
359 if (-f $mby && -f $m && -M $m < -M $mby) {
360 require File::Copy;
361 File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
362 }
911a92db 363 my $loopcount = 0;
36263cb3 364 while () {
365 if ( ! -f $mby ){
366 print qq{You have no $mby
09d9d230 367 I\'m trying to fetch one
368};
36263cb3 369 $mby = CPAN::FTP->localize($m,$mby,3);
911a92db 370 } elsif (-M $mby > 60 && $loopcount == 0) {
371 print qq{Your $mby is older than 60 days,
09d9d230 372 I\'m trying to fetch one
373};
36263cb3 374 $mby = CPAN::FTP->localize($m,$mby,3);
911a92db 375 $loopcount++;
36263cb3 376 } elsif (-s $mby == 0) {
377 print qq{You have an empty $mby,
378 I\'m trying to fetch one
379};
380 $mby = CPAN::FTP->localize($m,$mby,3);
381 } else {
382 last;
383 }
09d9d230 384 }
385 read_mirrored_by($mby);
386}
387
5f05dabc 388sub find_exe {
389 my($exe,$path) = @_;
55e314ee 390 my($dir);
391 #warn "in find_exe exe[$exe] path[@$path]";
5f05dabc 392 for $dir (@$path) {
55e314ee 393 my $abs = MM->catfile($dir,$exe);
13bc20ff 394 if (($abs = MM->maybe_command($abs))) {
5f05dabc 395 return $abs;
396 }
397 }
398}
399
f610777f 400sub picklist {
401 my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
402 $default ||= '';
403
404 my ($item, $i);
405 for $item (@$items) {
406 printf "(%d) %s\n", ++$i, $item;
407 }
408
409 my @nums;
410 while (1) {
411 my $num = prompt($prompt,$default);
412 @nums = split (' ', $num);
413 (warn "invalid items entered, try again\n"), next
414 if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
415 if ($require_nonempty) {
416 (warn "$empty_warning\n"), next
417 unless @nums;
418 }
419 last;
420 }
421 print "\n";
422 for (@nums) { $_-- }
423 @{$items}[@nums];
424}
425
5f05dabc 426sub read_mirrored_by {
427 my($local) = @_;
428 my(%all,$url,$expected_size,$default,$ans,$host,$dst,$country,$continent,@location);
05454584 429 my $fh = FileHandle->new;
430 $fh->open($local) or die "Couldn't open $local: $!";
f14b5cec 431 local $/ = "\012";
05454584 432 while (<$fh>) {
5f05dabc 433 ($host) = /^([\w\.\-]+)/ unless defined $host;
434 next unless defined $host;
435 next unless /\s+dst_(dst|location)/;
436 /location\s+=\s+\"([^\"]+)/ and @location = (split /\s*,\s*/, $1) and
437 ($continent, $country) = @location[-1,-2];
438 $continent =~ s/\s\(.*//;
f610777f 439 $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
5f05dabc 440 /dst_dst\s+=\s+\"([^\"]+)/ and $dst = $1;
441 next unless $host && $dst && $continent && $country;
442 $all{$continent}{$country}{$dst} = CPAN::Mirrored::By->new($continent,$country,$dst);
443 undef $host;
444 $dst=$continent=$country="";
445 }
05454584 446 $fh->close;
5f05dabc 447 $CPAN::Config->{urllist} ||= [];
f610777f 448 my(@previous_urls);
449 if (@previous_urls = @{$CPAN::Config->{urllist}}) {
5f05dabc 450 $CPAN::Config->{urllist} = [];
5f05dabc 451 }
f610777f 452
5f05dabc 453 print qq{
454
f610777f 455Now we need to know where your favorite CPAN sites are located. Push
5f05dabc 456a few sites onto the array (just in case the first on the array won\'t
457work). If you are mirroring CPAN to your local workstation, specify a
458file: URL.
459
f610777f 460First, pick a nearby continent and country (you can pick several of
461each, separated by spaces, or none if you just want to keep your
462existing selections). Then, you will be presented with a list of URLs
463of CPAN mirrors in the countries you selected, along with previously
464selected URLs. Select some of those URLs, or just keep the old list.
465Finally, you will be prompted for any extra URLs -- file:, ftp:, or
466http: -- that host a CPAN mirror.
5f05dabc 467
468};
469
f610777f 470 my (@cont, $cont, %cont, @countries, @urls, %seen);
471 my $no_previous_warn =
472 "Sorry! since you don't have any existing picks, you must make a\n" .
473 "geographic selection.";
474 @cont = picklist([sort keys %all],
475 "Select your continent (or several nearby continents)",
476 '',
477 ! @previous_urls,
478 $no_previous_warn);
479
480
481 foreach $cont (@cont) {
482 my @c = sort keys %{$all{$cont}};
483 @cont{@c} = map ($cont, 0..$#c);
484 @c = map ("$_ ($cont)", @c) if @cont > 1;
485 push (@countries, @c);
5f05dabc 486 }
f610777f 487
488 if (@countries) {
489 @countries = picklist (\@countries,
490 "Select your country (or several nearby countries)",
491 '',
492 ! @previous_urls,
493 $no_previous_warn);
494 %seen = map (($_ => 1), @previous_urls);
495 # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
496 foreach $country (@countries) {
497 (my $bare_country = $country) =~ s/ \(.*\)//;
498 my @u = sort keys %{$all{$cont{$bare_country}}{$bare_country}};
499 @u = grep (! $seen{$_}, @u);
500 @u = map ("$_ ($bare_country)", @u)
501 if @countries > 1;
502 push (@urls, @u);
503 }
504 }
505 push (@urls, map ("$_ (previous pick)", @previous_urls));
506 my $prompt = "Select as many URLs as you like";
507 if (@previous_urls) {
508 $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
509 (scalar @urls));
510 $prompt .= "\n(or just hit RETURN to keep your previous picks)";
511 }
512
513 @urls = picklist (\@urls, $prompt, $default);
514 foreach (@urls) { s/ \(.*\)//; }
515 %seen = map (($_ => 1), @urls);
516
517 do {
518 $ans = prompt ("Enter another URL or RETURN to quit:", "");
519
520 if ($ans) {
521 $ans =~ s|/?$|/|; # has to end with one slash
522 $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
523 if ($ans =~ /^\w+:\/./) {
524 push @urls, $ans
525 unless $seen{$ans};
526 }
527 else {
528 print qq{"$ans" doesn\'t look like an URL at first sight.
529I\'ll ignore it for now. You can add it to $INC{'CPAN/MyConfig.pm'}
530later if you\'re sure it\'s right.\n};
531 }
532 }
533 } while $ans;
534
535 push @{$CPAN::Config->{urllist}}, @urls;
536 # xxx delete or comment these out when you're happy that it works
537 print "New set of picks:\n";
538 map { print " $_\n" } @{$CPAN::Config->{urllist}};
5f05dabc 539}
540
5411;