ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/lib/CPAN/FirstTime.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:10 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
2     package CPAN::Mirrored::By;
3    
4     sub new {
5     my($self,@arg) = @_;
6     bless [@arg], $self;
7     }
8     sub continent { shift->[0] }
9     sub country { shift->[1] }
10     sub url { shift->[2] }
11    
12     package CPAN::FirstTime;
13    
14     use strict;
15     use ExtUtils::MakeMaker qw(prompt);
16     use FileHandle ();
17     use File::Basename ();
18     use File::Path ();
19     use File::Spec;
20     use vars qw($VERSION);
21     $VERSION = substr q$Revision: 1.60 $, 10;
22    
23     =head1 NAME
24    
25     CPAN::FirstTime - Utility for CPAN::Config file Initialization
26    
27     =head1 SYNOPSIS
28    
29     CPAN::FirstTime::init()
30    
31     =head1 DESCRIPTION
32    
33     The init routine asks a few questions and writes a CPAN::Config
34     file. Nothing special.
35    
36     =cut
37    
38    
39     sub init {
40     my($configpm) = @_;
41     use Config;
42     unless ($CPAN::VERSION) {
43     require CPAN::Nox;
44     }
45     eval {require CPAN::Config;};
46     $CPAN::Config ||= {};
47     local($/) = "\n";
48     local($\) = "";
49     local($|) = 1;
50    
51     my($ans,$default);
52    
53     #
54     # Files, directories
55     #
56    
57     print qq[
58    
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.
64    
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.)
68    
69     ];
70    
71     my $manual_conf =
72     ExtUtils::MakeMaker::prompt("Are you ready for manual configuration?",
73     "yes");
74     my $fastread;
75     {
76     local $^W;
77     if ($manual_conf =~ /^\s*y/i) {
78     $fastread = 0;
79     *prompt = \&ExtUtils::MakeMaker::prompt;
80     } else {
81     $fastread = 1;
82     $CPAN::Config->{urllist} ||= [];
83     # prototype should match that of &MakeMaker::prompt
84     *prompt = sub ($;$) {
85     my($q,$a) = @_;
86     my($ret) = defined $a ? $a : "";
87     printf qq{%s [%s]\n\n}, $q, $ret;
88     $ret;
89     };
90     }
91     }
92     print qq{
93    
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.
98    
99     };
100    
101     my $cpan_home = $CPAN::Config->{cpan_home} || File::Spec->catdir($ENV{HOME}, ".cpan");
102     if (-d $cpan_home) {
103     print qq{
104    
105     I see you already have a directory
106     $cpan_home
107     Shall we use it as the general CPAN build and cache directory?
108    
109     };
110     } else {
111     print qq{
112    
113     First of all, I\'d like to create this directory. Where?
114    
115     };
116     }
117    
118     $default = $cpan_home;
119     while ($ans = prompt("CPAN build and cache directory?",$default)) {
120     unless (File::Spec->file_name_is_absolute($ans)) {
121     require Cwd;
122     my $cwd = Cwd::cwd();
123     my $absans = File::Spec->catdir($cwd,$ans);
124     warn "The path '$ans' is not an absolute path. Please specify an absolute path\n";
125     $default = $absans;
126     next;
127     }
128     eval { File::Path::mkpath($ans); }; # dies if it can't
129     if ($@) {
130     warn "Couldn't create directory $ans.
131     Please retry.\n";
132     next;
133     }
134     if (-d $ans && -w _) {
135     last;
136     } else {
137     warn "Couldn't find directory $ans
138     or directory is not writable. Please retry.\n";
139     }
140     }
141     $CPAN::Config->{cpan_home} = $ans;
142    
143     print qq{
144    
145     If you want, I can keep the source files after a build in the cpan
146     home directory. If you choose so then future builds will take the
147     files from there. If you don\'t want to keep them, answer 0 to the
148     next question.
149    
150     };
151    
152     $CPAN::Config->{keep_source_where} = File::Spec->catdir($CPAN::Config->{cpan_home},"sources");
153     $CPAN::Config->{build_dir} = File::Spec->catdir($CPAN::Config->{cpan_home},"build");
154    
155     #
156     # Cache size, Index expire
157     #
158    
159     print qq{
160    
161     How big should the disk cache be for keeping the build directories
162     with all the intermediate files\?
163    
164     };
165    
166     $default = $CPAN::Config->{build_cache} || 10;
167     $ans = prompt("Cache size for build directory (in MB)?", $default);
168     $CPAN::Config->{build_cache} = $ans;
169    
170     # XXX This the time when we refetch the index files (in days)
171     $CPAN::Config->{'index_expire'} = 1;
172    
173     print qq{
174    
175     By default, each time the CPAN module is started, cache scanning
176     is performed to keep the cache size in sync. To prevent from this,
177     disable the cache scanning with 'never'.
178    
179     };
180    
181     $default = $CPAN::Config->{scan_cache} || 'atstart';
182     do {
183     $ans = prompt("Perform cache scanning (atstart or never)?", $default);
184     } while ($ans ne 'atstart' && $ans ne 'never');
185     $CPAN::Config->{scan_cache} = $ans;
186    
187     #
188     # cache_metadata
189     #
190     print qq{
191    
192     To considerably speed up the initial CPAN shell startup, it is
193     possible to use Storable to create a cache of metadata. If Storable
194     is not available, the normal index mechanism will be used.
195    
196     };
197    
198     defined($default = $CPAN::Config->{cache_metadata}) or $default = 1;
199     do {
200     $ans = prompt("Cache metadata (yes/no)?", ($default ? 'yes' : 'no'));
201     } while ($ans !~ /^\s*[yn]/i);
202     $CPAN::Config->{cache_metadata} = ($ans =~ /^\s*y/i ? 1 : 0);
203    
204     #
205     # term_is_latin
206     #
207     print qq{
208    
209     The next option deals with the charset your terminal supports. In
210     general CPAN is English speaking territory, thus the charset does not
211     matter much, but some of the aliens out there who upload their
212     software to CPAN bear names that are outside the ASCII range. If your
213     terminal supports UTF-8, you say no to the next question, if it
214     supports ISO-8859-1 (also known as LATIN1) then you say yes, and if it
215     supports neither nor, your answer does not matter, you will not be
216     able to read the names of some authors anyway. If you answer no, names
217     will be output in UTF-8.
218    
219     };
220    
221     defined($default = $CPAN::Config->{term_is_latin}) or $default = 1;
222     do {
223     $ans = prompt("Your terminal expects ISO-8859-1 (yes/no)?",
224     ($default ? 'yes' : 'no'));
225     } while ($ans !~ /^\s*[yn]/i);
226     $CPAN::Config->{term_is_latin} = ($ans =~ /^\s*y/i ? 1 : 0);
227    
228     #
229     # save history in file histfile
230     #
231     print qq{
232    
233     If you have one of the readline packages (Term::ReadLine::Perl,
234     Term::ReadLine::Gnu, possibly others) installed, the interactive CPAN
235     shell will have history support. The next two questions deal with the
236     filename of the history file and with its size. If you do not want to
237     set this variable, please hit SPACE RETURN to the following question.
238    
239     };
240    
241     defined($default = $CPAN::Config->{histfile}) or
242     $default = File::Spec->catfile($CPAN::Config->{cpan_home},"histfile");
243     $ans = prompt("File to save your history?", $default);
244     $ans =~ s/^\s+//;
245     $ans =~ s/\s+\z//;
246     $CPAN::Config->{histfile} = $ans;
247    
248     if ($CPAN::Config->{histfile}) {
249     defined($default = $CPAN::Config->{histsize}) or $default = 100;
250     $ans = prompt("Number of lines to save?", $default);
251     $CPAN::Config->{histsize} = $ans;
252     }
253    
254     #
255     # prerequisites_policy
256     # Do we follow PREREQ_PM?
257     #
258     print qq{
259    
260     The CPAN module can detect when a module that which you are trying to
261     build depends on prerequisites. If this happens, it can build the
262     prerequisites for you automatically ('follow'), ask you for
263     confirmation ('ask'), or just ignore them ('ignore'). Please set your
264     policy to one of the three values.
265    
266     };
267    
268     $default = $CPAN::Config->{prerequisites_policy} || 'ask';
269     do {
270     $ans =
271     prompt("Policy on building prerequisites (follow, ask or ignore)?",
272     $default);
273     } while ($ans ne 'follow' && $ans ne 'ask' && $ans ne 'ignore');
274     $CPAN::Config->{prerequisites_policy} = $ans;
275    
276     #
277     # External programs
278     #
279    
280     print qq{
281    
282     The CPAN module will need a few external programs to work properly.
283     Please correct me, if I guess the wrong path for a program. Don\'t
284     panic if you do not have some of them, just press ENTER for those. To
285     disable the use of a download program, you can type a space followed
286     by ENTER.
287    
288     };
289    
290     my $old_warn = $^W;
291     local $^W if $^O eq 'MacOS';
292     my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
293     local $^W = $old_warn;
294     my $progname;
295     for $progname (qw/gzip tar unzip make lynx wget ncftpget ncftp ftp gpg/){
296     if ($^O eq 'MacOS') {
297     $CPAN::Config->{$progname} = 'not_here';
298     next;
299     }
300     my $progcall = $progname;
301     # we don't need ncftp if we have ncftpget
302     next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
303     my $path = $CPAN::Config->{$progname}
304     || $Config::Config{$progname}
305     || "";
306     if (File::Spec->file_name_is_absolute($path)) {
307     # testing existence is not good enough, some have these exe
308     # extensions
309    
310     # warn "Warning: configured $path does not exist\n" unless -e $path;
311     # $path = "";
312     } else {
313     $path = '';
314     }
315     unless ($path) {
316     # e.g. make -> nmake
317     $progcall = $Config::Config{$progname} if $Config::Config{$progname};
318     }
319    
320     $path ||= find_exe($progcall,[@path]);
321     warn "Warning: $progcall not found in PATH\n" unless
322     $path; # not -e $path, because find_exe already checked that
323     $ans = prompt("Where is your $progname program?",$path) || $path;
324     $CPAN::Config->{$progname} = $ans;
325     }
326     my $path = $CPAN::Config->{'pager'} ||
327     $ENV{PAGER} || find_exe("less",[@path]) ||
328     find_exe("more",[@path]) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 )
329     || "more";
330     $ans = prompt("What is your favorite pager program?",$path);
331     $CPAN::Config->{'pager'} = $ans;
332     $path = $CPAN::Config->{'shell'};
333     if (File::Spec->file_name_is_absolute($path)) {
334     warn "Warning: configured $path does not exist\n" unless -e $path;
335     $path = "";
336     }
337     $path ||= $ENV{SHELL};
338     if ($^O eq 'MacOS') {
339     $CPAN::Config->{'shell'} = 'not_here';
340     } else {
341     $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only
342     $ans = prompt("What is your favorite shell?",$path);
343     $CPAN::Config->{'shell'} = $ans;
344     }
345    
346     #
347     # Arguments to make etc.
348     #
349    
350     print qq{
351    
352     Every Makefile.PL is run by perl in a separate process. Likewise we
353     run \'make\' and \'make install\' in processes. If you have any
354     parameters \(e.g. PREFIX, LIB, UNINST or the like\) you want to pass
355     to the calls, please specify them here.
356    
357     If you don\'t understand this question, just press ENTER.
358    
359     };
360    
361     $default = $CPAN::Config->{makepl_arg} || "";
362     $CPAN::Config->{makepl_arg} =
363     prompt("Parameters for the 'perl Makefile.PL' command?
364     Typical frequently used settings:
365    
366     PREFIX=~/perl non-root users (please see manual for more hints)
367    
368     Your choice: ",$default);
369     $default = $CPAN::Config->{make_arg} || "";
370     $CPAN::Config->{make_arg} = prompt("Parameters for the 'make' command?
371     Typical frequently used setting:
372    
373     -j3 dual processor system
374    
375     Your choice: ",$default);
376    
377     $default = $CPAN::Config->{make_install_arg} || $CPAN::Config->{make_arg} || "";
378     $CPAN::Config->{make_install_arg} =
379     prompt("Parameters for the 'make install' command?
380     Typical frequently used setting:
381    
382     UNINST=1 to always uninstall potentially conflicting files
383    
384     Your choice: ",$default);
385    
386     #
387     # Alarm period
388     #
389    
390     print qq{
391    
392     Sometimes you may wish to leave the processes run by CPAN alone
393     without caring about them. As sometimes the Makefile.PL contains
394     question you\'re expected to answer, you can set a timer that will
395     kill a 'perl Makefile.PL' process after the specified time in seconds.
396    
397     If you set this value to 0, these processes will wait forever. This is
398     the default and recommended setting.
399    
400     };
401    
402     $default = $CPAN::Config->{inactivity_timeout} || 0;
403     $CPAN::Config->{inactivity_timeout} =
404     prompt("Timeout for inactivity during Makefile.PL?",$default);
405    
406     # Proxies
407    
408     print qq{
409    
410     If you\'re accessing the net via proxies, you can specify them in the
411     CPAN configuration or via environment variables. The variable in
412     the \$CPAN::Config takes precedence.
413    
414     };
415    
416     for (qw/ftp_proxy http_proxy no_proxy/) {
417     $default = $CPAN::Config->{$_} || $ENV{$_};
418     $CPAN::Config->{$_} = prompt("Your $_?",$default);
419     }
420    
421     if ($CPAN::Config->{ftp_proxy} ||
422     $CPAN::Config->{http_proxy}) {
423     $default = $CPAN::Config->{proxy_user} || $CPAN::LWP::UserAgent::USER;
424     print qq{
425    
426     If your proxy is an authenticating proxy, you can store your username
427     permanently. If you do not want that, just press RETURN. You will then
428     be asked for your username in every future session.
429    
430     };
431     if ($CPAN::Config->{proxy_user} = prompt("Your proxy user id?",$default)) {
432     print qq{
433    
434     Your password for the authenticating proxy can also be stored
435     permanently on disk. If this violates your security policy, just press
436     RETURN. You will then be asked for the password in every future
437     session.
438    
439     };
440    
441     if ($CPAN::META->has_inst("Term::ReadKey")) {
442     Term::ReadKey::ReadMode("noecho");
443     } else {
444     print qq{
445    
446     Warning: Term::ReadKey seems not to be available, your password will
447     be echoed to the terminal!
448    
449     };
450     }
451     $CPAN::Config->{proxy_pass} = prompt("Your proxy password?");
452     if ($CPAN::META->has_inst("Term::ReadKey")) {
453     Term::ReadKey::ReadMode("restore");
454     }
455     $CPAN::Frontend->myprint("\n\n");
456     }
457     }
458    
459     #
460     # MIRRORED.BY
461     #
462    
463     conf_sites() unless $fastread;
464    
465     # We don't ask that now, it will be noticed in time, won't it?
466     $CPAN::Config->{'inhibit_startup_message'} = 0;
467     $CPAN::Config->{'getcwd'} = 'cwd';
468    
469     print "\n\n";
470     CPAN::Config->commit($configpm);
471     }
472    
473     sub conf_sites {
474     my $m = 'MIRRORED.BY';
475     my $mby = File::Spec->catfile($CPAN::Config->{keep_source_where},$m);
476     File::Path::mkpath(File::Basename::dirname($mby));
477     if (-f $mby && -f $m && -M $m < -M $mby) {
478     require File::Copy;
479     File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
480     }
481     my $loopcount = 0;
482     local $^T = time;
483     my $overwrite_local = 0;
484     if ($mby && -f $mby && -M _ <= 60 && -s _ > 0) {
485     my $mtime = localtime((stat _)[9]);
486     my $prompt = qq{Found $mby as of $mtime
487    
488     I\'d use that as a database of CPAN sites. If that is OK for you,
489     please answer 'y', but if you want me to get a new database now,
490     please answer 'n' to the following question.
491    
492     Shall I use the local database in $mby?};
493     my $ans = prompt($prompt,"y");
494     $overwrite_local = 1 unless $ans =~ /^y/i;
495     }
496     while ($mby) {
497     if ($overwrite_local) {
498     print qq{Trying to overwrite $mby
499     };
500     $mby = CPAN::FTP->localize($m,$mby,3);
501     $overwrite_local = 0;
502     } elsif ( ! -f $mby ){
503     print qq{You have no $mby
504     I\'m trying to fetch one
505     };
506     $mby = CPAN::FTP->localize($m,$mby,3);
507     } elsif (-M $mby > 60 && $loopcount == 0) {
508     print qq{Your $mby is older than 60 days,
509     I\'m trying to fetch one
510     };
511     $mby = CPAN::FTP->localize($m,$mby,3);
512     $loopcount++;
513     } elsif (-s $mby == 0) {
514     print qq{You have an empty $mby,
515     I\'m trying to fetch one
516     };
517     $mby = CPAN::FTP->localize($m,$mby,3);
518     } else {
519     last;
520     }
521     }
522     read_mirrored_by($mby);
523     bring_your_own();
524     }
525    
526     sub find_exe {
527     my($exe,$path) = @_;
528     my($dir);
529     #warn "in find_exe exe[$exe] path[@$path]";
530     for $dir (@$path) {
531     my $abs = File::Spec->catfile($dir,$exe);
532     if (($abs = MM->maybe_command($abs))) {
533     return $abs;
534     }
535     }
536     }
537    
538     sub picklist {
539     my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
540     $default ||= '';
541    
542     my $pos = 0;
543    
544     my @nums;
545     while (1) {
546    
547     # display, at most, 15 items at a time
548     my $limit = $#{ $items } - $pos;
549     $limit = 15 if $limit > 15;
550    
551     # show the next $limit items, get the new position
552     $pos = display_some($items, $limit, $pos);
553     $pos = 0 if $pos >= @$items;
554    
555     my $num = prompt($prompt,$default);
556    
557     @nums = split (' ', $num);
558     my $i = scalar @$items;
559     (warn "invalid items entered, try again\n"), next
560     if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
561     if ($require_nonempty) {
562     (warn "$empty_warning\n");
563     }
564     print "\n";
565    
566     # a blank line continues...
567     next unless @nums;
568     last;
569     }
570     for (@nums) { $_-- }
571     @{$items}[@nums];
572     }
573    
574     sub display_some {
575     my ($items, $limit, $pos) = @_;
576     $pos ||= 0;
577    
578     my @displayable = @$items[$pos .. ($pos + $limit)];
579     for my $item (@displayable) {
580     printf "(%d) %s\n", ++$pos, $item;
581     }
582     printf("%d more items, hit SPACE RETURN to show them\n",
583     (@$items - $pos)
584     )
585     if $pos < @$items;
586     return $pos;
587     }
588    
589     sub read_mirrored_by {
590     my $local = shift or return;
591     my(%all,$url,$expected_size,$default,$ans,$host,$dst,$country,$continent,@location);
592     my $fh = FileHandle->new;
593     $fh->open($local) or die "Couldn't open $local: $!";
594     local $/ = "\012";
595     while (<$fh>) {
596     ($host) = /^([\w\.\-]+)/ unless defined $host;
597     next unless defined $host;
598     next unless /\s+dst_(dst|location)/;
599     /location\s+=\s+\"([^\"]+)/ and @location = (split /\s*,\s*/, $1) and
600     ($continent, $country) = @location[-1,-2];
601     $continent =~ s/\s\(.*//;
602     $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
603     /dst_dst\s+=\s+\"([^\"]+)/ and $dst = $1;
604     next unless $host && $dst && $continent && $country;
605     $all{$continent}{$country}{$dst} = CPAN::Mirrored::By->new($continent,$country,$dst);
606     undef $host;
607     $dst=$continent=$country="";
608     }
609     $fh->close;
610     $CPAN::Config->{urllist} ||= [];
611     my(@previous_urls);
612     if (@previous_urls = @{$CPAN::Config->{urllist}}) {
613     $CPAN::Config->{urllist} = [];
614     }
615    
616     print qq{
617    
618     Now we need to know where your favorite CPAN sites are located. Push
619     a few sites onto the array (just in case the first on the array won\'t
620     work). If you are mirroring CPAN to your local workstation, specify a
621     file: URL.
622    
623     First, pick a nearby continent and country (you can pick several of
624     each, separated by spaces, or none if you just want to keep your
625     existing selections). Then, you will be presented with a list of URLs
626     of CPAN mirrors in the countries you selected, along with previously
627     selected URLs. Select some of those URLs, or just keep the old list.
628     Finally, you will be prompted for any extra URLs -- file:, ftp:, or
629     http: -- that host a CPAN mirror.
630    
631     };
632    
633     my (@cont, $cont, %cont, @countries, @urls, %seen);
634     my $no_previous_warn =
635     "Sorry! since you don't have any existing picks, you must make a\n" .
636     "geographic selection.";
637     @cont = picklist([sort keys %all],
638     "Select your continent (or several nearby continents)",
639     '',
640     ! @previous_urls,
641     $no_previous_warn);
642    
643    
644     foreach $cont (@cont) {
645     my @c = sort keys %{$all{$cont}};
646     @cont{@c} = map ($cont, 0..$#c);
647     @c = map ("$_ ($cont)", @c) if @cont > 1;
648     push (@countries, @c);
649     }
650    
651     if (@countries) {
652     @countries = picklist (\@countries,
653     "Select your country (or several nearby countries)",
654     '',
655     ! @previous_urls,
656     $no_previous_warn);
657     %seen = map (($_ => 1), @previous_urls);
658     # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
659     foreach $country (@countries) {
660     (my $bare_country = $country) =~ s/ \(.*\)//;
661     my @u = sort keys %{$all{$cont{$bare_country}}{$bare_country}};
662     @u = grep (! $seen{$_}, @u);
663     @u = map ("$_ ($bare_country)", @u)
664     if @countries > 1;
665     push (@urls, @u);
666     }
667     }
668     push (@urls, map ("$_ (previous pick)", @previous_urls));
669     my $prompt = "Select as many URLs as you like (by number),
670     put them on one line, separated by blanks, e.g. '1 4 5'";
671     if (@previous_urls) {
672     $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
673     (scalar @urls));
674     $prompt .= "\n(or just hit RETURN to keep your previous picks)";
675     }
676    
677     @urls = picklist (\@urls, $prompt, $default);
678     foreach (@urls) { s/ \(.*\)//; }
679     push @{$CPAN::Config->{urllist}}, @urls;
680     }
681    
682     sub bring_your_own {
683     my %seen = map (($_ => 1), @{$CPAN::Config->{urllist}});
684     my($ans,@urls);
685     do {
686     my $prompt = "Enter another URL or RETURN to quit:";
687     unless (%seen) {
688     $prompt = qq{CPAN.pm needs at least one URL where it can fetch CPAN files from.
689    
690     Please enter your CPAN site:};
691     }
692     $ans = prompt ($prompt, "");
693    
694     if ($ans) {
695     $ans =~ s/^\s+//; # no leading spaces
696     $ans =~ s/\s+\z//; # no trailing spaces
697     $ans =~ s|/?\z|/|; # has to end with one slash
698     $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
699     if ($ans =~ /^\w+:\/./) {
700     push @urls, $ans unless $seen{$ans}++;
701     } else {
702     printf(qq{"%s" doesn\'t look like an URL at first sight.
703     I\'ll ignore it for now.
704     You can add it to your %s
705     later if you\'re sure it\'s right.\n},
706     $ans,
707     $INC{'CPAN/MyConfig.pm'} || $INC{'CPAN/Config.pm'} || "configuration file",
708     );
709     }
710     }
711     } while $ans || !%seen;
712    
713     push @{$CPAN::Config->{urllist}}, @urls;
714     # xxx delete or comment these out when you're happy that it works
715     print "New set of picks:\n";
716     map { print " $_\n" } @{$CPAN::Config->{urllist}};
717     }
718    
719     1;