Synchronize ExtUtils::Instal 1.41
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / Installed.pm
index da4a653..e8f9f3a 100644 (file)
@@ -1,6 +1,6 @@
 package ExtUtils::Installed;
 
-use 5.005_64;
+use 5.00503;
 use strict;
 use Carp qw();
 use ExtUtils::Packlist;
@@ -8,170 +8,235 @@ use ExtUtils::MakeMaker;
 use Config;
 use File::Find;
 use File::Basename;
-our $VERSION = '0.02';
-
-sub _is_type($$$)
-{
-my ($self, $path, $type) = @_;
-return(1) if ($type eq "all");
-if ($type eq "doc")
-   {
-   return(substr($path, 0, length($Config{installman1dir}))
-              eq $Config{installman1dir}
-          ||
-          substr($path, 0, length($Config{installman3dir}))
-              eq $Config{installman3dir}
-          ? 1 : 0)
-   }
-if ($type eq "prog")
-   {
-   return(substr($path, 0, length($Config{prefix})) eq $Config{prefix}
-          &&
-          substr($path, 0, length($Config{installman1dir}))
-             ne $Config{installman1dir}
-          &&
-          substr($path, 0, length($Config{installman3dir}))
-              ne $Config{installman3dir}
-          ? 1 : 0);
-   }
-return(0);
+use File::Spec;
+
+my $Is_VMS = $^O eq 'VMS';
+my $DOSISH = ($^O =~ /^(MSWin\d\d|os2|dos|mint)$/);
+
+require VMS::Filespec if $Is_VMS;
+
+use vars qw($VERSION);
+$VERSION = '1.41';
+$VERSION = eval $VERSION;
+
+sub _is_prefix {
+    my ($self, $path, $prefix) = @_;
+    return unless defined $prefix && defined $path;
+
+    if( $Is_VMS ) {
+        $prefix = VMS::Filespec::unixify($prefix);
+        $path   = VMS::Filespec::unixify($path);
+    }
+
+    # Sloppy Unix path normalization.
+    $prefix =~ s{/+}{/}g;
+    $path   =~ s{/+}{/}g;
+
+    return 1 if substr($path, 0, length($prefix)) eq $prefix;
+
+    if ($DOSISH) {
+        $path =~ s|\\|/|g;
+        $prefix =~ s|\\|/|g;
+        return 1 if $path =~ m{^\Q$prefix\E}i;
+    }
+    return(0);
 }
 
-sub _is_under($$;)
-{
-my ($self, $path, @under) = @_;
-$under[0] = "" if (! @under);
-foreach my $dir (@under)
-   {
-   return(1) if (substr($path, 0, length($dir)) eq $dir);
-   }
-return(0);
+sub _is_doc {
+    my ($self, $path) = @_;
+    my $man1dir = $Config{man1direxp};
+    my $man3dir = $Config{man3direxp};
+    return(($man1dir && $self->_is_prefix($path, $man1dir))
+           ||
+           ($man3dir && $self->_is_prefix($path, $man3dir))
+           ? 1 : 0)
 }
 
-sub new($)
-{
-my ($class) = @_;
-$class = ref($class) || $class;
-my $self = {};
-
-# Read the core packlist
-$self->{Perl}{packlist} =
-   ExtUtils::Packlist->new("$Config{installarchlib}/.packlist");
-$self->{Perl}{version} = $Config{version};
-
-# Read the module packlists
-my $sub = sub
-   {
-   # Only process module .packlists
-   return if ($_) ne ".packlist" || $File::Find::dir eq $Config{installarchlib};
-
-   # Hack of the leading bits of the paths & convert to a module name
-   my $module = $File::Find::name;
-   $module =~ s!$Config{archlib}/auto/(.*)/.packlist!$1!;
-   $module =~ s!$Config{sitearch}/auto/(.*)/.packlist!$1!;
-   my $modfile = "$module.pm";
-   $module =~ s!/!::!g;
-
-   # Find the top-level module file in @INC
-   $self->{$module}{version} = '';
-   foreach my $dir (@INC)
-      {
-      my $p = MM->catfile($dir, $modfile);
-      if (-f $p)
-         {
-         $self->{$module}{version} = MM->parse_version($p);
-         last;
-         }
-      }
-
-   # Read the .packlist
-   $self->{$module}{packlist} = ExtUtils::Packlist->new($File::Find::name);
-   };
-find($sub, $Config{archlib}, $Config{sitearch});
-
-return(bless($self, $class));
+sub _is_type {
+    my ($self, $path, $type) = @_;
+    return 1 if $type eq "all";
+
+    return($self->_is_doc($path)) if $type eq "doc";
+
+    if ($type eq "prog") {
+        return($self->_is_prefix($path, $Config{prefix} || $Config{prefixexp})
+               &&
+               !($self->_is_doc($path))
+               ? 1 : 0);
+    }
+    return(0);
 }
 
-sub modules($)
-{
-my ($self) = @_;
-return(sort(keys(%$self)));
+sub _is_under {
+    my ($self, $path, @under) = @_;
+    $under[0] = "" if (! @under);
+    foreach my $dir (@under) {
+        return(1) if ($self->_is_prefix($path, $dir));
+    }
+
+    return(0);
 }
 
-sub files($$;$)
-{
-my ($self, $module, $type, @under) = @_;
-
-# Validate arguments
-Carp::croak("$module is not installed") if (! exists($self->{$module}));
-$type = "all" if (! defined($type));
-Carp::croak('type must be "all", "prog" or "doc"')
-   if ($type ne "all" && $type ne "prog" && $type ne "doc");
-
-my (@files);
-foreach my $file (keys(%{$self->{$module}{packlist}}))
-   {
-   push(@files, $file)
-      if ($self->_is_type($file, $type) && $self->_is_under($file, @under));
-   }
-return(@files);
+sub new {
+    my ($class) = @_;
+    $class = ref($class) || $class;
+    my $self = {};
+
+    my $archlib = $Config{archlibexp};
+    my $sitearch = $Config{sitearchexp};
+
+    # File::Find does not know how to deal with VMS filepaths.
+    if( $Is_VMS ) {
+        $archlib  = VMS::Filespec::unixify($archlib);
+        $sitearch = VMS::Filespec::unixify($sitearch);
+    }
+
+    if ($DOSISH) {
+        $archlib =~ s|\\|/|g;
+        $sitearch =~ s|\\|/|g;
+    }
+
+    # Read the core packlist
+    $self->{Perl}{packlist} =
+      ExtUtils::Packlist->new( File::Spec->catfile($archlib, '.packlist') );
+    $self->{Perl}{version} = $Config{version};
+
+    # Read the module packlists
+    my $sub = sub {
+        # Only process module .packlists
+        return if $_ ne ".packlist" || $File::Find::dir eq $archlib;
+
+        # Hack of the leading bits of the paths & convert to a module name
+        my $module = $File::Find::name;
+
+        $module =~ s!\Q$archlib\E/?auto/(.*)/.packlist!$1!s  or
+        $module =~ s!\Q$sitearch\E/?auto/(.*)/.packlist!$1!s;
+        my $modfile = "$module.pm";
+        $module =~ s!/!::!g;
+
+        # Find the top-level module file in @INC
+        $self->{$module}{version} = '';
+        foreach my $dir (@INC) {
+            my $p = File::Spec->catfile($dir, $modfile);
+            if (-r $p) {
+                $module = _module_name($p, $module) if $Is_VMS;
+
+                require ExtUtils::MM;
+                $self->{$module}{version} = MM->parse_version($p);
+                last;
+            }
+        }
+
+        # Read the .packlist
+        $self->{$module}{packlist} =
+          ExtUtils::Packlist->new($File::Find::name);
+    };
+
+    my(@dirs) = grep { -e } ($archlib, $sitearch);
+    find($sub, @dirs) if @dirs;
+
+    return(bless($self, $class));
 }
 
-sub directories($$;$)
-{
-my ($self, $module, $type, @under) = @_;
-my (%dirs);
-foreach my $file ($self->files($module, $type, @under))
-   {
-   $dirs{dirname($file)}++;
-   }
-return(sort(keys(%dirs)));
+# VMS's non-case preserving file-system means the package name can't
+# be reconstructed from the filename.
+sub _module_name {
+    my($file, $orig_module) = @_;
+
+    my $module = '';
+    if (open PACKFH, $file) {
+        while (<PACKFH>) {
+            if (/package\s+(\S+)\s*;/) {
+                my $pack = $1;
+                # Make a sanity check, that lower case $module
+                # is identical to lowercase $pack before
+                # accepting it
+                if (lc($pack) eq lc($orig_module)) {
+                    $module = $pack;
+                    last;
+                }
+            }
+        }
+        close PACKFH;
+    }
+
+    print STDERR "Couldn't figure out the package name for $file\n"
+      unless $module;
+
+    return $module;
 }
 
-sub directory_tree($$;$)
-{
-my ($self, $module, $type, @under) = @_;
-my (%dirs);
-foreach my $dir ($self->directories($module, $type, @under))
-   {
-   $dirs{$dir}++;
-   my ($last) = ("");
-   while ($last ne $dir)
-      {
-      $last = $dir;
-      $dir = dirname($dir);
-      last if (! $self->_is_under($dir, @under));
-      $dirs{$dir}++;
-      }
-   }
-return(sort(keys(%dirs)));
+
+
+sub modules {
+    my ($self) = @_;
+
+    # Bug/feature of sort in scalar context requires this.
+    return wantarray ? sort keys %$self : keys %$self;
 }
 
-sub validate($;$)
-{
-my ($self, $module, $remove) = @_;
-Carp::croak("$module is not installed") if (! exists($self->{$module}));
-return($self->{$module}{packlist}->validate($remove));
+sub files {
+    my ($self, $module, $type, @under) = @_;
+
+    # Validate arguments
+    Carp::croak("$module is not installed") if (! exists($self->{$module}));
+    $type = "all" if (! defined($type));
+    Carp::croak('type must be "all", "prog" or "doc"')
+        if ($type ne "all" && $type ne "prog" && $type ne "doc");
+
+    my (@files);
+    foreach my $file (keys(%{$self->{$module}{packlist}})) {
+        push(@files, $file)
+          if ($self->_is_type($file, $type) &&
+              $self->_is_under($file, @under));
+    }
+    return(@files);
 }
 
-sub packlist($$)
-{
-my ($self, $module) = @_;
-Carp::croak("$module is not installed") if (! exists($self->{$module}));
-return($self->{$module}{packlist});
+sub directories {
+    my ($self, $module, $type, @under) = @_;
+    my (%dirs);
+    foreach my $file ($self->files($module, $type, @under)) {
+        $dirs{dirname($file)}++;
+    }
+    return sort keys %dirs;
 }
 
-sub version($$)
-{
-my ($self, $module) = @_;
-Carp::croak("$module is not installed") if (! exists($self->{$module}));
-return($self->{$module}{version});
+sub directory_tree {
+    my ($self, $module, $type, @under) = @_;
+    my (%dirs);
+    foreach my $dir ($self->directories($module, $type, @under)) {
+        $dirs{$dir}++;
+        my ($last) = ("");
+        while ($last ne $dir) {
+            $last = $dir;
+            $dir = dirname($dir);
+            last if !$self->_is_under($dir, @under);
+            $dirs{$dir}++;
+        }
+    }
+    return(sort(keys(%dirs)));
 }
 
-sub DESTROY
-{
+sub validate {
+    my ($self, $module, $remove) = @_;
+    Carp::croak("$module is not installed") if (! exists($self->{$module}));
+    return($self->{$module}{packlist}->validate($remove));
 }
 
+sub packlist {
+    my ($self, $module) = @_;
+    Carp::croak("$module is not installed") if (! exists($self->{$module}));
+    return($self->{$module}{packlist});
+}
+
+sub version {
+    my ($self, $module) = @_;
+    Carp::croak("$module is not installed") if (! exists($self->{$module}));
+    return($self->{$module}{version});
+}
+
+
 1;
 
 __END__
@@ -208,7 +273,7 @@ described below.
 
 =head1 FUNCTIONS
 
-=over
+=over 4
 
 =item new()
 
@@ -225,7 +290,7 @@ is given the special name 'Perl'.
 This takes one mandatory parameter, the name of a module.  It returns a list of
 all the filenames from the package.  To obtain a list of core perl files, use
 the module name 'Perl'.  Additional parameters are allowed.  The first is one
-of the strings "prog", "man" or "all", to select either just program files,
+of the strings "prog", "doc" or "all", to select either just program files,
 just manual files or all files.  The remaining parameters are a list of
 directories. The filenames returned will be restricted to those under the
 specified directories.
@@ -234,7 +299,7 @@ specified directories.
 
 This takes one mandatory parameter, the name of a module.  It returns a list of
 all the directories from the package.  Additional parameters are allowed.  The
-first is one of the strings "prog", "man" or "all", to select either just
+first is one of the strings "prog", "doc" or "all", to select either just
 program directories, just manual directories or all directories.  The remaining
 parameters are a list of directories. The directories returned will be
 restricted to those under the specified directories.  This method returns only
@@ -242,7 +307,7 @@ the leaf directories that contain files from the specified module.
 
 =item directory_tree()
 
-This is identical in operation to directory(), except that it includes all the
+This is identical in operation to directories(), except that it includes all the
 intermediate directories back up to the specified directories.
 
 =item validate()