Upgrade to CPAN 1.64, from Andreas Koenig.
authorJarkko Hietaniemi <jhi@iki.fi>
Sat, 8 Feb 2003 08:45:35 +0000 (08:45 +0000)
committerJarkko Hietaniemi <jhi@iki.fi>
Sat, 8 Feb 2003 08:45:35 +0000 (08:45 +0000)
p4raw-id: //depot/perl@18672

MANIFEST
lib/CPAN.pm
lib/CPAN/ChangeLog [new file with mode: 0644]
lib/CPAN/FirstTime.pm
lib/CPAN/README [new file with mode: 0644]
lib/CPAN/t/Nox.t
lib/CPAN/t/loadme.t
lib/CPAN/t/mirroredby.t
lib/CPAN/t/vcmp.t
utils.lst
utils/cpan [new file with mode: 0644]

index 066d2ca..63c0ef8 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1024,6 +1024,8 @@ lib/Config.t                      See if Config works
 lib/constant.pm                        For "use constant"
 lib/constant.t                 See if compile-time constants work
 lib/CPAN.pm                    Interface to Comprehensive Perl Archive Network
+lib/CPAN/ChangeLog             Changes of CPAN
+lib/CPAN/README                        README of CPAN
 lib/CPAN/FirstTime.pm          Utility for creating CPAN config files
 lib/CPAN/Nox.pm                        Runs CPAN while avoiding compiled extensions
 lib/CPAN/t/loadme.t            See if CPAN the module works
@@ -2735,6 +2737,7 @@ utfebcdic.h                       Unicode on EBCDIC (UTF-EBCDIC, tr16) header
 util.c                         Utility routines
 util.h                         Dummy header
 utils.lst                      Lists utilities bundled with Perl
+utils/cpan                     easily interact with CPAN from the command line
 utils/c2ph.PL                  program to translate dbx stabs to perl
 utils/dprofpp.PL               Perl code profile post-processor
 utils/enc2xs.PL                        Encode module generator
index b628386..0abfe1d 100644 (file)
@@ -1,11 +1,11 @@
 # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
 package CPAN;
-$VERSION = '1.61';
-# $Id: CPAN.pm,v 1.390 2002/05/07 10:04:58 k Exp $
+$VERSION = '1.64';
+# $Id: CPAN.pm,v 1.397 2003/02/06 09:44:40 k Exp $
 
 # only used during development:
 $Revision = "";
-# $Revision = "[".substr(q$Revision: 1.390 $, 10)."]";
+# $Revision = "[".substr(q$Revision: 1.397 $, 10)."]";
 
 use Carp ();
 use Config ();
@@ -112,6 +112,20 @@ sub shell {
            $readline::rl_completion_function =
                $readline::rl_completion_function = 'CPAN::Complete::cpl';
        }
+        if (my $histfile = $CPAN::Config->{'histfile'}) {{
+            unless ($term->can("AddHistory")) {
+                $CPAN::Frontend->mywarn("Terminal does not support AddHistory.\n");
+                last;
+            }
+            my($fh) = FileHandle->new;
+            open $fh, "<$histfile" or last;
+            local $/ = "\n";
+            while (<$fh>) {
+                chomp;
+                $term->AddHistory($_);
+            }
+            close $fh;
+        }}
        # $term->OUT is autoflushed anyway
        my $odef = select STDERR;
        $| = 1;
@@ -765,27 +779,43 @@ sub cleanup {
   my($message) = @_;
   my $i = 0;
   my $ineval = 0;
-  if (
-      0 &&           # disabled, try reload cpan with it
-      $] > 5.004_60  # thereabouts
-     ) {
-    $ineval = $^S;
-  } else {
-    my($subroutine);
-    while ((undef,undef,undef,$subroutine) = caller(++$i)) {
+  my($subroutine);
+  while ((undef,undef,undef,$subroutine) = caller(++$i)) {
       $ineval = 1, last if
          $subroutine eq '(eval)';
-    }
   }
   return if $ineval && !$End;
-  return unless defined $META->{LOCK}; # unsafe meta access, ok
-  return unless -f $META->{LOCK}; # unsafe meta access, ok
-  unlink $META->{LOCK}; # unsafe meta access, ok
+  return unless defined $META->{LOCK};
+  return unless -f $META->{LOCK};
+  $META->savehist;
+  unlink $META->{LOCK};
   # require Carp;
   # Carp::cluck("DEBUGGING");
   $CPAN::Frontend->mywarn("Lockfile removed.\n");
 }
 
