Re: DOC PATCH (5.005_54 perlsub.pod)
[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);
f610777f 19$VERSION = substr q$Revision: 1.33 $, 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 {
186 $ans = prompt("Perform cache scanning (follow, ask or ignore)?", $default);
187 } while ($ans ne 'follow' && $ans ne 'ask' && $ans ne 'ignore');
188 $CPAN::Config->{prerequisites_policy} = $ans;
189
da199366 190 #
191 # External programs
192 #
193
5f05dabc 194 print qq{
195
196The CPAN module will need a few external programs to work
197properly. Please correct me, if I guess the wrong path for a program.
05454584 198Don\'t panic if you do not have some of them, just press ENTER for
199those.
5f05dabc 200
201};
202
55e314ee 203 my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
09d9d230 204 my $progname;
2e2b7522 205 for $progname (qw/gzip tar unzip make lynx ncftpget ncftp ftp/){
09d9d230 206 my $progcall = $progname;
2e2b7522 207 # we don't need ncftp if we have ncftpget
208 next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
209 my $path = $CPAN::Config->{$progname}
210 || $Config::Config{$progname}
211 || "";
212 if (MM->file_name_is_absolute($path)) {
213 # testing existence is not good enough, some have these exe
214 # extensions
215
216 # warn "Warning: configured $path does not exist\n" unless -e $path;
217 # $path = "";
218 } else {
219 $path = '';
220 }
221 unless ($path) {
222 # e.g. make -> nmake
223 $progcall = $Config::Config{$progname} if $Config::Config{$progname};
224 }
09d9d230 225
2e2b7522 226 $path ||= find_exe($progcall,[@path]);
227 warn "Warning: $progcall not found in PATH\n" unless
228 $path; # not -e $path, because find_exe already checked that
229 $ans = prompt("Where is your $progname program?",$path) || $path;
230 $CPAN::Config->{$progname} = $ans;
5f05dabc 231 }
232 my $path = $CPAN::Config->{'pager'} ||
233 $ENV{PAGER} || find_exe("less",[@path]) ||
234 find_exe("more",[@path]) || "more";
55e314ee 235 $ans = prompt("What is your favorite pager program?",$path);
5f05dabc 236 $CPAN::Config->{'pager'} = $ans;
55e314ee 237 $path = $CPAN::Config->{'shell'};
238 if (MM->file_name_is_absolute($path)) {
239 warn "Warning: configured $path does not exist\n" unless -e $path;
240 $path = "";
241 }
242 $path ||= $ENV{SHELL};
13bc20ff 243 $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only
55e314ee 244 $ans = prompt("What is your favorite shell?",$path);
05454584 245 $CPAN::Config->{'shell'} = $ans;
da199366 246
247 #
248 # Arguments to make etc.
249 #
250
5f05dabc 251 print qq{
252
da199366 253Every Makefile.PL is run by perl in a separate process. Likewise we
5f05dabc 254run \'make\' and \'make install\' in processes. If you have any parameters
255\(e.g. PREFIX, INSTALLPRIVLIB, UNINST or the like\) you want to pass to
256the calls, please specify them here.
257
05454584 258If you don\'t understand this question, just press ENTER.
259
5f05dabc 260};
261
262 $default = $CPAN::Config->{makepl_arg} || "";
263 $CPAN::Config->{makepl_arg} =
264 prompt("Parameters for the 'perl Makefile.PL' command?",$default);
265 $default = $CPAN::Config->{make_arg} || "";
266 $CPAN::Config->{make_arg} = prompt("Parameters for the 'make' command?",$default);
267
268 $default = $CPAN::Config->{make_install_arg} || $CPAN::Config->{make_arg} || "";
269 $CPAN::Config->{make_install_arg} =
270 prompt("Parameters for the 'make install' command?",$default);
271
da199366 272 #
273 # Alarm period
274 #
275
10b2abe6 276 print qq{
277
278Sometimes you may wish to leave the processes run by CPAN alone
279without caring about them. As sometimes the Makefile.PL contains
280question you\'re expected to answer, you can set a timer that will
281kill a 'perl Makefile.PL' process after the specified time in seconds.
282
e50380aa 283If you set this value to 0, these processes will wait forever. This is
284the default and recommended setting.
10b2abe6 285
286};
287
288 $default = $CPAN::Config->{inactivity_timeout} || 0;
289 $CPAN::Config->{inactivity_timeout} =
09d9d230 290 prompt("Timeout for inactivity during Makefile.PL?",$default);
10b2abe6 291
09d9d230 292 # Proxies
da199366 293
09d9d230 294 print qq{
10b2abe6 295
09d9d230 296If you\'re accessing the net via proxies, you can specify them in the
297CPAN configuration or via environment variables. The variable in
298the \$CPAN::Config takes precedence.
5f05dabc 299
05454584 300};
09d9d230 301
302 for (qw/ftp_proxy http_proxy no_proxy/) {
303 $default = $CPAN::Config->{$_} || $ENV{$_};
304 $CPAN::Config->{$_} = prompt("Your $_?",$default);
5f05dabc 305 }
306
09d9d230 307 #
308 # MIRRORED.BY
309 #
310
311 conf_sites() unless $fastread;
312
d4fd5c69 313 unless (@{$CPAN::Config->{'wait_list'}||[]}) {
314 print qq{
da199366 315
05454584 316WAIT support is available as a Plugin. You need the CPAN::WAIT module
317to actually use it. But we need to know your favorite WAIT server. If
318you don\'t know a WAIT server near you, just press ENTER.
319
320};
d4fd5c69 321 $default = "wait://ls6.informatik.uni-dortmund.de:1404";
322 $ans = prompt("Your favorite WAIT server?\n ",$default);
323 push @{$CPAN::Config->{'wait_list'}}, $ans;
324 }
05454584 325
e50380aa 326 # We don't ask that now, it will be noticed in time, won't it?
5f05dabc 327 $CPAN::Config->{'inhibit_startup_message'} = 0;
e50380aa 328 $CPAN::Config->{'getcwd'} = 'cwd';
5f05dabc 329
330 print "\n\n";
331 CPAN::Config->commit($configpm);
332}
333
09d9d230 334sub conf_sites {
335 my $m = 'MIRRORED.BY';
336 my $mby = MM->catfile($CPAN::Config->{keep_source_where},$m);
337 File::Path::mkpath(File::Basename::dirname($mby));
338 if (-f $mby && -f $m && -M $m < -M $mby) {
339 require File::Copy;
340 File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
341 }
342 if ( ! -f $mby ){
343 print qq{You have no $mby
344 I\'m trying to fetch one
345};
346 $mby = CPAN::FTP->localize($m,$mby,3);
347 } elsif (-M $mby > 30 ) {
348 print qq{Your $mby is older than 30 days,
349 I\'m trying to fetch one
350};
351 $mby = CPAN::FTP->localize($m,$mby,3);
352 }
353 read_mirrored_by($mby);
354}
355
5f05dabc 356sub find_exe {
357 my($exe,$path) = @_;
55e314ee 358 my($dir);
359 #warn "in find_exe exe[$exe] path[@$path]";
5f05dabc 360 for $dir (@$path) {
55e314ee 361 my $abs = MM->catfile($dir,$exe);
13bc20ff 362 if (($abs = MM->maybe_command($abs))) {
5f05dabc 363 return $abs;
364 }
365 }
366}
367
f610777f 368sub picklist {
369 my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
370 $default ||= '';
371
372 my ($item, $i);
373 for $item (@$items) {
374 printf "(%d) %s\n", ++$i, $item;
375 }
376
377 my @nums;
378 while (1) {
379 my $num = prompt($prompt,$default);
380 @nums = split (' ', $num);
381 (warn "invalid items entered, try again\n"), next
382 if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
383 if ($require_nonempty) {
384 (warn "$empty_warning\n"), next
385 unless @nums;
386 }
387 last;
388 }
389 print "\n";
390 for (@nums) { $_-- }
391 @{$items}[@nums];
392}
393
5f05dabc 394sub read_mirrored_by {
395 my($local) = @_;
396 my(%all,$url,$expected_size,$default,$ans,$host,$dst,$country,$continent,@location);
05454584 397 my $fh = FileHandle->new;
398 $fh->open($local) or die "Couldn't open $local: $!";
399 while (<$fh>) {
5f05dabc 400 ($host) = /^([\w\.\-]+)/ unless defined $host;
401 next unless defined $host;
402 next unless /\s+dst_(dst|location)/;
403 /location\s+=\s+\"([^\"]+)/ and @location = (split /\s*,\s*/, $1) and
404 ($continent, $country) = @location[-1,-2];
405 $continent =~ s/\s\(.*//;
f610777f 406 $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
5f05dabc 407 /dst_dst\s+=\s+\"([^\"]+)/ and $dst = $1;
408 next unless $host && $dst && $continent && $country;
409 $all{$continent}{$country}{$dst} = CPAN::Mirrored::By->new($continent,$country,$dst);
410 undef $host;
411 $dst=$continent=$country="";
412 }
05454584 413 $fh->close;
5f05dabc 414 $CPAN::Config->{urllist} ||= [];
f610777f 415 my(@previous_urls);
416 if (@previous_urls = @{$CPAN::Config->{urllist}}) {
5f05dabc 417 $CPAN::Config->{urllist} = [];
5f05dabc 418 }
f610777f 419
5f05dabc 420 print qq{
421
f610777f 422Now we need to know where your favorite CPAN sites are located. Push
5f05dabc 423a few sites onto the array (just in case the first on the array won\'t
424work). If you are mirroring CPAN to your local workstation, specify a
425file: URL.
426
f610777f 427First, pick a nearby continent and country (you can pick several of
428each, separated by spaces, or none if you just want to keep your
429existing selections). Then, you will be presented with a list of URLs
430of CPAN mirrors in the countries you selected, along with previously
431selected URLs. Select some of those URLs, or just keep the old list.
432Finally, you will be prompted for any extra URLs -- file:, ftp:, or
433http: -- that host a CPAN mirror.
5f05dabc 434
435};
436
f610777f 437 my (@cont, $cont, %cont, @countries, @urls, %seen);
438 my $no_previous_warn =
439 "Sorry! since you don't have any existing picks, you must make a\n" .
440 "geographic selection.";
441 @cont = picklist([sort keys %all],
442 "Select your continent (or several nearby continents)",
443 '',
444 ! @previous_urls,
445 $no_previous_warn);
446
447
448 foreach $cont (@cont) {
449 my @c = sort keys %{$all{$cont}};
450 @cont{@c} = map ($cont, 0..$#c);
451 @c = map ("$_ ($cont)", @c) if @cont > 1;
452 push (@countries, @c);
5f05dabc 453 }
f610777f 454
455 if (@countries) {
456 @countries = picklist (\@countries,
457 "Select your country (or several nearby countries)",
458 '',
459 ! @previous_urls,
460 $no_previous_warn);
461 %seen = map (($_ => 1), @previous_urls);
462 # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
463 foreach $country (@countries) {
464 (my $bare_country = $country) =~ s/ \(.*\)//;
465 my @u = sort keys %{$all{$cont{$bare_country}}{$bare_country}};
466 @u = grep (! $seen{$_}, @u);
467 @u = map ("$_ ($bare_country)", @u)
468 if @countries > 1;
469 push (@urls, @u);
470 }
471 }
472 push (@urls, map ("$_ (previous pick)", @previous_urls));
473 my $prompt = "Select as many URLs as you like";
474 if (@previous_urls) {
475 $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
476 (scalar @urls));
477 $prompt .= "\n(or just hit RETURN to keep your previous picks)";
478 }
479
480 @urls = picklist (\@urls, $prompt, $default);
481 foreach (@urls) { s/ \(.*\)//; }
482 %seen = map (($_ => 1), @urls);
483
484 do {
485 $ans = prompt ("Enter another URL or RETURN to quit:", "");
486
487 if ($ans) {
488 $ans =~ s|/?$|/|; # has to end with one slash
489 $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
490 if ($ans =~ /^\w+:\/./) {
491 push @urls, $ans
492 unless $seen{$ans};
493 }
494 else {
495 print qq{"$ans" doesn\'t look like an URL at first sight.
496I\'ll ignore it for now. You can add it to $INC{'CPAN/MyConfig.pm'}
497later if you\'re sure it\'s right.\n};
498 }
499 }
500 } while $ans;
501
502 push @{$CPAN::Config->{urllist}}, @urls;
503 # xxx delete or comment these out when you're happy that it works
504 print "New set of picks:\n";
505 map { print " $_\n" } @{$CPAN::Config->{urllist}};
5f05dabc 506}
507
5081;