App::Module::ListerI - List the Perl modules in @INC
# run the .pm file
prompt> perl Lister.pm
---OR---
# rename this file to something your webserver will treat as a
# CGI script and upload it. Run it to see the module list
prompt> cp Lister.pm lister.cgi
... modify the shebang line if you must
prompt> ftp www.example.com
... upload file
prompt> wget http://www.example.com/cgi-bin/lister.cgi
=head1 DESCRIPTION
This is a program to list all of the Perl modules it finds in @INC
for a no-shell web hosting account. It has these explicit design goals:
If you have a shell account, you should just use CPAN.pm's autobundle
feature.
You do not need to install this module. You just need the .pm file.
The rest of the distribution is there to help me give it to other
people and test it.
You might have to modify the shebang line (the first line in the file)
to point to Perl. Your web hoster probably has instructions on what
that should be. As shipped, this program uses the env trick described
in the perlrun manpage. If that doesn't work for you, you'll probably see an
error like:
/usr/bin/env: bad interpreter: No such file or directory
That's similar to the error you'll see if you have the wrong path
to C<perl>.
The program searches each entry in @INC individually and outputs
modules as it finds them.
Do the magic, sending the output to FILEHANDLE. By default, it sends
the output to STDOUT.
Returns three closures to find, report, and clear a list of modules.
See their use in run.
=cut
| sub generator | ||
| { | ||
| my @files = (); |
sub { push @files,
File::Spec->canonpath( $File::Find::name )
if m/\A\w+\.pm\z/ },
sub { @files },
sub { @files = () }
}
=item parse_version_safely( FILENAME )
Find the $VERSION in FILENAME and return its value. The entire
statement in the file must be on a single line with nothing else (just
like for the PAUSE indexer). If the version is undefined, it returns the
string 'undef'.
=cut
| sub parse_version_safely # stolen from PAUSE's mldistwatch, but refactored | |
| { | |
| my( $file ) = @_; |
local $/ = "\n";
local $_; # don't mess with the $_ in the map calling this
return unless open FILE, "<$file";
my $in_pod = 0;
my $version;
while( <FILE> )
{
chomp;
$in_pod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $in_pod;
next if $in_pod || /^\s*#/;
next unless /([\$*])(([\w\:\']*)\bVERSION)\b.*\=/;
my( $sigil, $var ) = ( $1, $2 );
$version = eval_version( $_, $sigil, $var );
last;
}
close FILE;
return 'undef' unless defined $version;
return $version;
}
=item eval_version( STATEMENT, SIGIL, VAR )
Used by parse_version_safely to evaluate the $VERSION line
and return a number.
The STATEMENT is the single statement containing the assignment
to $VERSION.
The SIGIL may be either a $ (for a scalar) or a * for a
typeglob.
The VAR is the variable identifier.
=cut
| sub eval_version | |
| { | |
| my( $line, $sigil, $var ) = @_; |
my $eval = qq{
package ExtUtils::MakeMaker::_version;
local $sigil$var;
\$$var=undef; do {
$line
}; \$$var
};
my $version = do {
local $^W = 0;
no strict;
eval( $eval );
};
return $version;
}
Turn a PATH into a Perl module name, ignoring the @INC directory
specified in INC_DIR.
=cut
| sub path_to_module | |
| { | |
| my( $inc, $path ) = @_; |
my $module_path = substr( $path, length $inc );
$module_path =~ s/\.pm\z//;
# XXX: this is cheating and doesn't handle everything right
my @dirs = grep { ! /\W/ } File::Spec->splitdir( $module_path );
shift @dirs;
my $module_name = join "::", @dirs;
return $module_name;
}
1;
Guessing the module name from the full path name isn't perfect. If I
run into directories that aren't part of the module name in one of the
@INC directories, this program shows the wrong thing.
For example, I have in @INC the directory
/usr/local/lib/perl5/5.8.8. Inside that directory, I expect to find
something like /usr/local/lib/perl5/5.8.8/Foo/Bar.pm, which
translates in the module Foo::Bar. If I find a directory like
/usr/local/lib/perl5/5.8.8/lib/Foo/Bar.pm, where I created the
extra lib by hand, this program guesses the module name is
lib::Foo::Bar. That's not a great tradegy, but I don't have a
simple way around that right now.
This program finds all modules, even those installed in multiple locations. It makes no attempt to figure out which ones Perl will choose first.
The CPAN.pm module
This source is part of a SourceForge project which always has the latest sources in CVS, as well as all of the previous releases.
http://sourceforge.net/projects/brian-d-foy/
If, for some reason, I disappear from the world, one of the other members of the project can shepherd this module appropriately.
brian d foy, <bdfoy@cpan.org>
The idea and some of the testing came from Adam Wohld.
Some bits stolen from mldistwatch in the PAUSE code, by Andreas König.
Copyright (c) 2007, brian d foy, All Rights Reserved.
You may redistribute this under the same terms as Perl itself.