+#-> sub CPAN::savehist
+sub savehist {
+    my($self) = @_;
+    my($histfile,$histsize);
+    unless ($histfile = $CPAN::Config->{'histfile'}){
+        $CPAN::Frontend->mywarn("No history written (no histfile specified).\n");
+        return;
+    }
+    $histsize = $CPAN::Config->{'histsize'} || 100;
+    unless ($CPAN::term->can("GetHistory")) {
+        $CPAN::Frontend->mywarn("Terminal does not support GetHistory.\n");
+        return;
+    }
+    my @h = $CPAN::term->GetHistory;
+    splice @h, 0, @h-$histsize if @h>$histsize;
+    my($fh) = FileHandle->new;
+    open $fh, ">$histfile" or mydie("Couldn't open >$histfile: $!");
+    local $\ = local $, = "\n";
+    print $fh @h;
+    close $fh;
+}
+
 sub is_tested {
     my($self,$what) = @_;
     $self->{is_tested}{$what} = 1;
@@ -1340,7 +1370,7 @@ sub ls      {
     my @accept;
     for (@arg) {
         unless (/^[A-Z\-]+$/i) {
-            $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author");
+            $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author\n");
             next;
         }
         push @accept, uc $_;
@@ -1510,7 +1540,7 @@ Known options:
 sub paintdots_onreload {
     my($ref) = shift;
     sub {
-       if ( $_[0] =~ /[Ss]ubroutine (\w+) redefined/ ) {
+       if ( $_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) {
            my($subr) = $1;
            ++$$ref;
            local($|) = 1;
@@ -1528,14 +1558,17 @@ sub reload {
     $command ||= "";
     $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG;
     if ($command =~ /cpan/i) {
-       CPAN->debug("reloading the whole CPAN.pm") if $CPAN::DEBUG;
-       my $fh = FileHandle->new($INC{'CPAN.pm'});
-       local($/);
-       my $redef = 0;
-       local($SIG{__WARN__}) = paintdots_onreload(\$redef);
-       eval <$fh>;
-       warn $@ if $@;
-       $CPAN::Frontend->myprint("\n$redef subroutines redefined\n");
+        for my $f (qw(CPAN.pm CPAN/FirstTime.pm)) {
+            next unless $INC{$f};
+            CPAN->debug("reloading the whole $f") if $CPAN::DEBUG;
+            my $fh = FileHandle->new($INC{$f});
+            local($/);
+            my $redef = 0;
+            local($SIG{__WARN__}) = paintdots_onreload(\$redef);
+            eval <$fh>;
+            warn $@ if $@;
+            $CPAN::Frontend->myprint("\n$redef subroutines redefined\n");
+        }
     } elsif ($command =~ /index/) {
       CPAN::Index->force_reload;
     } else {
@@ -1929,6 +1962,8 @@ sub print_ornamented {
            print color($ornament), sprintf($sprintf,$line), color("reset"), $nl;
        }
     } else {
+        # chomp $what;
+        # $what .= "\n"; # newlines unless $PRINT_ORNAMENTING
        print $what;
     }
 }
@@ -2020,8 +2055,8 @@ sub rematein {
             push @qcopy, $obj;
        } elsif ($CPAN::META->exists('CPAN::Author',$s)) {
            $obj = $CPAN::META->instance('CPAN::Author',$s);
-            if ($meth eq "dump") {
-                $obj->dump;
+            if ($meth =~ /^(dump|ls)$/) {
+                $obj->$meth();
             } else {
                 $CPAN::Frontend->myprint(
                                          join "",
@@ -2273,7 +2308,7 @@ sub localize {
             CPAN::LWP::UserAgent->config;
            eval {$Ua = CPAN::LWP::UserAgent->new;}; # Why is has_usable still not fit enough?
             if ($@) {
-                $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@")
+                $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n")
                     if $CPAN::DEBUG;
             } else {
                 my($var);
@@ -2424,7 +2459,7 @@ sub hosteasy {
               CPAN::LWP::UserAgent->config;
               eval { $Ua = CPAN::LWP::UserAgent->new; };
               if ($@) {
-                  $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@");
+                  $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n");
               }
          }
          my $res = $Ua->mirror($url, $aslocal);
@@ -2655,7 +2690,7 @@ sub hosthardest {
             @dialog,
             "lcd $aslocal_dir",
             "cd /",
-            map("cd $_", split "/", $dir), # RFC 1738
+            map("cd $_", split /\//, $dir), # RFC 1738
             "bin",
             "get $getfile $targetfile",
             "quit"
@@ -3351,7 +3386,7 @@ sub write_metadata_cache {
     $cache->{PROTOCOL} = PROTOCOL;
     $CPAN::Frontend->myprint("Going to write $metadata_file\n");
     eval { Storable::nstore($cache, $metadata_file) };
-    $CPAN::Frontend->mywarn($@) if $@;
+    $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
 }
 
 #-> sub CPAN::Index::read_metadata_cache ;
@@ -3364,7 +3399,7 @@ sub read_metadata_cache {
     $CPAN::Frontend->myprint("Going to read $metadata_file\n");
     my $cache;
     eval { $cache = Storable::retrieve($metadata_file) };
-    $CPAN::Frontend->mywarn($@) if $@;
+    $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
     if (!$cache || ref $cache ne 'HASH'){
         $LAST_TIME = 0;
         return;
@@ -3372,7 +3407,7 @@ sub read_metadata_cache {
     if (exists $cache->{PROTOCOL}) {
         if (PROTOCOL > $cache->{PROTOCOL}) {
             $CPAN::Frontend->mywarn(sprintf("Ignoring Metadata cache written ".
-                                            "with protocol v%s, requiring v%s",
+                                            "with protocol v%s, requiring v%s\n",
                                             $cache->{PROTOCOL},
                                             PROTOCOL)
                                    );
@@ -3380,7 +3415,7 @@ sub read_metadata_cache {
         }
     } else {
         $CPAN::Frontend->mywarn("Ignoring Metadata cache written ".
-                                "with protocol v1.0");
+                                "with protocol v1.0\n");
         return;
     }
     my $clcnt = 0;
@@ -3676,7 +3711,7 @@ sub normalize {
        ) {
         return $s if $s =~ m:^N/A|^Contact Author: ;
         $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4| or
-            $CPAN::Frontend->mywarn("Strange distribution name [$s]");
+            $CPAN::Frontend->mywarn("Strange distribution name [$s]\n");
         CPAN->debug("s[$s]") if $CPAN::DEBUG;
     }
     $s;
@@ -3789,7 +3824,7 @@ sub get {
                            $CPAN::Config->{keep_source_where},
                            "authors",
                            "id",
-                           split("/",$self->id)
+                           split(/\//,$self->id)
                           );
 
     $self->debug("Doing localize") if $CPAN::DEBUG;
@@ -4059,7 +4094,7 @@ sub cvs_import {
 
     my $userid = $self->cpan_userid;
 
-    my $cvs_dir = (split '/', $dir)[-1];
+    my $cvs_dir = (split /\//, $dir)[-1];
     $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//;
     my $cvs_root = 
       $CPAN::Config->{cvsroot} || $ENV{CVSROOT};
@@ -4096,7 +4131,7 @@ sub readme {
                             $CPAN::Config->{keep_source_where},
                             "authors",
                             "id",
-                            split("/","$sans.readme"),
+                            split(/\//,"$sans.readme"),
                            );
     $self->debug("Doing localize") if $CPAN::DEBUG;
     $local_file = CPAN::FTP->localize("authors/id/$sans.readme",
@@ -4134,7 +4169,7 @@ sub verifyMD5 {
        $CPAN::Frontend->myprint(join "", map {"  $_\n"} @e) and return if @e;
     }
     my($lc_want,$lc_file,@local,$basename);
-    @local = split("/",$self->id);
+    @local = split(/\//,$self->id);
     pop @local;
     push @local, "CHECKSUMS";
     $lc_want =
@@ -5894,7 +5929,7 @@ sub readable {
 
     # And if they say v1.2, then the old perl takes it as "v12"
 
-    $CPAN::Frontend->mywarn("Suspicious version string seen [$n]");
+    $CPAN::Frontend->mywarn("Suspicious version string seen [$n]\n");
     return $n;
   }
   my $better = sprintf "v%vd", $n;
@@ -5924,6 +5959,16 @@ Batch mode:
 
   autobundle, clean, install, make, recompile, test
 
+=head1 STATUS
+
+This module will eventually be replaced by CPANPLUS. CPANPLUS is kind
+of a modern rewrite from ground up with greater extensibility and more
+features but no full compatibility. If you're new to CPAN.pm, you
+probably should investigate if CPANPLUS is the better choice for you.
+If you're already used to CPAN.pm you're welcome to continue using it,
+if you accept that its development is mostly (though not completely)
+stalled.
+
 =head1 DESCRIPTION
 
 The CPAN module is designed to automate the make and install of perl
@@ -6666,6 +6711,8 @@ defined:
   dontload_hash      anonymous hash: modules in the keys will not be
                      loaded by the CPAN::has_inst() routine
   gzip              location of external program gzip
+  histfile           file to maintain history between sessions
+  histsize           maximum number of lines to keep in histfile
   inactivity_timeout breaks interactive Makefile.PLs after this
                      many seconds inactivity. Set to 0 to never break.
   inhibit_startup_message
@@ -6858,6 +6905,16 @@ This is the firewall implemented in the Linux kernel, it allows you to
 hide a complete network behind one IP address. With this firewall no
 special compiling is needed as you can access hosts directly.
 
+For accessing ftp servers behind such firewalls you may need to set
+the environment variable C<FTP_PASSIVE> to a true value, e.g.
+
+    env FTP_PASSIVE=1 perl -MCPAN -eshell
+
+or
+
+    perl -MCPAN -e '$ENV{FTP_PASSIVE} = 1; shell'
+
+
 =back
 
 =back
diff --git a/lib/CPAN/ChangeLog b/lib/CPAN/ChangeLog
new file mode 100644 (file)
index 0000000..c7e7efe
--- /dev/null
@@ -0,0 +1,1186 @@
+2003-02-05  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN.pm (savehist, CPAN::shell): new config variables
+       histfile and histsize control saving and retrieving of history.
+
+       * Explain the status of CPAN.pm vs. CPANPLUS.pm in the POD
+
+       * Documentation: mention FTP_PASSIVE; courtesy Peter Valdemar
+       Mørch
+
+2002-11-22  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * correct all split commands to use a regex instead of a string.
+       Thanks to Rafael Garcia-Suarez for detecting the abuse.
+
+2002-11-17  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * BUNDLE/Test/{Builder,More}.pm: Strip POD from the two bundled
+       modules.
+
+2002-11-15  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Makefile.PL: Switch to CPAN::MakeMaker for this one experimental
+       release. The implications of CPAN::MakeMaker are yet to be
+       evaluated. Here I use the "True Bundle" feature to add Test::More
+       and Test::Builder and remove the dependency on them.
+
+2002-11-12  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN/FirstTime.pm (read_mirrored_by): Bill Pollock made me
+       aware about simple mistakes that can be avoided in the URL
+       selection dialogue (entering URL strings instead of numbers,
+       entering leading or trailing whitespace). With a few simple tweaks
+       these should be avoided in the future.
+
+2002-10-20  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN.pm: the last few patches also fixed accidentally some
+       "redefined" warnings during "reload cpan".
+
+2002-09-30  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Roland Bauer sent me a patch that carefully appended a trailing
+       newline to a couple of "mywarn" messages that came without it.
+       
+       * CPAN::FirstTime::display_some: Change the displayed dialogue to
+       make clear that SPACE ENTER is the trick to page through results.
+       Correct some indenting and trailing whitespace. Remove some unused
+       variables.
+
+       * print_ornamented: Newline fix for various Windows systems by
+       Roland Bauer
+
+2002-09-03  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::FirstTime::init: Catch non-absolute path in cpan_home.
+
+2002-08-30  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * New version of the cpan script by brian d foy.
+
+2002-07-28  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing as 1.62.
+
+       * cpan: beefed-up cpan script courtesy brian d foy.
+
+       * Makefile.PL: deactivate PREREQ_PM for File::Spec in case we are
+       running under 5.6.0, otherwise 5.6.0's CPAN.pm would download
+       5.8.0 just for File::Spec.
+
+2002-05-07  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing as 1.61.
+
+       * The default WAIT server has got a new domain name:
+       ls6-www.informatik.uni-dortmund.de
+
+       * Protecting against not existing $META->{is_tested} element.
+
+2002-04-21  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Repackaging, no changes in the code. The reason is that
+       search.cpan.org could not grok the format of my ChangeLog file
+       which mixed POD and non-POD. Now ChangeLog is POD-free and old
+       Changes are in Changes.old. Going to package as 1.60b.
+
+2002-04-19  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Change the quoting in system command for Windows systems. Thanks
+       to Alessandro Forghieri <alf at orion dot it> for the report.
+
+       * merge with bleadperl 
+
+2001-06-16  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Typo Frontent->Frontend in three places. Thanks to Rich Williams
+       for spotting.
+
+2001-05-28  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * manpage_headline: fixed the NAME parsing regular expression to
+       ignore headlines that just start with NAME. Thanks to Jost Krieger
+       for spotting.
+
+2001-05-22  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Bundle::look: disable the look command on bundles. Till
+       now it meant to recursively look into all members. This could be
+       time-consuming and even hard to interrupt. As I know nothing else
+       one could expect from look(Bundle), I decided to disable it
+       completely.
+
+2001-04-xx  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Do not remember exact date: Applied a patch by Gisle Aas to
+       replace MD5 by Digest::MD5.
+
+2001-02-09  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing as 1.59_54.
+
+       * CPAN::Tarzip::TIEHANDLE: Applied a patch by Robin Barker
+       <rmb1@cise.npl.co.uk> about a wrong error message ("Could pipe"
+       instead of "Could not pipe")
+
+2001-02-06  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Index::rd_modpacks: Add a stalenes warning if the index
+       file is older than 30 days. Thanks to "tanbin"
+       <tiger40490@yahoo.com> for the report.
+
+       * To improve the protection against stale mirrors, add a global
+       for $CPAN::Index::DATE_OF_02 to keep track of the currently used
+       index. This is also stored in the cache. It will be printed as a
+       reminder whenever a fetch fails and whenever the metadata are
+       retrieved from the index file or via Storable.
+
+2001-01-02  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Author::as_glimpse): added email address
+
+       * CPAN::Shell::a: uppercasing any argument broke experimental
+       advanced query. Made conditional on the existence of an equal sign
+       now.
+
+2000-12-31  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * POD: add a description of the ls command.
+
+       * Improve documentation of support for authenticated proxies.
+
+       * CPAN::Bundle::contains: Bail out if there is no inst_file and
+       cpan_file eq "N/A". Old code would have tried to download N/A.
+
+2000-12-27  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * normalize: Fix bug with "Strange distribution name" if it is
+       "Contact Author..."
+
+2000-12-26  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::LWP::UserAgent: new class to customize proxy
+       authentication. Thanks to David C Worenklein for a working
+       implementation that I could use as a basis.
+
+2000-12-19  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * manpage: Added a pointer to the Japanese translation.
+
+2000-12-13  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * FAQ: While working on the FAQ mirroring item, I discovered that
+       we need a mirror command because "get" unwraps the tarfiles as a
+       side effect, which is not nice. Mirror() will do nothing if source
+       is a "file:" URL. It will probably understand force to override
+       that. It will copy to ~/.cpan/sources but leave the file unopened
+       and untouched. Backed out the FAQ item until we have that fixed.
+
+2000-12-11  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Distribution::normalize: Did not work correctly for
+       authors that have subdirectories in their CPAN directory. Was
+       counting slashes, am now also checking against a regexp.
+
+       * cpl: make completion work with "get".
+
+       * CPAN::Shell::ls: Reject arguments not matching [A-Z\-] to
+       prevent /.../ expansion which neither worked nor is considered
+       useful.
+
+       * CPAN::Shell::h: include ls command
+
+       * variable naming: rename $date_of_03 and $last_time to uppercase
+       counterparts. Globals must stand out visually.
+
+       * FAQ: Adding "How do I set up a local CPAN mirror that does not
+       contain things I'm not interested in?". Thanks to Paul Moore for
+       asking the question (but see above, the article was removed for
+       further consideration on 2000-12-13)
+
+       * CPAN::Author::id: add a sanity check, first letter must be A-Z
+
+2000-12-10  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Distribution::look: Protect against empty $dir and use
+       safe_chdir instead of chdir.
+
+2000-12-01  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * get: finished the treatment of the NFS racing condition that
+       motivated many of the recent changes in get(). Thanks for
+       reporting and heavy testing to Steffen Beyer.
+
+       * Releasing as 1.59_51.
+
+       * normalize: protect against the case when normalize is called
+       without argument.
+
+       * Thanks to Jeremy Wadsack who read the first sketch of the
+       documentation of the programmer's interface and provided helpful
+       comments and additions.
+
+        * Declaring 1.58_93 as 1.59 and releasing as such to have a stable
+        baseline again. 1.58_93 had been integrated into the development
+        track of 5.7.0 with patch 7737 on 2000/11/18.
+
+2000-11-30  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Distribution::get: removed a special case that was never
+       documented and apparently never worked: when keep_source_where
+       matched /^no/, we tried to delete the source again after an
+       installation.
+
+       * POD: documented expandany
+
+       * CPAN::Bundle::inst_file: now takes the newest Bundle definition
+       file it finds within @INC and ~/.cpan/Bundle/. Sets INST_VERSION
+       as side effect. CPAN::Bundle::inst_version calls inst_file.
+
+       * CPAN::Distribution::uptodate: New method.
+
+       * CPAN::Bundle::uptodate: New method. Thanks to Jeremy Wadsack who
+       discovered that an uptodate method for Bundles was missing.
+
+       * POD: Wrote at least the headlines for all public methods to make
+       a second step at opening CPAN.pm for programmers.
+
+2000-11-28  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Admin (CPAN::Shell::register): opened for XML, Tk, and Apache.
+
+       * CPAN::Author::ls: include the author's ID in the listing to make
+       copy&paste easier.
+
+       * normalize: Allowed the special case "N/A ..." for bundles.
+
+       * CPAN::Complete::cpl: made completion for bundles work on install
+       et al.
+
+       * localize: Encountered a C<Can't locate object method "new" via
+       package "LWP::UserAgent"> although has_usable returned true. Could
+       not find out the reason, so I wrapped it into an eval.
+
+2000-11-23  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Sending as 1.58_94 to Steffen, no release to avoid confusion.
+
+       * Due to a bug report by Steffen Beyer I added a whole lot of
+       debugging statements to get in the hope, I can find a reason why
+       his copy misbehaves under 5.00503.
+
+       * CPAN::Distribution::get: Fixed indenting in get(). Added $! to
+       the error messages there.
+
+
+2000-11-22  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::FirstTime::conf_sites: Added the option to download a
+       MIRRORED.BY immediately even if the local one seems fresh enough.
+
+       * POD: Lots of fixes spotted by John P. Linderman
+
+2000-11-15  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Fixed an incompatibility with 5.00503 discovered by Ask B.
+       Hansen.
+
+2000-11-14  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN/FirstTime.pm: MyConfig/Config buglet during
+       site-picking and more verbosity for selecting good arguments for
+       make (Thanks to Larry Virden for the report)
+
+       * print_ornamented: Made shell output ornamenting dependent on a
+       global variable $CPAN::Shell::PRINT_ORNAMENTING. It is and will
+       stay a rarely used feature, so a global to turn it on and off
+       seems appropriate. For the record: this does not do anything but
+       colorize STDOUT and STDERR differently for debugging if all
+       messages are wrapped correctly.
+
+2000-11-11  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Admin: Made the machine name of PAUSE a constant.
+
+2000-11-10  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * rematein: Enable dump of Author objects (was the useless silly
+       message)
+
+       * Two (temporary) global variables introduced:
+       $CPAN::Tarzip::BUGHUNTING enables naughty code that may help track
+       some bugs in Archive::Tar (already reported to SRZ). And
+       $CPAN::Shell::ADVANCED_QUERY turns on a form of the query like
+           C<m userid=RFOLEY> or
+           C<m userid=~FOL> or
+           C<d cpan_userid=RFOLEY>
+
+       But this syntax is highly experimental and WILL change, do not
+       rely on it.
+       
+2000-11-09  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Module::userid: change to mean either CPAN_USERID from
+       02modules or userid from 03modlist. Up to now it only meant the
+       latter. As both are always identical, we could save some space by
+       renaming CPAN_USERID to userid. --> Todo
+
+2000-11-08  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Complete::cpl: Make completion work for locally installed
+       bundles on the first try, not just the second.
+
+       * CPAN::Complete::cpl: Make completion for authors work even when
+       lowercase was typed in so far.
+
+       * releasing as 1.58_90
+
+       * CPAN::Module::name: was an alias for &cpan_file. That made the m
+       command slow without any visible advantage. C<m /html-tree/> used
+       to find the modules in the distribution HTML-Tree-XXX and now
+       doesn't anymore. But this is misfeature as we have both <d
+       /html-tree/> and <i /html-tree/> for that.
+
+       * cpan_file: Fixed a bug that could instantiate an empty Author
+       object.
+
+2000-11-07  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * format_result: Add a summary line at the end how many items in
+       the set.
+
+       * print_ornamented: Moved the special-case for fullname to
+       print-ornamented to be prepared for other UTF-8 fields besides
+       fullname (Try with C<m Sub::Curry>)
+
+2000-11-06  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Released as 1.58_57
+
+       * CPAN::Shell::ls: I believe, ls is now fully functional, but it
+       still needs some work on PAUSE to be perceived as bugfree. Thu
+       left undocumented (but it's already useful as it is, even
+       completion works; if you're interested: give it only authors as
+       arguments).
+
+       * CPAN::shell: Detect parse errors when Text::ParseWords fails
+       without die()ing, like in C<d Documentum's>.
+
+       * CPAN::Distribution::normalize: Try A/AC/ACALPINI/foo when the
+       user says ACALPINI/foo. I have only tested for the C<rematein>
+       family and the C<d> command so far. Need to find all places where
+       the normalization is needed.
+
+       * CPAN::Module::as_string: improved manpage parsing on files with
+       CRLF in them.
+
+2000-11-04  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing as 1.58_56.
+
+       * CPAN::Shell::local_bundles: Did not discover local bundle files
+       if they were nested. Thanks to Ask B. Hansen for the report.
+
+       * CPAN::Shell::ls: Started work on an ls command. Left
+       undocumented because not yet finished. Needs mtime in CHECKSUMS
+       file.
+
+       * localize: Improved messaging when we try to download a
+       compressed file instead of an uncompressed.
+
+       * o conf: Made C<o conf -Module> to mean remove Module debugging
+       from the current debugging settings. Handy when you turn on "all"
+       and discover that Module is too noisy.
+
+2000-10-29  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * FAQ about readline: Thanks to Joseph Kewish
+       <jkewish@thedrag.com> who knew the correct answer.
+
+2000-10-28  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * untar: again change preference to tag+gzip to hunt down a bug in
+       Archive::Tar.
+
+       * Admin's register: Forgive when URI::Escape isn't installed yet
+       and let it be installed while we're running.
+
+2000-10-27  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing snapshot as 1.58_55.
+
+       * CPAN::Admin::register: do not run a get if the command line
+       already contains more than one arguments.
+
+2000-10-26  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Added documentation for CPAN::shell and term_is_latin.
+
+       * CPAN::Author::fullname: convert to latin1 if
+       $CPAN::Config->{term_is_latin} is set to true.
+
+       * CPAN::Module::as_glimpse and CPAN::Shell::_u_r_common: enabled
+       coloring of module names that are already registered in the module
+       list. This feature bloat will have to go away in a future version,
+       but for a while it might prove useful. The diffs between RCS 1.361
+       and 1.362 should then be applied reversed. The feature bloat is
+       only visible when the global $CPAN::Shell::COLOR_REGISTERED is
+       set, no visible changes are made otherwise.
+
+       * Added CPAN::Admin in an extra file. The subclass is for CPAN
+       admins only. For others it is an instructive programming example.
+       I consider the programming environment still alpha and need
+       feedback on its usefulness. E.g. I consider it ugly that
+       CPAN::Shell::expand and CPAN::instance have such a B<slightly>
+       different interface. I hate it that testing C<$m->{RO}{something}>
+       creates the RO slot. I'm unsure what one could make easier when
+       expand() returns a list of objects instead of a single object.
+
+       * cpl: made CPAN::Complete::cpl more flexible by assigning all
+       commands to the global @COMMANDS and offering a fallback for the
+       second word to modules and bundles when an unknown command is
+       entered. CPAN::Admin takes advantage of this feature.
+
+2000-10-25  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * shell: The C<$term||=> change of 2000-10-20 broke the
+       re-detection of ReadLine for fresh installations. Fixed that again
+       so that both ways are possible: disposing the Stub interface and
+       re-using an interface that is better than Stub.
+
+2000-10-21  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::shell: Now takes two arguments, one is the prompt, the
+       second is the default initial command line.
+
+       * Released this snapshot as 1.58_51
+
+       * hosthard: applied a patch by Michael Dean
+       <sysmwd@blackhole.detir.qld.gov.au> to support wget.
+
+2000-10-20  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Distribution::containsmods: Did not return a value, now
+       returns the contained modules
+
+       * CPAN::Distribution::get: chdir back to initial CWD
+
+       * CPAN::anycwd: new routine replaces all occurrences of replicated
+       two-line code
+
+       * shell: chdir-ing back to initial directory at end of CPAN::shell
+
+       * CPAN::exists: added a config loader because everything depends
+       on it. Will have to identify other places that need it.
+
+       * shell: Assignment of a readline interface to term now is a "||="
+       rather than a "=" in case somebody calls shell multiple times.
+
+       * Moved the call to read_metadata_cache from shell to
+       CPAN::Index::reload so that (1) it isn't called so early and (2)
+       programmers can enjoy its availability too.
+
+       * CPAN::Config::commit: die when you can't write the config file.
+       We did only warn, but it is more frustrating to repeatedly get the
+       same questions asked than to get at least a good error message.
+       Will have to catch some error conditions earlier.
+
+2000-10-18  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Module::as_string: up to now the MANPAGE attribute was
+       only generated for installed modules. Now we try to read the
+       manpage headline if a get has been issued so that a build_dir
+       exists. This is helpful for exploring CPAN without installing
+       anything, e.g. when you have no or only slow access to a WAIT
+       server.
+
+       * Releasing as 1.58
+
+2000-10-15  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * FAQ: two new FAQ items added: autobundle and readline
+
+2000-10-07  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Setting Version to 1.57_68RC
+
+       * POD: numbering FAQ items; rewording of FAQ item 6 about bundles;
+       introduced FAQ item 7 about CPAN::Site.
+
+       * CPAN::FirstTime::init: Making cache_metadata default to 1.
+
+       * missing_config_data: Making cache_metadata a reason to rerun
+       configuration.
+
+2000-09-29  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::DESTROY: Protected the call to $gz->gzclose with an if
+       defined $gz. Thanks to abigail for reporting the bug, apologies
+       that I'm also not sure if this fixes the cause, or just the
+       sympton.
+
+       * has_inst: 2nd warning for not having installed Net::FTP
+       silencified with a global (Thanks to Anno Siegel for the
+       suggestion)
+
+2000-09-16  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * 1.57_67 is a release candidate.
+
+       * FirstTime: rewording of the intro for the cache_metadata feature
+       from experimental to beta. Leaving default to off. As it is still
+       turned off, I do not add the feature to the "necessary" features
+       in sub missing_config_data. Will do so when default changes to on.
+
+       * untar: for running the pipe, the external programs gzip and tar
+       are OK to use but for a pure uncompress I prefer to use our own
+       method gunzip for maximum code reuse (fallback to external gzip is
+       there anyway) and less use of system().
+
+       * hosthard: after Jost has approved that the code now is much more
+       defensive against the install-an-inexistent-distribution errors,
+       now the funkyftp programs are disallowed to process C<file> URLs
+       at all.
+
+2000-09-12  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * get: userid "anon" if cpan_userid does not provide one.
+
+       * 1.57_66 for the sole purpose of testing the error provoked by
+       the old lynx version. Next version will disable lynx for file:
+       URLs and thus will doubly guard against the bug.
+
+       * untar and gtest: enabled gtest with Compress::Zlib again, now
+       with a test if the file size and buffer size are equal. In that
+       case gtest returns false. untar now also uses gtest ahead of
+       decompression to catch the error condition provoked by
+
+          DB<5> x system "echo -n | /bin/tar xvf -"
+        0  0
+
+       The fact that tar returns TRUE on zero byte input could lead us to
+       believe that we were doing a successful untar while in reality we
+       had an uncompressed file that was completely bogus.
+
+       Once again a big thank you to Jost Krieger who discovered this bug
+       by feeding an inexistent distribution name to install() while he
+       had an old version of lynx installed that did not discover the
+       mistake and created the file as textfile containing an error
+       message.
+
+2000-09-11  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * gtest: disabled Compress::Zlib because it seems to offer no
+       method to test if a file is compressed or not. If a file was not
+       compressed, it happily treats it "as expected" setting no error. I
+       was so sure that I tested this when it was introduced. We really
+       need a test harness.
+
+       * get: New instance variable had_no_makefile_pl
+
+       * get: New instance variable was_uncompressed to later use it for
+       heuristics if we're on the wrong track.
+
+       * If we write a Makefile.PL on our own, we now choose the NAME
+       parameter more carefully.
+
+       * Ask user if he wants to proceed if the CHECKSUM file does not
+       contain data about a downloded file.
+
+       * hosthard: Skip "file" URLs
+
+       * hosthardest: eliminated unused code for is_reachable
+
+2000-09-10  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Tarball 1.57_65 (63 and 64 were not uploaded because I found
+       errors during testing)
+
+       * Bundle::inst_file: cleanup
+
+       * unsat_prereq: decision to accept any installed version if
+       PREREQ_PM says 0 or "undef" or undef.
+
+       * follow_prereqs: broke this new method out of make because I want
+       to repeat it in test. Repeating the check in test has the
+       advantage that the user is reminded in time that still some prereq
+       is missing.
+
+2000-09-09  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Tarball 1.57_63.
+
+       * rd_modpacks: do not let bundles be both bundles and modules
+       anymore. Seems like memory bloat without any value.
+
+       * reload: $last_time was set too early to a new value. It seems to
+       have never manifested itself as a bug, but we now do the more
+       correct localizing of the newer timestamp until we have read all
+       three index files and then set the timestamp globally.
+
+       * reload and read_metadata_cache: extend the index protocol to
+       memory so that whenever a new protocol is introduced, the index
+       gets loaded into memory asap.
+
+       * instance vs set: moved the code that creates the RO pointer from
+       instance to set and commenting the set method to have this side
+       effect. This was the cause for a very difficult to diagnose bug.
+       Thanks to Jost Krieger for discovering wrong content in Metadata.
+
+2000-09-08  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * read_metadata_cache: More sanity checks.
+
+       * _u_r_common: Added informational message about the number of
+       matches in the database.
+
+       * checklock: Checking $fh for undef. Thanks to
+       Slaven Rezic for the report.
+
+2000-09-06  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN.pm (expandany): Distributions always had the habit to
+       spring into existence, that means, people could say
+
+           test A/AN/ANDK/CPAN-1.57_60.tar.gz
+
+       and got that thing downloaded if it existed on CPAN. Jost
+       discovered this was broken. Fixed by replacing an expand() by
+       instance() for distributions in expandany.
+
+2000-09-05  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * undelay: After a jumpqueue we must not continue because success
+       is unlikely. We set $self->{later} and the queuerunner calls
+       undelay.
+
+       * Bundle::inst_file: reviewed the code after Jost pointed out that
+       it was suspectly formatted. Re-enabled the newer, better code that
+       allows for multi-level Bundle package names.
+
+       * Distribution::install: improved wording for the case where make
+       failed (Thanks To Jost Krieger for spotting)
+
+       * Bundle::as_string: CONTAINS was rendered as ARRAY(...)
+
+       * expandany: added a scan for bundles as one could not install
+       bundles immediately after program start but only after a "b"
+       command (Thanks to Jost Krieger for the bugreport)
+
+       * color_cmd_tmps: protection against deep recursion with a panic
+       message.
+
+       * expand: temporary introduced the "=" hack to eval code on the
+       command line repeatedly. Now disabled again to prevent surprise.
+       But as a reminder, I did run this command successfully before
+       disabling:
+
+       cpan> m '=length($self->id)==16 && substr($self->id,12,2) eq "::"'
+       Module          Bundle::HTML::EP (N/A)
+       Module          Games::Cards::Tk (A/AK/AKARGER/Games-Cards-1.45.tar.gz)
+       Module          Games::Worms::PS (S/SB/SBURKE/Games-Worms-0.61.tar.gz)
+       Module          Games::Worms::Tk (S/SB/SBURKE/Games-Worms-0.61.tar.gz)
+       Module          Lingua::Stem::En (S/SN/SNOWHARE/Lingua-Stem-0.40.tar.gz)
+
+       * color_cmd_tmps: we're now coloring all objects when they enter
+       the queue and we uncolor them when a command is finished. We just
+       need a hook now to check if we really uncolored them all. What
+       should the hook be? i ="$self->{incommandcolor}>0"
+
+2000-09-04  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * color_cmd_tmps: rename the method reset_badtestcnt to
+       color_cmd_tmps because it turns out to be the right place to reset
+       sponsored_mods and maybe install_failed too, and if we mark them
+       as dirty when used and as clean when reset, we might even succeed
+       to have a tidy kitchen.
+
+       * untar: backed out the preference towards Archive::Tar. It seems
+       from reports I get and one hiccups I witnessed myself that
+       Archive::Tar is not stable (sorry, no bugreport available). With
+       the current state of CPAN.pm we cannot afford the additional risk
+       from an external source.
+
+       * Queue: backed out the change from string based queue to object
+       based queue. I made some mistakes during transition and everything
+       stopped working. This seemed the easiest way out.
+
+       * reset_testcnt: introduced attribute badtestcnt for Modules,
+       Bundles, and Distributions and method reset_badtestcnt to get rid
+       of that counter before and after a command. During the command we
+       inc the counter on unsuccessful make test commands. But we do not
+       reset unknown dependencies. During 'make test' we up this counter
+       if test fails and consequently do not repeat the testing. This
+       should now safe much time if, say LWP tests fail and we have all
+       of WWW::RobotRules, File::Listing, LWP, HTTP::Negotiate,
+       HTML::Form, and LWP::Simple in a Bundle or reach the stuff via a
+       dependency. Former versions would have repeated the testing ad
+       nauseam. We now refuse on the second occasion and the user may be
+       required to run something to finish building.
+
+       * prereq_pm: split of method needs_prereq into unsat_prereq_pm and
+       prereq_pm and letting the prereq_pm be stored in the object
+
+       * cpl: added readme and dump to the list of supported keywords for
+       completion
+
+       * POD: documented the dump command in the debugging section of the
+       manpage. Simplified the debugging section.
+
+       * changed queue to work with objects instead of object IDs
+       making it more natural to deal with them. Having the string
+       representation there bit me several times in the past. At the same
+       time shuffled some code from the queue-running loop to the
+       queue-constructing loop thus catching errors before starting to
+       work on the queue.
+
+       * renamed dotdot_onreload to paintdots_onreload. Changed $redef
+       from global to lexical.
+
+       * lib/CPAN.pm (dump): made dump more userfriendly by adding a
+       print statement, it is now a regular command to type C<dump
+       Net::FTP>. But still left undocumented to augment comments from
+       those who read the ChangeLog (That's you:)
+
+2000-09-03  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * heavy re-structuring of Metadata in memory with high potential
+       for breakage. All metadata are now split into a readonly and a
+       read-write part and all objects have a pointer to the readonly
+       part. The Metadata cache logic stores only the readonly part, so
+       that no session-specific data will ever be found again in a future
+       session.
+
+       * AUTOLOAD: removed the autoloader support that was never used and
+       seems not very intersting anymore with today's hardware. RCS: 1.325
+
+       * removed all the %vd comments.
+
+       * shortened all lines longer than 80 characters to make future
+       patches better readable.
+
+       * read_metadata_cache: Introduced protocol version number for
+       Metadata.
+
+       * removing a 'no strict' around the shell loop I do not recall the
+       reason of.
+
+       * lib/CPAN.pm: Folding two occurrances of use vars into one.
+
+2000-09-01  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN.pm (readable): After release spotted en error in the
+       FAQ about not being root. Improved it a little, added another FAQ
+       and gave it the VERSION 1.57_57.
+
+       * Releasing as 1.57_56 as candidate for 5.7.0
+
+       * missing_config_data and FirstTime: declared cache_metadata as
+       not yet stable enough to turn it on per default. The reason is
+       that I want the official external data from CPAN and the generated
+       internal data from the current session clearly separated and this
+       will take another working session that I cannot provide before
+       5.7.0.
+
+2000-08-31  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * POD: Added two FAQs about not being root and about the look
+       command.
+
+       * Replaced all backticks that were misused in documentation or
+       dialogs as pretty left quotes by single ticks. I think it was
+       Markus Kuhn who said so.
+
+       * float2vv: added conversion of float to visible v-string for
+       comparisons. Added some tests too.
+
+       * MD5_check_file: Now die instead of print when the MD5 checksum
+       mismatches.
+
+       * untar and unzip: preferring Archive::Tar now that it works
+       again. Adding extra security check by testing for absolute path
+       and updir.
+
+       * unzip_me: made it symmetrical to untar_me and added a few Signal
+       checkers to both.
+
+       * hosteasy/hard/hardest: now checking for $Signal and giving up in
+       several places within the download loop. Thanks for the suggestion
+       to Johan Vromans. I'd be ready to ask a question where to continue
+       but it turns out to need careful wording because the loop is
+       deeply nested: method, host, and within the methods LWP/Net::FTP
+       or lynx/ncftpget/ncftp. Simple wording might cause more grief than
+       just giving up.
+
+       * localize: now setting $ENV for proxies if config has values for
+       them. Thanks for the bugreport to Johan Vromans.
+
+       * checklock: changed comment in the code
+
+2000-08-30  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Applied 2 doc patches by Elaine and Jarkko.
+
+       * Call to force now wants a first argument and this was not there.
+       This was the reason why force DIST didn't work. Thanks to Jost
+       Krieger for the bugreport.
+
+       * install /xyz/ always needlessly went down the wrong path of
+       trying to download "/xyz/". We're now catching this mistake
+       earlier. Thanks to Jost Krieger for he idea.
+
+       * changed the messages on a failure of make in test and install
+       from "Oops" to something much more certifying. Thanks to Jost
+       Krieger for the idea.
+
+       * in vcmp short circuit for equality for speedup. Thanks to Jost
+       Krieger for the idea.
+
+2000-08-27  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing as 1.57_53 without enough testing in the hope that I
+       can test more the next days and maybe others can test a little.
+
+       * CPAN::Distribution did not handle the force_update attribute
+       correctly: it was never reset to false. Tried to fix that at the
+       end of sub install and by limiting the scope of the force_update
+       attribute to install, not to make anymore. Thirdly, the places
+       where we leave the make, test or install by means of the signal
+       handler, we also reset force.
+
+       * Added a test for CPAN::Version::vcmp.
+
+       * lib/CPAN/FirstTime.pm (init): corrected spelling (Thanks to Ask
+       B. Hansen)
+
+2000-08-25  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * rd_modpacks: track deletes on every reread, otherwise the
+       metadatacache won't forget a thing ever.
+
+       * Fixing Distribution->clean which was broken in that it set
+       "force_update" leading to a mess when the user later tried to
+       build this dist again. Thanks to Jost Krieger for spotting this.
+
+       * Minor cleanups
+
+       * CPAN::Version::readable now picks the head of the string
+
+       * Storable::store => nstore. Thanks to Tim Jenness for the hint
+
+2000-08-21  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Detected code duplication in CPAN::Shell::o and
+       CPAN::Config::edit. Moved everything to CPAN::Config::prettyprint
+
+       * Introduced package CPAN::Version which fixed and extended the
+       support for v-strings. Old perls should not be affected at all and
+       new perls should be protected against broken displays. New perls
+       should also "do the right thing" as soon as the index files write
+       "v1.0" for the literal v1.0 . Seems now feature-complete to me.
+       Next thing to do is upgrade PAUSE and see what happens.
+
+       * Applied a patch by Slaven Rezic to allow cacheing of the
+       metadata from the index files via Storable.
+
+2000-08-16  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Fixed numerous chdir that were not checked for success.
+
+2000-08-13  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Thought about v-strings and their impact. Marked the relevant
+       places in the code with "%vd" and applied some more or less simple
+       changes to try a few things out. See Todo for a few memo
+       sentences. At least diagnostics.pm is now reported fine as 1.0
+       again.
+
+       * Added support for Archive::Zip. The less external programs
+       needed the better (?)
+
+2000-08-11  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Changed all occurrences of $ in regular expressions to (?!\n)\Z
+       which is a 5.004-save equivalent of \z. Thus patch 5406 to the
+       perl core is re-integrated after it had been thrown out on
+       2000-03-25.
+
+       * isa_perl logic was duplicated in CPAN::Distribution::isa_perl
+       and in CPAN::Shell::_binary_extensions. Made the latter use the
+       former. Also extended the Distribution object with CPAN_COMMENT
+       that can be set from the "02..." index file. If that comment
+       matches /isa_perl\(.+?\)/, then it is a perl and $1 is the
+       version.
+
+2000-08-01  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Quick bugfix release 1.56. Thanks to Bruce Barnett <barnett
+       birch.crd.ge.com> who showed me that I had forgotten debugging
+       statements in the CPAN::Module::inst_version method reminding me
+       also that unpatched 5.6.0 still produces warnings where it
+       shouldn't. A quick fix is in and I release that as 1.56
+       immediately.
+
+2000-07-30  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Made completion output for a,b,d,m sorted. I have no idea when
+       this sorting was lost or if it ever was there.
+
+       * Set version number to 1.55 and going to release today or
+       tomorrow after testing.
+
+       * o conf was not prepared for hash refs.
+
+       * Fixed propagation of error report during Bundle installation.
+       Until now recursive bundles reported each bundle's faiures
+       separately. Now callers in addition report what called bundles
+       reported. This still doesn't seem perfect because the report can
+       come too early but at least it is better now than it was and if
+       one reruns the install command on a bundle, the report will be
+       correct on the second run.
+
+2000-07-29  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Applied a patch by Daniel Muiño <dmuino@afip.gov.ar> that was
+       submitted to p5p where a my($msg) declaration was conditional.
+
+       * Applied a patch by Anno Siegel who encountered a rarely seen bug
+       in the download logic wrt. gzipped vs. not gzipped downloads. He
+       cleaned up the variable names too in that area and I cleaned some
+       more variable names after him. I believe, the variable names there
+       were really inappropriate/misleading.
+
+       * Following a suggestion by Michael G. Schwern, I made "ask" the
+       default for prerequisites_policy. The old default of "follow"
+       seemed to intimidate some new users, he said, and I agree, the
+       default should be as little intrusive as possible while still
+       being useful. "ask" seems the right choice for a first time user.
+
+2000-06-23  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Replaced the undocumented old semantics of
+       C<$CPAN::Dontload{"Compress::Zlib"} = undef;> in favor of the more
+       natural C<$CPAN::Config->{"dontload_hash"}{"Compress::Zlib"} = 1;>
+       and documented that.
+
+       * Eliminated all occurrances of E<39> in the POD because
+       pod2html has a bug that mistreats them and we do not really
+       need them. Thanks to Daniel S. Lewart for reporting his.
+
+2000-06-18  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * The "a" command now always converts its arguments to uppercase.
+
+2000-06-17  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Introduced has_usable which is pickier than has_inst. Thanks to
+       a report by Ian Phillipps who reported the Net::FTP/Net::Config
+       connection: e.g. upgrading the processor deprecates Net::Config
+       but not Net::FTP.
+
+       * Applied a patch by Ben Tilly that changed the exception of
+       isa_perl in CPAN::Distribution::make() from dying to warning so
+       that bundles can continue if they contain core modules.
+
+2000-04-15  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Thanks to "Magnus Ullberg" <mullberg@hotmail.com> who reported
+       that configuring lynx with arguments actually works, so I
+       documented it in the firewall section.
+
+2000-03-28  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Change ${DISTVNAME} to $(DISTVNAME) in the Makefile.PL because
+       nmake can't deal with the former. Thanks to David P. Mott
+       <dpmott@sep.com> for the report.
+
+2000-03-25  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Change all \z back to $ because \z is not in perl5.004_05.
+       Thanks to Paul Schinder <schinder@pobox.com> for the report.
+       Update: Later Ronald Kimball posted the better solution to P5P. He
+       said "'\z' is equivalent to '(?!\n)\Z' and '\Z(?!\n)', which
+       should work under 5.004."
+
+2000-03-22  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Both Andrew Speer <andrew.speer@isolutions.com.au> and Michael
+       G. Schwern <schwern@pobox.com> sent me a patch to the effect that
+       version numbers in PREREQ_PM are honoured. Till now we installed
+       the newest version for all PREREQ_PMs. I applied a mishmash of the
+       two patches.
+
+2000-03-20  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Found bug in the changes made on 03-14, the return value of
+       &CPAN::Config::edit must be true.
+
+2000-03-17  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * lib/CPAN.pm: no lib "."; since we do a lot of chdirs *and* do a
+       lot of demand-loading, we need to prune the current directory. I
+       wonder how everything could work so smoothely with the default
+       INC path.
+
+2000-03-14  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Editing the $CPAN::Config hashref had always tried to keep the
+       type of hash values but that was errorprone. Switched to matching
+       /list\z/ in the key instead.
+
+       * Changing the urllist now triggers resetting of Thesite and
+       Themethod. Maybe this needs a more general solution that resets
+       any cache of any variable, but for testing the effect, I start
+       with these two.
+
+2000-03-11  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Added an FAQ section to the manpage. First 2 Fs deal with
+       UNINST=1.
+
+2000-03-10  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Updated the isa_perl checks to match 5.6.0 style.
+
+       * The 02modules... file is now verified against its Line-Count
+       header. The other index files need new headers to verify them.
+
+       * Without any net access we did not make it through the
+       configuration dialog. Fixed now.
+
+       * Apply patches 4416, 4419, 5406 and 5409 from perl-5.6.0
+       candidate.
+
+2000-01-08  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Releasing 1.52 which is a pure bugfix release. New functionality
+       is there but not used or not documented. Should be very stable.
+
+2000-01-03  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Added a CPAN::Distribution::containsmods method that lists all
+       modules within a distribution.
+
+       * reload index now removes the whole old index. No, wait a minute,
+       that's stupid. We want to keep session info. This is just a
+       temporary measure to improve debugging. What we need is "wipe
+       index" or some such and we need it for debugging only. [Backed out]
+
+       * Text::Wrapping output of "o debug".
+
+       * Fixed an uninitialized warning in CPAN::Shell::expand()
+
+       * Protected call to close() in DESTROY with "if defined".
+
+       * Allow "#" comments in a bundle definition section.
+
+       * Text::Wrapping bundle install summary.
+
+2000-01-02  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Overhauled the help page that gets output on "h", documented
+       "get", undocumented "install r", it never worked (Thanks to Peder
+       Stray <pederst@ifi.uio.no> for spotting)
+
+       * ncftpget made to work again by changing directory before
+       downloading (spotted aeons ago by Jarkko Hietaniemi)
+
+1999-12-31  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Applied a patch by Paul Schinder <schinder@pobox.com> which
+       corrects the computation of disk usage on the Mac.
+
+1999-12-29  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Increased 30 to 60 in FirstTime where we "protect" against old
+       MIRRORED.BY files and protect against endless loop if MIRRORED.BY
+       remains older. Thanks for spotting the bug to James P. Goltz
+       <goltz@nfr.net>.
+       
+       * Applied patch from Doug MacEachern that implements cvs_import
+       without documentation.
+
+1999-10-26  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Joe Schell <jschell@peakss.com> sent me a fix that disabled
+       processing of bundles on NT.
+
+1999-10-15  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Fixed a typo reported by Stas Bekman <sbekman@iil.intel.com>
+
+1999-10-01  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Added a posting by Larry as a comment to rethink use of
+       $SIG{__DIE__}
+
+1999-08-01  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Applied a patch by 1999-06-13 Adrian Aichner
+       <aichner@ecf.teradyne.com>
+        (hosthardest): Initialize $netrcfile with $netrc->netrc.
+        (untar): Attempt piping gzip output to tar irregardless of
+       $OSNAME. Run commands separately in case of error.
+
+       * Applied a patch from Ilya Zakharevich <ilya@math.ohio-state.edu>
+       for unbuffering STDOUT and STDERR to get sane behavior in pipes.
+
+1999-07-30  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Fixed a floating point issue that came up with DBD::ADO. See
+       stringify comment in CPAN::Module::inst_version. Thanks to Lupe
+       Christoph <lupe@lupe-christoph.de> and Michael G. Schwern
+       <schwern@pobox.com> for the reports and Tim Bunce
+       <Tim.Bunce@ig.co.uk> for the suggestion how to fix.
+
+       * Fixed my email address in the manpage
+
+1999-07-28  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * CPAN::Nox was broken, probably since 5.005's new AUTOLOAD
+       behavior. Thanks to Marc Lehmann <pcg@goof.com> for the report.
+
+1999-05-23  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * The force pragma no longer removes its record of prerequisites
+       that it has already dealt with. This removes a potential for
+       infinite loops when force is in effect.
+
+       * Added a CPAN::InfoObj::dump method that can be used like so:
+       ! print expand("Distribution","JWIED/DBD-CSV-0.1021.tar.gz")->dump
+       or
+       ! print expand("Module","DBD::CSV")->dump
+       Not particularly userfriendly, thus left undocumented.
+
+       * Added a check if Makefile.PL really wrote a Makefile.
+
+1999-05-22  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Applied another patch by Ilya for return value of gzreadline
+       with regard to -1: <19990522144647.A15778@monk.mps.ohio-state.edu>
+
+       * Applied Ilya's patch for MD5_check_file for READ returning -1.
+
+1999-05-08  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Improved error message if cpan_home can't be created (bug report
+       by Jarkko Hietaniemi <jhi@iki.fi>)
+
+1999-04-19  Andreas J. Koenig  <andreas.koenig@anima.de>
+
+       * Added a note about the correct format of file URLs
+
+       * Added documentation to CPAN.pm for how to write cronjobs that
+       watch The CPAN (thanks to Brian Moseley <ix@cp.net> for asking)
+
+       * FirstTime: initialize urllist to be an empty array, because
+       otherwise it could accidentally become a string
+
+       * Renamed Changes file to ChangeLog and switched format to
+       emacsens ChangeLog format
+
+\f
+       Local Variables:
+       coding:utf-8
+       End:
index 578a5bd..8a1724a 100644 (file)
@@ -18,7 +18,7 @@ use File::Basename ();
 use File::Path ();
 use File::Spec;
 use vars qw($VERSION);
-$VERSION = substr q$Revision: 1.56 $, 10;
+$VERSION = substr q$Revision: 1.58 $, 10;
 
 =head1 NAME
 
@@ -48,7 +48,7 @@ sub init {
     local($\) = "";
     local($|) = 1;
 
-    my($ans,$default,$local,$cont,$url,$expected_size);
+    my($ans,$default);
 
     #
     # Files, directories
@@ -117,6 +117,14 @@ First of all, I\'d like to create this directory. Where?
 
     $default = $cpan_home;
     while ($ans = prompt("CPAN build and cache directory?",$default)) {
+      unless (File::Spec->file_name_is_absolute($ans)) {
+        require Cwd;
+        my $cwd = Cwd::cwd();
+        my $absans = File::Spec->catdir($cwd,$ans);
+        warn "The path '$ans' is not an absolute path. Please specify an absolute path\n";
+        $default = $absans;
+        next;
+      }
       eval { File::Path::mkpath($ans); }; # dies if it can't
       if ($@) {
        warn "Couldn't create directory $ans.
@@ -218,6 +226,32 @@ will be output in UTF-8.
     $CPAN::Config->{term_is_latin} = ($ans =~ /^\s*y/i ? 1 : 0);
 
     #
+    # save history in file histfile
+    #
+    print qq{
+
+If you have one of the readline packages (Term::ReadLine::Perl,
+Term::ReadLine::Gnu, possibly others) installed, the interactive CPAN
+shell will have history support. The next two questions deal with the
+filename of the history file and with its size. If you do not want to
+set this variable, please hit SPACE RETURN to the following question.
+
+};
+
+    defined($default = $CPAN::Config->{histfile}) or
+        $default = File::Spec->catfile($CPAN::Config->{cpan_home},"histfile");
+    $ans = prompt("File to save your history?", $default);
+    $ans =~ s/^\s+//;
+    $ans =~ s/\s+\z//;
+    $CPAN::Config->{histfile} = $ans;
+
+    if ($CPAN::Config->{histfile}) {
+      defined($default = $CPAN::Config->{histsize}) or $default = 100;
+      $ans = prompt("Number of lines to save?", $default);
+      $CPAN::Config->{histsize} = $ans;
+    }
+
+    #
     # prerequisites_policy
     # Do we follow PREREQ_PM?
     #
@@ -519,33 +553,33 @@ sub picklist {
     my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
     $default ||= '';
 
-       my $pos = 0;
+    my $pos = 0;
 
     my @nums;
     while (1) {
 
-               # display, at most, 15 items at a time
-               my $limit = $#{ $items } - $pos;
-               $limit = 15 if $limit > 15;
-
-               # show the next $limit items, get the new position
-               $pos = display_some($items, $limit, $pos);
-               $pos = 0 if $pos >= @$items;
-
-               my $num = prompt($prompt,$default);
-               
-               @nums = split (' ', $num);
-               my $i = scalar @$items;
-               (warn "invalid items entered, try again\n"), next
-                   if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
-               if ($require_nonempty) {
-                   (warn "$empty_warning\n");
-               }
-       print "\n";
-
-               # a blank line continues...
-               next unless @nums;
-               last;
+        # display, at most, 15 items at a time
+        my $limit = $#{ $items } - $pos;
+        $limit = 15 if $limit > 15;
+
+        # show the next $limit items, get the new position
+        $pos = display_some($items, $limit, $pos);
+        $pos = 0 if $pos >= @$items;
+
+        my $num = prompt($prompt,$default);
+
+        @nums = split (' ', $num);
+        my $i = scalar @$items;
+        (warn "invalid items entered, try again\n"), next
+            if grep (/\D/ || $_ < 1 || $_ > $i, @nums);
+        if ($require_nonempty) {
+            (warn "$empty_warning\n");
+        }
+        print "\n";
+
+        # a blank line continues...
+        next unless @nums;
+        last;
     }
     for (@nums) { $_-- }
     @{$items}[@nums];
@@ -559,7 +593,10 @@ sub display_some {
     for my $item (@displayable) {
                printf "(%d) %s\n", ++$pos, $item;
     }
-       printf "%d more items, hit ENTER\n", (@$items - $pos) if $pos < @$items;
+       printf("%d more items, hit SPACE RETURN to show them\n",
+               (@$items - $pos)
+              )
+            if $pos < @$items;
        return $pos;
 }
 
@@ -643,8 +680,8 @@ http: -- that host a CPAN mirror.
         }
     }
     push (@urls, map ("$_ (previous pick)", @previous_urls));
-    my $prompt = "Select as many URLs as you like,
-put them on one line, separated by blanks";
+    my $prompt = "Select as many URLs as you like (by number),
+put them on one line, separated by blanks, e.g. '1 4 5'";
     if (@previous_urls) {
        $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
                              (scalar @urls));
@@ -669,6 +706,8 @@ Please enter your CPAN site:};
         $ans = prompt ($prompt, "");
 
         if ($ans) {
+            $ans =~ s/^\s+//;  # no leading spaces
+            $ans =~ s/\s+\z//; # no trailing spaces
             $ans =~ s|/?\z|/|; # has to end with one slash
             $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
             if ($ans =~ /^\w+:\/./) {
diff --git a/lib/CPAN/README b/lib/CPAN/README
new file mode 100644 (file)
index 0000000..c1287e1
--- /dev/null
@@ -0,0 +1,1006 @@
+NAME
+    CPAN - query, download and build perl modules from CPAN sites
+
+SYNOPSIS
+    Interactive mode:
+
+      perl -MCPAN -e shell;
+
+    Batch mode:
+
+      use CPAN;
+
+      autobundle, clean, install, make, recompile, test
+
+STATUS
+    This module will eventually be replaced by CPANPLUS. CPANPLUS is kind of
+    a modern rewrite from ground up with greater extensibility and more
+    features but no full compatibility. If you're new to CPAN.pm, you
+    probably should investigate if CPANPLUS is the better choice for you. If
+    you're already used to CPAN.pm you're welcome to continue using it, if
+    you accept that its development is mostly (though not completely)
+    stalled.
+
+DESCRIPTION
+    The CPAN module is designed to automate the make and install of perl
+    modules and extensions. It includes some searching capabilities and
+    knows how to use Net::FTP or LWP (or lynx or an external ftp client) to
+    fetch the raw data from the net.
+
+    Modules are fetched from one or more of the mirrored CPAN (Comprehensive
+    Perl Archive Network) sites and unpacked in a dedicated directory.
+
+    The CPAN module also supports the concept of named and versioned
+    *bundles* of modules. Bundles simplify the handling of sets of related
+    modules. See Bundles below.
+
+    The package contains a session manager and a cache manager. There is no
+    status retained between sessions. The session manager keeps track of
+    what has been fetched, built and installed in the current session. The
+    cache manager keeps track of the disk space occupied by the make
+    processes and deletes excess space according to a simple FIFO mechanism.
+
+    For extended searching capabilities there's a plugin for CPAN available,
+    "CPAN::WAIT". "CPAN::WAIT" is a full-text search engine that indexes all
+    documents available in CPAN authors directories. If "CPAN::WAIT" is
+    installed on your system, the interactive shell of CPAN.pm will enable
+    the "wq", "wr", "wd", "wl", and "wh" commands which send queries to the
+    WAIT server that has been configured for your installation.
+
+    All other methods provided are accessible in a programmer style and in
+    an interactive shell style.
+
+  Interactive Mode
+    The interactive mode is entered by running
+
+        perl -MCPAN -e shell
+
+    which puts you into a readline interface. You will have the most fun if
+    you install Term::ReadKey and Term::ReadLine to enjoy both history and
+    command completion.
+
+    Once you are on the command line, type 'h' and the rest should be
+    self-explanatory.
+
+    The function call "shell" takes two optional arguments, one is the
+    prompt, the second is the default initial command line (the latter only
+    works if a real ReadLine interface module is installed).
+
+    The most common uses of the interactive modes are
+
+    Searching for authors, bundles, distribution files and modules
+      There are corresponding one-letter commands "a", "b", "d", and "m" for
+      each of the four categories and another, "i" for any of the mentioned
+      four. Each of the four entities is implemented as a class with
+      slightly differing methods for displaying an object.
+
+      Arguments you pass to these commands are either strings exactly
+      matching the identification string of an object or regular expressions
+      that are then matched case-insensitively against various attributes of
+      the objects. The parser recognizes a regular expression only if you
+      enclose it between two slashes.
+
+      The principle is that the number of found objects influences how an
+      item is displayed. If the search finds one item, the result is
+      displayed with the rather verbose method "as_string", but if we find
+      more than one, we display each object with the terse method
+      <as_glimpse>.
+
+    make, test, install, clean modules or distributions
+      These commands take any number of arguments and investigate what is
+      necessary to perform the action. If the argument is a distribution
+      file name (recognized by embedded slashes), it is processed. If it is
+      a module, CPAN determines the distribution file in which this module
+      is included and processes that, following any dependencies named in
+      the module's Makefile.PL (this behavior is controlled by
+      *prerequisites_policy*.)
+
+      Any "make" or "test" are run unconditionally. An
+
+        install <distribution_file>
+
+      also is run unconditionally. But for
+
+        install <module>
+
+      CPAN checks if an install is actually needed for it and prints *module
+      up to date* in the case that the distribution file containing the
+      module doesn't need to be updated.
+
+      CPAN also keeps track of what it has done within the current session
+      and doesn't try to build a package a second time regardless if it
+      succeeded or not. The "force" command takes as a first argument the
+      method to invoke (currently: "make", "test", or "install") and
+      executes the command from scratch.
+
+      Example:
+
+          cpan> install OpenGL
+          OpenGL is up to date.
+          cpan> force install OpenGL
+          Running make
+          OpenGL-0.4/
+          OpenGL-0.4/COPYRIGHT
+          [...]
+
+      A "clean" command results in a
+
+        make clean
+
+      being executed within the distribution file's working directory.
+
+    get, readme, look module or distribution
+      "get" downloads a distribution file without further action. "readme"
+      displays the README file of the associated distribution. "Look" gets
+      and untars (if not yet done) the distribution file, changes to the
+      appropriate directory and opens a subshell process in that directory.
+
+    ls author
+      "ls" lists all distribution files in and below an author's CPAN
+      directory. Only those files that contain modules are listed and if
+      there is more than one for any given module, only the most recent one
+      is listed.
+
+    Signals
+      CPAN.pm installs signal handlers for SIGINT and SIGTERM. While you are
+      in the cpan-shell it is intended that you can press "^C" anytime and
+      return to the cpan-shell prompt. A SIGTERM will cause the cpan-shell
+      to clean up and leave the shell loop. You can emulate the effect of a
+      SIGTERM by sending two consecutive SIGINTs, which usually means by
+      pressing "^C" twice.
+
+      CPAN.pm ignores a SIGPIPE. If the user sets inactivity_timeout, a
+      SIGALRM is used during the run of the "perl Makefile.PL" subprocess.
+
+  CPAN::Shell
+    The commands that are available in the shell interface are methods in
+    the package CPAN::Shell. If you enter the shell command, all your input
+    is split by the Text::ParseWords::shellwords() routine which acts like
+    most shells do. The first word is being interpreted as the method to be
+    called and the rest of the words are treated as arguments to this
+    method. Continuation lines are supported if a line ends with a literal
+    backslash.
+
+  autobundle
+    "autobundle" writes a bundle file into the
+    "$CPAN::Config->{cpan_home}/Bundle" directory. The file contains a list
+    of all modules that are both available from CPAN and currently installed
+    within @INC. The name of the bundle file is based on the current date
+    and a counter.
+
+  recompile
+    recompile() is a very special command in that it takes no argument and
+    runs the make/test/install cycle with brute force over all installed
+    dynamically loadable extensions (aka XS modules) with 'force' in effect.
+    The primary purpose of this command is to finish a network installation.
+    Imagine, you have a common source tree for two different architectures.
+    You decide to do a completely independent fresh installation. You start
+    on one architecture with the help of a Bundle file produced earlier.
+    CPAN installs the whole Bundle for you, but when you try to repeat the
+    job on the second architecture, CPAN responds with a "Foo up to date"
+    message for all modules. So you invoke CPAN's recompile on the second
+    architecture and you're done.
+
+    Another popular use for "recompile" is to act as a rescue in case your
+    perl breaks binary compatibility. If one of the modules that CPAN uses
+    is in turn depending on binary compatibility (so you cannot run CPAN
+    commands), then you should try the CPAN::Nox module for recovery.
+
+  The four "CPAN::*" Classes: Author, Bundle, Module, Distribution
+    Although it may be considered internal, the class hierarchy does matter
+    for both users and programmer. CPAN.pm deals with above mentioned four
+    classes, and all those classes share a set of methods. A classical
+    single polymorphism is in effect. A metaclass object registers all
+    objects of all kinds and indexes them with a string. The strings
+    referencing objects have a separated namespace (well, not completely
+    separated):
+
+             Namespace                         Class
+
+       words containing a "/" (slash)      Distribution
+        words starting with Bundle::          Bundle
+              everything else            Module or Author
+
+    Modules know their associated Distribution objects. They always refer to
+    the most recent official release. Developers may mark their releases as
+    unstable development versions (by inserting an underbar into the module
+    version number which will also be reflected in the distribution name
+    when you run 'make dist'), so the really hottest and newest distribution
+    is not always the default. If a module Foo circulates on CPAN in both
+    version 1.23 and 1.23_90, CPAN.pm offers a convenient way to install
+    version 1.23 by saying
+
+        install Foo
+
+    This would install the complete distribution file (say
+    BAR/Foo-1.23.tar.gz) with all accompanying material. But if you would
+    like to install version 1.23_90, you need to know where the distribution
+    file resides on CPAN relative to the authors/id/ directory. If the
+    author is BAR, this might be BAR/Foo-1.23_90.tar.gz; so you would have
+    to say
+
+        install BAR/Foo-1.23_90.tar.gz
+
+    The first example will be driven by an object of the class CPAN::Module,
+    the second by an object of class CPAN::Distribution.
+
+  Programmer's interface
+    If you do not enter the shell, the available shell commands are both
+    available as methods ("CPAN::Shell->install(...)") and as functions in
+    the calling package ("install(...)").
+
+    There's currently only one class that has a stable interface -
+    CPAN::Shell. All commands that are available in the CPAN shell are
+    methods of the class CPAN::Shell. Each of the commands that produce
+    listings of modules ("r", "autobundle", "u") also return a list of the
+    IDs of all modules within the list.
+
+    expand($type,@things)
+      The IDs of all objects available within a program are strings that can
+      be expanded to the corresponding real objects with the
+      "CPAN::Shell->expand("Module",@things)" method. Expand returns a list
+      of CPAN::Module objects according to the @things arguments given. In
+      scalar context it only returns the first element of the list.
+
+    expandany(@things)
+      Like expand, but returns objects of the appropriate type, i.e.
+      CPAN::Bundle objects for bundles, CPAN::Module objects for modules and
+      CPAN::Distribution objects fro distributions.
+
+    Programming Examples
+      This enables the programmer to do operations that combine
+      functionalities that are available in the shell.
+
+          # install everything that is outdated on my disk:
+          perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'
+
+          # install my favorite programs if necessary:
+          for $mod (qw(Net::FTP Digest::MD5 Data::Dumper)){
+              my $obj = CPAN::Shell->expand('Module',$mod);
+              $obj->install;
+          }
+
+          # list all modules on my disk that have no VERSION number
+          for $mod (CPAN::Shell->expand("Module","/./")){
+              next unless $mod->inst_file;
+              # MakeMaker convention for undefined $VERSION:
+              next unless $mod->inst_version eq "undef";
+              print "No VERSION in ", $mod->id, "\n";
+          }
+
+          # find out which distribution on CPAN contains a module:
+          print CPAN::Shell->expand("Module","Apache::Constants")->cpan_file
+
+      Or if you want to write a cronjob to watch The CPAN, you could list
+      all modules that need updating. First a quick and dirty way:
+
+          perl -e 'use CPAN; CPAN::Shell->r;'
+
+      If you don't want to get any output in the case that all modules are
+      up to date, you can parse the output of above command for the regular
+      expression //modules are up to date// and decide to mail the output
+      only if it doesn't match. Ick?
+
+      If you prefer to do it more in a programmer style in one single
+      process, maybe something like this suits you better:
+
+        # list all modules on my disk that have newer versions on CPAN
+        for $mod (CPAN::Shell->expand("Module","/./")){
+          next unless $mod->inst_file;
+          next if $mod->uptodate;
+          printf "Module %s is installed as %s, could be updated to %s from CPAN\n",
+              $mod->id, $mod->inst_version, $mod->cpan_version;
+        }
+
+      If that gives you too much output every day, you maybe only want to
+      watch for three modules. You can write
+
+        for $mod (CPAN::Shell->expand("Module","/Apache|LWP|CGI/")){
+
+      as the first line instead. Or you can combine some of the above
+      tricks:
+
+        # watch only for a new mod_perl module
+        $mod = CPAN::Shell->expand("Module","mod_perl");
+        exit if $mod->uptodate;
+        # new mod_perl arrived, let me know all update recommendations
+        CPAN::Shell->r;
+
+  Methods in the other Classes
+    The programming interface for the classes CPAN::Module,
+    CPAN::Distribution, CPAN::Bundle, and CPAN::Author is still considered
+    beta and partially even alpha. In the following paragraphs only those
+    methods are documented that have proven useful over a longer time and
+    thus are unlikely to change.
+
+    CPAN::Author::as_glimpse()
+        Returns a one-line description of the author
+
+    CPAN::Author::as_string()
+        Returns a multi-line description of the author
+
+    CPAN::Author::email()
+        Returns the author's email address
+
+    CPAN::Author::fullname()
+        Returns the author's name
+
+    CPAN::Author::name()
+        An alias for fullname
+
+    CPAN::Bundle::as_glimpse()
+        Returns a one-line description of the bundle
+
+    CPAN::Bundle::as_string()
+        Returns a multi-line description of the bundle
+
+    CPAN::Bundle::clean()
+        Recursively runs the "clean" method on all items contained in the
+        bundle.
+
+    CPAN::Bundle::contains()
+        Returns a list of objects' IDs contained in a bundle. The associated
+        objects may be bundles, modules or distributions.
+
+    CPAN::Bundle::force($method,@args)
+        Forces CPAN to perform a task that normally would have failed. Force
+        takes as arguments a method name to be called and any number of
+        additional arguments that should be passed to the called method. The
+        internals of the object get the needed changes so that CPAN.pm does
+        not refuse to take the action. The "force" is passed recursively to
+        all contained objects.
+
+    CPAN::Bundle::get()
+        Recursively runs the "get" method on all items contained in the
+        bundle
+
+    CPAN::Bundle::inst_file()
+        Returns the highest installed version of the bundle in either @INC
+        or "$CPAN::Config-"{cpan_home}>. Note that this is different from
+        CPAN::Module::inst_file.
+
+    CPAN::Bundle::inst_version()
+        Like CPAN::Bundle::inst_file, but returns the $VERSION
+
+    CPAN::Bundle::uptodate()
+        Returns 1 if the bundle itself and all its members are uptodate.
+
+    CPAN::Bundle::install()
+        Recursively runs the "install" method on all items contained in the
+        bundle
+
+    CPAN::Bundle::make()
+        Recursively runs the "make" method on all items contained in the
+        bundle
+
+    CPAN::Bundle::readme()
+        Recursively runs the "readme" method on all items contained in the
+        bundle
+
+    CPAN::Bundle::test()
+        Recursively runs the "test" method on all items contained in the
+        bundle
+
+    CPAN::Distribution::as_glimpse()
+        Returns a one-line description of the distribution
+
+    CPAN::Distribution::as_string()
+        Returns a multi-line description of the distribution
+
+    CPAN::Distribution::clean()
+        Changes to the directory where the distribution has been unpacked
+        and runs "make clean" there.
+
+    CPAN::Distribution::containsmods()
+        Returns a list of IDs of modules contained in a distribution file.
+        Only works for distributions listed in the 02packages.details.txt.gz
+        file. This typically means that only the most recent version of a
+        distribution is covered.
+
+    CPAN::Distribution::cvs_import()
+        Changes to the directory where the distribution has been unpacked
+        and runs something like
+
+            cvs -d $cvs_root import -m $cvs_log $cvs_dir $userid v$version
+
+        there.
+
+    CPAN::Distribution::dir()
+        Returns the directory into which this distribution has been
+        unpacked.
+
+    CPAN::Distribution::force($method,@args)
+        Forces CPAN to perform a task that normally would have failed. Force
+        takes as arguments a method name to be called and any number of
+        additional arguments that should be passed to the called method. The
+        internals of the object get the needed changes so that CPAN.pm does
+        not refuse to take the action.
+
+    CPAN::Distribution::get()
+        Downloads the distribution from CPAN and unpacks it. Does nothing if
+        the distribution has already been downloaded and unpacked within the
+        current session.
+
+    CPAN::Distribution::install()
+        Changes to the directory where the distribution has been unpacked
+        and runs the external command "make install" there. If "make" has
+        not yet been run, it will be run first. A "make test" will be issued
+        in any case and if this fails, the install will be canceled. The
+        cancellation can be avoided by letting "force" run the "install" for
+        you.
+
+    CPAN::Distribution::isa_perl()
+        Returns 1 if this distribution file seems to be a perl distribution.
+        Normally this is derived from the file name only, but the index from
+        CPAN can contain a hint to achieve a return value of true for other
+        filenames too.
+
+    CPAN::Distribution::look()
+        Changes to the directory where the distribution has been unpacked
+        and opens a subshell there. Exiting the subshell returns.
+
+    CPAN::Distribution::make()
+        First runs the "get" method to make sure the distribution is
+        downloaded and unpacked. Changes to the directory where the
+        distribution has been unpacked and runs the external commands "perl
+        Makefile.PL" and "make" there.
+
+    CPAN::Distribution::prereq_pm()
+        Returns the hash reference that has been announced by a distribution
+        as the PREREQ_PM hash in the Makefile.PL. Note: works only after an
+        attempt has been made to "make" the distribution. Returns undef
+        otherwise.
+
+    CPAN::Distribution::readme()
+        Downloads the README file associated with a distribution and runs it
+        through the pager specified in "$CPAN::Config-"{pager}>.
+
+    CPAN::Distribution::test()
+        Changes to the directory where the distribution has been unpacked
+        and runs "make test" there.
+
+    CPAN::Distribution::uptodate()
+        Returns 1 if all the modules contained in the distribution are
+        uptodate. Relies on containsmods.
+
+    CPAN::Index::force_reload()
+        Forces a reload of all indices.
+
+    CPAN::Index::reload()
+        Reloads all indices if they have been read more than
+        "$CPAN::Config-"{index_expire}> days.
+
+    CPAN::InfoObj::dump()
+        CPAN::Author, CPAN::Bundle, CPAN::Module, and CPAN::Distribution
+        inherit this method. It prints the data structure associated with an
+        object. Useful for debugging. Note: the data structure is considered
+        internal and thus subject to change without notice.
+
+    CPAN::Module::as_glimpse()
+        Returns a one-line description of the module
+
+    CPAN::Module::as_string()
+        Returns a multi-line description of the module
+
+    CPAN::Module::clean()
+        Runs a clean on the distribution associated with this module.
+
+    CPAN::Module::cpan_file()
+        Returns the filename on CPAN that is associated with the module.
+
+    CPAN::Module::cpan_version()
+        Returns the latest version of this module available on CPAN.
+
+    CPAN::Module::cvs_import()
+        Runs a cvs_import on the distribution associated with this module.
+
+    CPAN::Module::description()
+        Returns a 44 character description of this module. Only available
+        for modules listed in The Module List
+        (CPAN/modules/00modlist.long.html or 00modlist.long.txt.gz)
+
+    CPAN::Module::force($method,@args)
+        Forces CPAN to perform a task that normally would have failed. Force
+        takes as arguments a method name to be called and any number of
+        additional arguments that should be passed to the called method. The
+        internals of the object get the needed changes so that CPAN.pm does
+        not refuse to take the action.
+
+    CPAN::Module::get()
+        Runs a get on the distribution associated with this module.
+
+    CPAN::Module::inst_file()
+        Returns the filename of the module found in @INC. The first file
+        found is reported just like perl itself stops searching @INC when it
+        finds a module.
+
+    CPAN::Module::inst_version()
+        Returns the version number of the module in readable format.
+
+    CPAN::Module::install()
+        Runs an "install" on the distribution associated with this module.
+
+    CPAN::Module::look()
+        Changes to the directory where the distribution associated with this
+        module has been unpacked and opens a subshell there. Exiting the
+        subshell returns.
+
+    CPAN::Module::make()
+        Runs a "make" on the distribution associated with this module.
+
+    CPAN::Module::manpage_headline()
+        If module is installed, peeks into the module's manpage, reads the
+        headline and returns it. Moreover, if the module has been downloaded
+        within this session, does the equivalent on the downloaded module
+        even if it is not installed.
+
+    CPAN::Module::readme()
+        Runs a "readme" on the distribution associated with this module.
+
+    CPAN::Module::test()
+        Runs a "test" on the distribution associated with this module.
+
+    CPAN::Module::uptodate()
+        Returns 1 if the module is installed and up-to-date.
+
+    CPAN::Module::userid()
+        Returns the author's ID of the module.
+
+  Cache Manager
+    Currently the cache manager only keeps track of the build directory
+    ($CPAN::Config->{build_dir}). It is a simple FIFO mechanism that deletes
+    complete directories below "build_dir" as soon as the size of all
+    directories there gets bigger than $CPAN::Config->{build_cache} (in MB).
+    The contents of this cache may be used for later re-installations that
+    you intend to do manually, but will never be trusted by CPAN itself.
+    This is due to the fact that the user might use these directories for
+    building modules on different architectures.
+
+    There is another directory ($CPAN::Config->{keep_source_where}) where
+    the original distribution files are kept. This directory is not covered
+    by the cache manager and must be controlled by the user. If you choose
+    to have the same directory as build_dir and as keep_source_where
+    directory, then your sources will be deleted with the same fifo
+    mechanism.
+
+  Bundles
+    A bundle is just a perl module in the namespace Bundle:: that does not
+    define any functions or methods. It usually only contains documentation.
+
+    It starts like a perl module with a package declaration and a $VERSION
+    variable. After that the pod section looks like any other pod with the
+    only difference being that *one special pod section* exists starting
+    with (verbatim):
+
+            =head1 CONTENTS
+
+    In this pod section each line obeys the format
+
+            Module_Name [Version_String] [- optional text]
+
+    The only required part is the first field, the name of a module (e.g.
+    Foo::Bar, ie. *not* the name of the distribution file). The rest of the
+    line is optional. The comment part is delimited by a dash just as in the
+    man page header.
+
+    The distribution of a bundle should follow the same convention as other
+    distributions.
+
+    Bundles are treated specially in the CPAN package. If you say 'install
+    Bundle::Tkkit' (assuming such a bundle exists), CPAN will install all
+    the modules in the CONTENTS section of the pod. You can install your own
+    Bundles locally by placing a conformant Bundle file somewhere into your
+    @INC path. The autobundle() command which is available in the shell
+    interface does that for you by including all currently installed modules
+    in a snapshot bundle file.
+
+  Prerequisites
+    If you have a local mirror of CPAN and can access all files with "file:"
+    URLs, then you only need a perl better than perl5.003 to run this
+    module. Otherwise Net::FTP is strongly recommended. LWP may be required
+    for non-UNIX systems or if your nearest CPAN site is associated with a
+    URL that is not "ftp:".
+
+    If you have neither Net::FTP nor LWP, there is a fallback mechanism
+    implemented for an external ftp command or for an external lynx command.
+
+  Finding packages and VERSION
+    This module presumes that all packages on CPAN
+
+    * declare their $VERSION variable in an easy to parse manner. This
+      prerequisite can hardly be relaxed because it consumes far too much
+      memory to load all packages into the running program just to determine
+      the $VERSION variable. Currently all programs that are dealing with
+      version use something like this
+
+          perl -MExtUtils::MakeMaker -le \
+              'print MM->parse_version(shift)' filename
+
+      If you are author of a package and wonder if your $VERSION can be
+      parsed, please try the above method.
+
+    * come as compressed or gzipped tarfiles or as zip files and contain a
+      Makefile.PL (well, we try to handle a bit more, but without much
+      enthusiasm).
+
+  Debugging
+    The debugging of this module is a bit complex, because we have
+    interferences of the software producing the indices on CPAN, of the
+    mirroring process on CPAN, of packaging, of configuration, of
+    synchronicity, and of bugs within CPAN.pm.
+
+    For code debugging in interactive mode you can try "o debug" which will
+    list options for debugging the various parts of the code. You should
+    know that "o debug" has built-in completion support.
+
+    For data debugging there is the "dump" command which takes the same
+    arguments as make/test/install and outputs the object's Data::Dumper
+    dump.
+
+  Floppy, Zip, Offline Mode
+    CPAN.pm works nicely without network too. If you maintain machines that
+    are not networked at all, you should consider working with file: URLs.
+    Of course, you have to collect your modules somewhere first. So you
+    might use CPAN.pm to put together all you need on a networked machine.
+    Then copy the $CPAN::Config->{keep_source_where} (but not
+    $CPAN::Config->{build_dir}) directory on a floppy. This floppy is kind
+    of a personal CPAN. CPAN.pm on the non-networked machines works nicely
+    with this floppy. See also below the paragraph about CD-ROM support.
+
+CONFIGURATION
+    When the CPAN module is installed, a site wide configuration file is
+    created as CPAN/Config.pm. The default values defined there can be
+    overridden in another configuration file: CPAN/MyConfig.pm. You can
+    store this file in $HOME/.cpan/CPAN/MyConfig.pm if you want, because
+    $HOME/.cpan is added to the search path of the CPAN module before the
+    use() or require() statements.
+
+    Currently the following keys in the hash reference $CPAN::Config are
+    defined:
+
+      build_cache        size of cache for directories to build modules
+      build_dir          locally accessible directory to build modules
+      index_expire       after this many days refetch index files
+      cache_metadata     use serializer to cache metadata
+      cpan_home          local directory reserved for this package
+      dontload_hash      anonymous hash: modules in the keys will not be
+                         loaded by the CPAN::has_inst() routine
+      gzip               location of external program gzip
+      histfile           file to maintain history between sessions
+      histsize           maximum number of lines to keep in histfile
+      inactivity_timeout breaks interactive Makefile.PLs after this
+                         many seconds inactivity. Set to 0 to never break.
+      inhibit_startup_message
+                         if true, does not print the startup message
+      keep_source_where  directory in which to keep the source (if we do)
+      make               location of external make program
+      make_arg           arguments that should always be passed to 'make'
+      make_install_arg   same as make_arg for 'make install'
+      makepl_arg         arguments passed to 'perl Makefile.PL'
+      pager              location of external program more (or any pager)
+      prerequisites_policy
+                         what to do if you are missing module prerequisites
+                         ('follow' automatically, 'ask' me, or 'ignore')
+      proxy_user         username for accessing an authenticating proxy
+      proxy_pass         password for accessing an authenticating proxy
+      scan_cache         controls scanning of cache ('atstart' or 'never')
+      tar                location of external program tar
+      term_is_latin      if true internal UTF-8 is translated to ISO-8859-1
+                         (and nonsense for characters outside latin range)
+      unzip              location of external program unzip
+      urllist            arrayref to nearby CPAN sites (or equivalent locations)
+      wait_list          arrayref to a wait server to try (See CPAN::WAIT)
+      ftp_proxy,      }  the three usual variables for configuring
+        http_proxy,   }  proxy requests. Both as CPAN::Config variables
+        no_proxy      }  and as environment variables configurable.
+
+    You can set and query each of these options interactively in the cpan
+    shell with the command set defined within the "o conf" command:
+
+    "o conf <scalar option>"
+      prints the current value of the *scalar option*
+
+    "o conf <scalar option> <value>"
+      Sets the value of the *scalar option* to *value*
+
+    "o conf <list option>"
+      prints the current value of the *list option* in MakeMaker's neatvalue
+      format.
+
+    "o conf <list option> [shift|pop]"
+      shifts or pops the array in the *list option* variable
+
+    "o conf <list option> [unshift|push|splice] <list>"
+      works like the corresponding perl commands.
+
+  Note on urllist parameter's format
+    urllist parameters are URLs according to RFC 1738. We do a little
+    guessing if your URL is not compliant, but if you have problems with
+    file URLs, please try the correct format. Either:
+
+        file://localhost/whatever/ftp/pub/CPAN/
+
+    or
+
+        file:///home/ftp/pub/CPAN/
+
+  urllist parameter has CD-ROM support
+    The "urllist" parameter of the configuration table contains a list of
+    URLs that are to be used for downloading. If the list contains any
+    "file" URLs, CPAN always tries to get files from there first. This
+    feature is disabled for index files. So the recommendation for the owner
+    of a CD-ROM with CPAN contents is: include your local, possibly outdated
+    CD-ROM as a "file" URL at the end of urllist, e.g.
+
+      o conf urllist push file://localhost/CDROM/CPAN
+
+    CPAN.pm will then fetch the index files from one of the CPAN sites that
+    come at the beginning of urllist. It will later check for each module if
+    there is a local copy of the most recent version.
+
+    Another peculiarity of urllist is that the site that we could
+    successfully fetch the last file from automatically gets a preference
+    token and is tried as the first site for the next request. So if you add
+    a new site at runtime it may happen that the previously preferred site
+    will be tried another time. This means that if you want to disallow a
+    site for the next transfer, it must be explicitly removed from urllist.
+
+SECURITY
+    There's no strong security layer in CPAN.pm. CPAN.pm helps you to
+    install foreign, unmasked, unsigned code on your machine. We compare to
+    a checksum that comes from the net just as the distribution file itself.
+    If somebody has managed to tamper with the distribution file, they may
+    have as well tampered with the CHECKSUMS file. Future development will
+    go towards strong authentication.
+
+EXPORT
+    Most functions in package CPAN are exported per default. The reason for
+    this is that the primary use is intended for the cpan shell or for
+    one-liners.
+
+POPULATE AN INSTALLATION WITH LOTS OF MODULES
+    Populating a freshly installed perl with my favorite modules is pretty
+    easy if you maintain a private bundle definition file. To get a useful
+    blueprint of a bundle definition file, the command autobundle can be
+    used on the CPAN shell command line. This command writes a bundle
+    definition file for all modules that are installed for the currently
+    running perl interpreter. It's recommended to run this command only once
+    and from then on maintain the file manually under a private name, say
+    Bundle/my_bundle.pm. With a clever bundle file you can then simply say
+
+        cpan> install Bundle::my_bundle
+
+    then answer a few questions and then go out for a coffee.
+
+    Maintaining a bundle definition file means keeping track of two things:
+    dependencies and interactivity. CPAN.pm sometimes fails on calculating
+    dependencies because not all modules define all MakeMaker attributes
+    correctly, so a bundle definition file should specify prerequisites as
+    early as possible. On the other hand, it's a bit annoying that many
+    distributions need some interactive configuring. So what I try to
+    accomplish in my private bundle file is to have the packages that need
+    to be configured early in the file and the gentle ones later, so I can
+    go out after a few minutes and leave CPAN.pm untended.
+
+WORKING WITH CPAN.pm BEHIND FIREWALLS
+    Thanks to Graham Barr for contributing the following paragraphs about
+    the interaction between perl, and various firewall configurations. For
+    further informations on firewalls, it is recommended to consult the
+    documentation that comes with the ncftp program. If you are unable to go
+    through the firewall with a simple Perl setup, it is very likely that
+    you can configure ncftp so that it works for your firewall.
+
+  Three basic types of firewalls
+    Firewalls can be categorized into three basic types.
+
+    http firewall
+        This is where the firewall machine runs a web server and to access
+        the outside world you must do it via the web server. If you set
+        environment variables like http_proxy or ftp_proxy to a values
+        beginning with http:// or in your web browser you have to set proxy
+        information then you know you are running an http firewall.
+
+        To access servers outside these types of firewalls with perl (even
+        for ftp) you will need to use LWP.
+
+    ftp firewall
+        This where the firewall machine runs an ftp server. This kind of
+        firewall will only let you access ftp servers outside the firewall.
+        This is usually done by connecting to the firewall with ftp, then
+        entering a username like "user@outside.host.com"
+
+        To access servers outside these type of firewalls with perl you will
+        need to use Net::FTP.
+
+    One way visibility
+        I say one way visibility as these firewalls try to make themselves
+        look invisible to the users inside the firewall. An FTP data
+        connection is normally created by sending the remote server your IP
+        address and then listening for the connection. But the remote server
+        will not be able to connect to you because of the firewall. So for
+        these types of firewall FTP connections need to be done in a passive
+        mode.
+
+        There are two that I can think off.
+
+        SOCKS
+            If you are using a SOCKS firewall you will need to compile perl
+            and link it with the SOCKS library, this is what is normally
+            called a 'socksified' perl. With this executable you will be
+            able to connect to servers outside the firewall as if it is not
+            there.
+
+        IP Masquerade
+            This is the firewall implemented in the Linux kernel, it allows
+            you to hide a complete network behind one IP address. With this
+            firewall no special compiling is needed as you can access hosts
+            directly.
+
+            For accessing ftp servers behind such firewalls you may need to
+            set the environment variable "FTP_PASSIVE" to a true value, e.g.
+
+                env FTP_PASSIVE=1 perl -MCPAN -eshell
+
+            or
+
+                perl -MCPAN -e '$ENV{FTP_PASSIVE} = 1; shell'
+
+  Configuring lynx or ncftp for going through a firewall
+    If you can go through your firewall with e.g. lynx, presumably with a
+    command such as
+
+        /usr/local/bin/lynx -pscott:tiger
+
+    then you would configure CPAN.pm with the command
+
+        o conf lynx "/usr/local/bin/lynx -pscott:tiger"
+
+    That's all. Similarly for ncftp or ftp, you would configure something
+    like
+
+        o conf ncftp "/usr/bin/ncftp -f /home/scott/ncftplogin.cfg"
+
+    Your mileage may vary...
+
+FAQ
+    1)  I installed a new version of module X but CPAN keeps saying, I have
+        the old version installed
+
+        Most probably you do have the old version installed. This can happen
+        if a module installs itself into a different directory in the @INC
+        path than it was previously installed. This is not really a CPAN.pm
+        problem, you would have the same problem when installing the module
+        manually. The easiest way to prevent this behaviour is to add the
+        argument "UNINST=1" to the "make install" call, and that is why many
+        people add this argument permanently by configuring
+
+          o conf make_install_arg UNINST=1
+
+    2)  So why is UNINST=1 not the default?
+
+        Because there are people who have their precise expectations about
+        who may install where in the @INC path and who uses which @INC
+        array. In fine tuned environments "UNINST=1" can cause damage.
+
+    3)  I want to clean up my mess, and install a new perl along with all
+        modules I have. How do I go about it?
+
+        Run the autobundle command for your old perl and optionally rename
+        the resulting bundle file (e.g. Bundle/mybundle.pm), install the new
+        perl with the Configure option prefix, e.g.
+
+            ./Configure -Dprefix=/usr/local/perl-5.6.78.9
+
+        Install the bundle file you produced in the first step with
+        something like
+
+            cpan> install Bundle::mybundle
+
+        and you're done.
+
+    4)  When I install bundles or multiple modules with one command there is
+        too much output to keep track of.
+
+        You may want to configure something like
+
+          o conf make_arg "| tee -ai /root/.cpan/logs/make.out"
+          o conf make_install_arg "| tee -ai /root/.cpan/logs/make_install.out"
+
+        so that STDOUT is captured in a file for later inspection.
+
+    5)  I am not root, how can I install a module in a personal directory?
+
+        You will most probably like something like this:
+
+          o conf makepl_arg "LIB=~/myperl/lib \
+                            INSTALLMAN1DIR=~/myperl/man/man1 \
+                            INSTALLMAN3DIR=~/myperl/man/man3"
+          install Sybase::Sybperl
+
+        You can make this setting permanent like all "o conf" settings with
+        "o conf commit".
+
+        You will have to add ~/myperl/man to the MANPATH environment
+        variable and also tell your perl programs to look into ~/myperl/lib,
+        e.g. by including
+
+          use lib "$ENV{HOME}/myperl/lib";
+
+        or setting the PERL5LIB environment variable.
+
+        Another thing you should bear in mind is that the UNINST parameter
+        should never be set if you are not root.
+
+    6)  How to get a package, unwrap it, and make a change before building
+        it?
+
+          look Sybase::Sybperl
+
+    7)  I installed a Bundle and had a couple of fails. When I retried,
+        everything resolved nicely. Can this be fixed to work on first try?
+
+        The reason for this is that CPAN does not know the dependencies of
+        all modules when it starts out. To decide about the additional items
+        to install, it just uses data found in the generated Makefile. An
+        undetected missing piece breaks the process. But it may well be that
+        your Bundle installs some prerequisite later than some depending
+        item and thus your second try is able to resolve everything. Please
+        note, CPAN.pm does not know the dependency tree in advance and
+        cannot sort the queue of things to install in a topologically
+        correct order. It resolves perfectly well IFF all modules declare
+        the prerequisites correctly with the PREREQ_PM attribute to
+        MakeMaker. For bundles which fail and you need to install often, it
+        is recommended sort the Bundle definition file manually. It is
+        planned to improve the metadata situation for dependencies on CPAN
+        in general, but this will still take some time.
+
+    8)  In our intranet we have many modules for internal use. How can I
+        integrate these modules with CPAN.pm but without uploading the
+        modules to CPAN?
+
+        Have a look at the CPAN::Site module.
+
+    9)  When I run CPAN's shell, I get error msg about line 1 to 4, setting
+        meta input/output via the /etc/inputrc file.
+
+        Some versions of readline are picky about capitalization in the
+        /etc/inputrc file and specifically RedHat 6.2 comes with a
+        /etc/inputrc that contains the word "on" in lowercase. Change the
+        occurrences of "on" to "On" and the bug should disappear.
+
+    10) Some authors have strange characters in their names.
+
+        Internally CPAN.pm uses the UTF-8 charset. If your terminal is
+        expecting ISO-8859-1 charset, a converter can be activated by
+        setting term_is_latin to a true value in your config file. One way
+        of doing so would be
+
+            cpan> ! $CPAN::Config->{term_is_latin}=1
+
+        Extended support for converters will be made available as soon as
+        perl becomes stable with regard to charset issues.
+
+BUGS
+    We should give coverage for all of the CPAN and not just the PAUSE part,
+    right? In this discussion CPAN and PAUSE have become equal -- but they
+    are not. PAUSE is authors/, modules/ and scripts/. CPAN is PAUSE plus
+    the clpa/, doc/, misc/, ports/, and src/.
+
+    Future development should be directed towards a better integration of
+    the other parts.
+
+    If a Makefile.PL requires special customization of libraries, prompts
+    the user for special input, etc. then you may find CPAN is not able to
+    build the distribution. In that case, you should attempt the traditional
+    method of building a Perl module package from a shell.
+
+AUTHOR
+    Andreas Koenig <andreas.koenig@anima.de>
+
+TRANSLATIONS
+    Kawai,Takanori provides a Japanese translation of this manpage at
+    http://member.nifty.ne.jp/hippo2000/perltips/CPAN.htm
+
+SEE ALSO
+    perl(1), CPAN::Nox(3)
+
index 3d5565b..4006771 100644 (file)
@@ -1,14 +1,13 @@
 #!./perl
 
-BEGIN {
-       chdir 't' if -d 't';
-       @INC = '../lib';
-}
-
+use lib "BUNDLE";
 use Test::More tests => 8;
 
 # use this first to $CPAN::term can be undefined
 use_ok( 'CPAN' );
+$CPAN::Suppress_readline = $CPAN::Suppress_readline; # silence
+$CPAN::META = $CPAN::META; # silence
+$CPAN::term = $CPAN::term; # silence
 undef $CPAN::term;
 
 # this kicks off all the magic
index dce7e10..fd0b679 100644 (file)
@@ -1,11 +1,6 @@
 #!/usr/bin/perl -w
 
 BEGIN {
-       chdir 't' if -d 't';
-       @INC = '../lib';
-}
-
-BEGIN {
     print "1..1\n";
 }
 use strict;
index 91bd396..f383be8 100644 (file)
@@ -8,6 +8,7 @@ BEGIN {
 }
 
 use strict;
+use lib "BUNDLE";
 use Test::More tests => 6; 
 
 use_ok( 'CPAN::FirstTime' );
index 290fc3d..daed979 100644 (file)
@@ -1,10 +1,5 @@
 # -*- Mode: cperl; coding: utf-8; -*-
 
-BEGIN {
-       chdir 't' if -d 't';
-       @INC = '../lib';
-}
-
 use strict;
 use CPAN;
 use vars qw($D $N);
index 8725a8d..e4caa15 100644 (file)
--- a/utils.lst
+++ b/utils.lst
@@ -7,6 +7,7 @@ pod/pod2usage
 pod/podchecker
 pod/podselect
 utils/c2ph      # link = utils/pstruct
+utils/cpan
 utils/dprofpp
 utils/enc2xs
 utils/h2ph
diff --git a/utils/cpan b/utils/cpan
new file mode 100644 (file)
index 0000000..38af905
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/perl
+# $Id: cpan,v 1.3 2002/08/30 08:55:15 k Exp $
+use strict;
+
+=head1 NAME
+
+cpan - easily interact with CPAN from the command line
+
+=head1 SYNOPSIS
+
+       # with arguments, installs specified modules
+       cpan module_name [ module_name ... ]
+       
+       # with switches, installs modules with extra behavior
+       cpan [-cimt] module_name [ module_name ... ]
+       
+       # without arguments, starts CPAN shell
+       cpan
+       
+       # without arguments, but some switches
+       cpan [-ahrv]
+
+=head1 DESCRIPTION
+
+This script provides a command interface (not a shell) to CPAN.pm.
+
+=head2 Meta Options
+
+These options are mutually exclusive, and the script processes
+them in this order: [ahvr].  Once the script finds one, it ignores
+the others, and then exits after it finishes the task.  The script
+ignores any other command line options.
+
+=over 4
+
+=item -a
+
+Creates the CPAN.pm autobundle with CPAN::Shell->autobundle.  
+
+=item -h
+
+Prints a help message.
+
+=item -r
+
+Recompiles dynamically loaded modules with CPAN::Shell->recompile.
+
+=item -v
+
+Print the script version and CPAN.pm version.
+
+=back
+
+=head2 Module options
+
+These options are mutually exclusive, and the script processes
+them in alphabetical order. 
+
+=over 4
+
+=item c
+
+Runs a `make clean` in the specified module's directories.
+
+=item i
+
+Installed the specified modules.
+
+=item m
+
+Makes the specified modules.
+
+=item t
+
+Runs a `make test` on the specified modules.
+
+=back
+
+=head2 Examples
+
+       # print a help message
+       cpan -h
+       
+       # print the version numbers
+       cpan -v
+       
+       # create an autobundle
+       cpan -a
+       
+       # recompile modules
+       cpan -r 
+       
+       # install modules
+       cpan -i Netscape::Booksmarks Business::ISBN
+
+=head1 TO DO
+
+* add options for other CPAN::Shell functions
+autobundle, clean, make, recompile, test
+
+=head1 BUGS
+
+* none noted
+
+=head1 SEE ALSO
+
+Most behaviour, including environment variables and configuration,
+comes directly from CPAN.pm.
+
+=head1 AUTHOR
+
+brian d foy <bdfoy@cpan.org>
+
+=cut
+
+use CPAN ();
+use Getopt::Std;
+
+my $VERSION = 
+       sprintf "%d.%02d", q$Revision: 1.3 $ =~ m/ (\d+) \. (\d+) /xg;
+
+my $Default = 'default';
+
+my $META_OPTIONS = 'ahvr';
+
+my %CPAN_METHODS = (
+       $Default => 'install',
+       'c'      => 'clean',
+       'i'      => 'install',
+       'm'      => 'make',
+       't'      => 'test',
+       );
+
+my @cpan_options = grep { $_ ne $Default } sort keys %CPAN_METHODS;
+
+my $arg_count = @ARGV;
+my %options;
+
+Getopt::Std::getopts( 
+       join( '', @cpan_options, $META_OPTIONS ), \%options );
+       
+if( $options{h} )
+       {
+       print STDERR "Printing help message -- ignoring other arguments\n"
+               if $arg_count > 1;
+
+       print STDERR "Use perldoc to read the documentation\n";
+       exit 0;
+       }
+elsif( $options{v} )
+       {
+       print STDERR "Printing version message -- ignoring other arguments\n"
+       
+               if $arg_count > 1;
+
+       my $CPAN_VERSION = CPAN->VERSION;
+       print STDERR "cpan script version $VERSION\n" .
+               "CPAN.pm version $CPAN_VERSION\n";
+       exit 0;
+       }
+elsif( $options{a} )
+       {
+       print "Creating autobundle in ", $CPAN::Config->{cpan_home}, 
+               "/Bundle\n";
+       print STDERR "Creating autobundle -- ignoring other arguments\n"
+               if $arg_count > 1;
+
+       CPAN::Shell->autobundle;
+       exit 0;
+       }
+elsif( $options{r} )
+       {
+       print STDERR "Creating autobundle -- ignoring other arguments\n"
+               if $arg_count > 1;
+               
+       CPAN::Shell->recompile;
+       }
+else
+       {
+       my $switch = '';
+       
+       foreach my $option ( @cpan_options )
+               {
+               next unless $options{$option};
+               $switch = $option;
+               last;
+               }
+       
+          if( not $switch and     @ARGV ) { $switch = $Default;     }
+       elsif( not $switch and not @ARGV ) { CPAN::shell(); exit 0;  }  
+       elsif(     $switch and not @ARGV ) 
+               { die "Nothing to $CPAN_METHODS{$switch}!\n"; }
+
+       my $method = $CPAN_METHODS{$switch};
+       die "CPAN.pm cannot $method!\n" unless CPAN::Shell->can( $method );
+       
+       foreach my $arg ( @ARGV )
+               {
+               CPAN::Shell->$method( $arg );
+               }
+       }
+       
+1;