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