@@ -1,3 +1,51 @@
+[Changes for 1.15 - 2014-08-23]
+* Fix RT #98203: Migrate from deprecated Module::Build::ModuleInfo to Module::Metadata
+ - thanx Petr Pisar (ppisar@redhat.com) for the hint
+
+* add long option names to scandeps.pl
+
+* implement option --xargs for scandeps.pl
+
+* fix wrong version numbers in Changes
+
+[Changes for 1.14 - 2014-08-03]
+* Fix RT #92860 (t/7-check-dynaloader.t doesn't handle systems with mod2fname),
+ RT #97519 (Fix for t/7-check-dynaloader.t on systems with DynaLoader::mod2fname)
+ - applied patch from Brian Fraser (fraserbn@gmail.com), thanks!
+ - lib/Module/ScanDeps/DataFeed.pm: apply here, too
+
+[Changes for 1.13 - 2013-12-21]
+* Fix recognition of (open() arguments) "<:encoding(klingon)",
+ implies modules PerlIO and PerlIO::encoding.
+
+[Changes for 1.12 - 2013-12-01]
+* Fix RT #90869: Use of uninitialized value $module in substitution (s///)
+
+* Fix RT #87775: typo fixes, thanks dsteinbrunner@pobox.com
+
+* new %Preload rule for B::Hooks::EndOfScope
+
+* new %Preload rule for Pod::Usage
+
+* add a fake %Preload rule that warns if use of Module::Implementation
+ or Module::Runtime is detected (coz' they're doing runtime loading)
+
+* change some tests to use Test::Requires instead of homegrown stuff;
+ hence add it to "test_requires"
+* clean up some uses of Test::More
+
+[Changes for 1.11 - 2013-09-28]
+* Fix RT #89000: test broken by indirect base.pm disuse
+ - delete base.pm from list of expected deps,
+ patch by Andrew Main (zefram@fysh.org)
+
+* new %Preload rule for Net::HTTPS (e.g. used by LWP::Protocol::https)
+ - look for IO::Socket::SSL or Net::SSL
+
+* new %Preload rule for YAML::Any
+ - try to figure out what YAML::Any would have used (using YAML::Any->implementation)
+ - as fallback, include anything below YAML
+
[Changes for 1.10 - 2012-10-20]
* add %Preload rule for Params::Validate to detect
its PP and XS implementations
@@ -48,6 +48,7 @@ t/data/file-glob-yes.pl
t/data/pluggable/Foo.pm
t/data/pluggable/Foo/Plugin/Bar.pm
t/data/pluggable/Foo/Plugin/Baz.pm
+t/data/rt90869.pl
t/data/ScanFileRE/auto/example/example.h
t/data/ScanFileRE/example.pm
t/data/ScanFileRE/example_too.pm
@@ -73,4 +74,5 @@ t/data/static/TestC.pm
t/data/static/TestD.pm
t/data/static/useVERSION.pm
t/data/use_lib.pl
+t/rt90869.t
t/Utils.pm
@@ -5,11 +5,12 @@ author:
build_requires:
ExtUtils::MakeMaker: 6.59
Test::More: 0
+ Test::Requires: 0
configure_requires:
ExtUtils::MakeMaker: 6.59
distribution_type: module
dynamic_config: 1
-generated_by: 'Module::Install version 1.06'
+generated_by: 'Module::Install version 1.10'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -19,16 +20,18 @@ no_index:
directory:
- inc
- t
- module:
+ package:
- Module::ScanDeps::Cache
- Module::ScanDeps::DataFeed
requires:
File::Spec: 0
File::Temp: 0
- Module::Build::ModuleInfo: 0
+ Getopt::Long: 0
+ Module::Metadata: 0
+ Text::ParseWords: 0
perl: 5.8.1
version: 0
resources:
license: http://dev.perl.org/licenses/
repository: http://svn.openfoundry.org/par/Module-ScanDeps/trunk/
-version: 1.10
+version: '1.15'
@@ -9,14 +9,16 @@ repository 'http://svn.openfoundry.org/par/Module-ScanDeps/trunk/';
perl_version '5.008001';
requires 'File::Temp' => '0';
requires 'File::Spec' => '0';
-requires 'Module::Build::ModuleInfo' => '0';
+requires 'Getopt::Long' => '0';
+requires 'Module::Metadata' => '0';
+requires 'Text::ParseWords' => '0';
requires 'version' => '0';
-build_requires 'Test::More' => '0';
+test_requires 'Test::More' => '0';
+test_requires 'Test::Requires' => '0';
install_script 'script/scandeps.pl';
-no_index module => 'Module::ScanDeps::Cache';
-no_index module => 'Module::ScanDeps::DataFeed';
+no_index package => qw( Module::ScanDeps::Cache
+ Module::ScanDeps::DataFeed );
-#sign;
WriteAll;
@@ -4,7 +4,7 @@ package Module::Install::Base;
use strict 'vars';
use vars qw{$VERSION};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
}
# Suspend handler for "redefined" warnings
@@ -8,7 +8,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -91,3 +91,7 @@ END_FTP
}
1;
+
+__END__
+
+#line 109
@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -133,7 +133,7 @@ sub makemaker_args {
return $args;
}
-# For mm args that take multiple space-seperated args,
+# For mm args that take multiple space-separated args,
# append an argument to the current list.
sub makemaker_append {
my $self = shift;
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -347,7 +347,7 @@ sub name_from {
^ \s*
package \s*
([\w:]+)
- \s* ;
+ [\s|;]*
/ixms
) {
my ($name, $module_name) = ($1, $1);
@@ -453,24 +453,40 @@ sub author_from {
#Stolen from M::B
my %license_urls = (
- perl => 'http://dev.perl.org/licenses/',
- apache => 'http://apache.org/licenses/LICENSE-2.0',
- apache_1_1 => 'http://apache.org/licenses/LICENSE-1.1',
- artistic => 'http://opensource.org/licenses/artistic-license.php',
- artistic_2 => 'http://opensource.org/licenses/artistic-license-2.0.php',
- lgpl => 'http://opensource.org/licenses/lgpl-license.php',
- lgpl2 => 'http://opensource.org/licenses/lgpl-2.1.php',
- lgpl3 => 'http://opensource.org/licenses/lgpl-3.0.html',
- bsd => 'http://opensource.org/licenses/bsd-license.php',
- gpl => 'http://opensource.org/licenses/gpl-license.php',
- gpl2 => 'http://opensource.org/licenses/gpl-2.0.php',
- gpl3 => 'http://opensource.org/licenses/gpl-3.0.html',
- mit => 'http://opensource.org/licenses/mit-license.php',
- mozilla => 'http://opensource.org/licenses/mozilla1.1.php',
open_source => undef,
unrestricted => undef,
restrictive => undef,
unknown => undef,
+
+## from Software-License - should we be using S-L instead ?
+# duplicates commeted out, see hack above ^^
+# open_source => 'http://www.gnu.org/licenses/agpl-3.0.txt',
+# apache => 'http://www.apache.org/licenses/LICENSE-1.1',
+ apache => 'http://www.apache.org/licenses/LICENSE-2.0.txt',
+ artistic => 'http://www.perlfoundation.org/artistic_license_1_0',
+ artistic_2 => 'http://www.perlfoundation.org/artistic_license_2_0',
+ bsd => 'http://opensource.org/licenses/BSD-3-Clause',
+# unrestricted => 'http://creativecommons.org/publicdomain/zero/1.0/',
+# open_source => 'http://www.freebsd.org/copyright/freebsd-license.html',
+# open_source => 'http://www.gnu.org/licenses/fdl-1.2.txt',
+# open_source => 'http://www.gnu.org/licenses/fdl-1.3.txt',
+# gpl => 'http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt',
+# gpl => 'http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt',
+ gpl => 'http://www.gnu.org/licenses/gpl-3.0.txt',
+# lgpl => 'http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt',
+ lgpl => 'http://www.gnu.org/licenses/lgpl-3.0.txt',
+ mit => 'http://www.opensource.org/licenses/mit-license.php',
+# mozilla => 'http://www.mozilla.org/MPL/MPL-1.0.txt',
+# mozilla => 'http://www.mozilla.org/MPL/MPL-1.1.txt',
+ mozilla => 'http://www.mozilla.org/MPL/2.0/index.txt',
+# restrictive => '',
+# open_source => 'http://www.openssl.org/source/license.html',
+ perl => 'http://dev.perl.org/licenses/',
+# open_source => 'http://www.opensource.org/licenses/postgresql',
+# open_source => 'http://trolltech.com/products/qt/licenses/licensing/qpl',
+# unrestricted => 'http://h71000.www7.hp.com/doc/83final/BA554_90007/apcs02.html',
+# open_source => 'http://www.openoffice.org/licenses/sissl_license.html',
+# open_source => 'http://www.zlib.net/zlib_license.html',
);
sub license {
@@ -511,31 +527,43 @@ sub __extract_license {
my @phrases = (
'(?:under )?the same (?:terms|license) as (?:perl|the perl (?:\d )?programming language)' => 'perl', 1,
'(?:under )?the terms of (?:perl|the perl programming language) itself' => 'perl', 1,
- 'Artistic and GPL' => 'perl', 1,
- 'GNU general public license' => 'gpl', 1,
- 'GNU public license' => 'gpl', 1,
- 'GNU lesser general public license' => 'lgpl', 1,
- 'GNU lesser public license' => 'lgpl', 1,
- 'GNU library general public license' => 'lgpl', 1,
- 'GNU library public license' => 'lgpl', 1,
- 'GNU Free Documentation license' => 'unrestricted', 1,
- 'GNU Affero General Public License' => 'open_source', 1,
+
+ # the following are relied on by the test system even if they are wrong :(
'(?:Free)?BSD license' => 'bsd', 1,
'Artistic license 2\.0' => 'artistic_2', 1,
- 'Artistic license' => 'artistic', 1,
- 'Apache (?:Software )?license' => 'apache', 1,
- 'GPL' => 'gpl', 1,
'LGPL' => 'lgpl', 1,
- 'BSD' => 'bsd', 1,
- 'Artistic' => 'artistic', 1,
'MIT' => 'mit', 1,
- 'Mozilla Public License' => 'mozilla', 1,
- 'Q Public License' => 'open_source', 1,
- 'OpenSSL License' => 'unrestricted', 1,
- 'SSLeay License' => 'unrestricted', 1,
- 'zlib License' => 'open_source', 1,
- 'proprietary' => 'proprietary', 0,
+
+## from Software-License
+ 'The GNU Affero General Public License, Version 3, November 2007' => 'open_source', 1,
+ 'The Apache Software License, Version 1.1' => 'apache', 1,
+ 'The Apache License, Version 2.0, January 2004' => 'apache', 1,
+ 'The Artistic License 1.0' => 'artistic', 1,
+ 'The Artistic License 2.0 (GPL Compatible)' => 'artistic_2', 1,
+ 'The (three-clause) BSD License' => 'bsd', 1,
+ 'CC0 License' => 'unrestricted', 1,
+ 'The (two-clause) FreeBSD License' => 'open_source', 1,
+ 'GNU Free Documentation License v1.2' => 'open_source', 1,
+ 'GNU Free Documentation License v1.3' => 'open_source', 1,
+ 'The GNU General Public License, Version 1, February 1989' => 'gpl', 1,
+ 'The GNU General Public License, Version 2, June 1991' => 'gpl', 1,
+ 'The GNU General Public License, Version 3, June 2007' => 'gpl', 1,
+ 'The GNU Lesser General Public License, Version 2.1, February 1999' => 'lgpl', 1,
+ 'The GNU Lesser General Public License, Version 3, June 2007' => 'lgpl', 1,
+ 'The MIT (X11) License' => 'mit', 1,
+ 'The Mozilla Public License 1.0' => 'mozilla', 1,
+ 'The Mozilla Public License 1.1' => 'mozilla', 1,
+ 'Mozilla Public License Version 2.0' => 'mozilla', 1,
+ '"No License" License' => 'restrictive', 1,
+ 'OpenSSL License' => 'open_source', 1,
+ 'the same terms as the perl 5 programming language system itself' => 'perl', 1,
+ 'The PostgreSQL License' => 'open_source', 1,
+ 'The Q Public License, Version 1.0' => 'open_source', 1,
+ 'Original SSLeay License' => 'unrestricted', 1,
+ 'Sun Internet Standards Source License (SISSL)' => 'open_source', 1,
+ 'The zlib License' => 'open_source', 1,
);
+
while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
$pattern =~ s#\s+#\\s+#gs;
if ( $license_text =~ /\b$pattern\b/i ) {
@@ -705,7 +733,7 @@ sub _write_mymeta_data {
my @yaml = Parse::CPAN::Meta::LoadFile('META.yml');
my $meta = $yaml[0];
- # Overwrite the non-configure dependency hashs
+ # Overwrite the non-configure dependency hashes
delete $meta->{requires};
delete $meta->{build_requires};
delete $meta->{recommends};
@@ -720,3 +748,7 @@ sub _write_mymeta_data {
}
1;
+
+__END__
+
+#line 766
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -27,3 +27,7 @@ sub install_script {
}
1;
+
+__END__
+
+#line 45
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -62,3 +62,7 @@ END_MESSAGE
}
1;
+
+__END__
+
+#line 80
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.06';
+ $VERSION = '1.10';
@ISA = qw{Module::Install::Base};
$ISCORE = 1;
}
@@ -61,3 +61,7 @@ sub WriteAll {
}
1;
+
+__END__
+
+#line 79
@@ -17,7 +17,7 @@ package Module::Install;
# 3. The ./inc/ version of Module::Install loads
# }
-use 5.005;
+use 5.006;
use strict 'vars';
use Cwd ();
use File::Find ();
@@ -31,7 +31,7 @@ BEGIN {
# This is not enforced yet, but will be some time in the next few
# releases once we can make sure it won't clash with custom
# Module::Install extensions.
- $VERSION = '1.06';
+ $VERSION = '1.10';
# Storage for the pseudo-singleton
$MAIN = undef;
@@ -156,10 +156,10 @@ END_DIE
sub autoload {
my $self = shift;
my $who = $self->_caller;
- my $cwd = Cwd::cwd();
+ my $cwd = Cwd::getcwd();
my $sym = "${who}::AUTOLOAD";
$sym->{$cwd} = sub {
- my $pwd = Cwd::cwd();
+ my $pwd = Cwd::getcwd();
if ( my $code = $sym->{$pwd} ) {
# Delegate back to parent dirs
goto &$code unless $cwd eq $pwd;
@@ -239,7 +239,7 @@ sub new {
# ignore the prefix on extension modules built from top level.
my $base_path = Cwd::abs_path($FindBin::Bin);
- unless ( Cwd::abs_path(Cwd::cwd()) eq $base_path ) {
+ unless ( Cwd::abs_path(Cwd::getcwd()) eq $base_path ) {
delete $args{prefix};
}
return $args{_self} if $args{_self};
@@ -338,7 +338,7 @@ sub find_extensions {
if ( $subpath eq lc($subpath) || $subpath eq uc($subpath) ) {
my $content = Module::Install::_read($subpath . '.pm');
my $in_pod = 0;
- foreach ( split //, $content ) {
+ foreach ( split /\n/, $content ) {
$in_pod = 1 if /^=\w/;
$in_pod = 0 if /^=cut/;
next if ($in_pod || /^=cut/); # skip pod text
@@ -434,7 +434,7 @@ END_OLD
# _version is for processing module versions (eg, 1.03_05) not
# Perl versions (eg, 5.8.1).
-sub _version ($) {
+sub _version {
my $s = shift || 0;
my $d =()= $s =~ /(\.)/g;
if ( $d >= 2 ) {
@@ -450,12 +450,12 @@ sub _version ($) {
return $l + 0;
}
-sub _cmp ($$) {
+sub _cmp {
_version($_[1]) <=> _version($_[2]);
}
# Cloned from Params::Util::_CLASS
-sub _CLASS ($) {
+sub _CLASS {
(
defined $_[0]
and
@@ -467,4 +467,7 @@ sub _CLASS ($) {
1;
-# Copyright 2008 - 2012 Adam Kennedy.
+
+__END__
+
+#line 485
@@ -66,9 +66,9 @@ sub _dl_mod2filename {
my $dl_ext = $Config::Config{dlext};
- # Copied from XSLoader
+ # cf. DynaLoader.pm
my @modparts = split(/::/, $mod);
- my $modfname = $modparts[-1];
+ my $modfname = defined &DynaLoader::mod2fname ? DynaLoader::mod2fname(\@modparts) : $modparts[-1];
my $modpname = join('/', @modparts);
foreach my $dir (@_INC) {
@@ -4,7 +4,7 @@ use strict;
use warnings;
use vars qw( $VERSION @EXPORT @EXPORT_OK @ISA $CurrentPackage @IncludeLibs $ScanFileRE );
-$VERSION = '1.10';
+$VERSION = '1.15';
@EXPORT = qw( scan_deps scan_deps_runtime );
@EXPORT_OK = qw( scan_line scan_chunk add_deps scan_deps_runtime path_to_inc_name );
@@ -26,7 +26,7 @@ use File::Temp ();
use File::Spec ();
use File::Basename ();
use FileHandle;
-use Module::Build::ModuleInfo;
+use Module::Metadata;
$ScanFileRE = qr/(?:^|\\|\/)(?:[^.]*|.*\.(?i:p[ml]|t|al))$/;
@@ -117,8 +117,8 @@ If C<$compile> or C<$execute> is true, runs C<files> in either
compile-only or normal mode, then inspects their C<%INC> after
termination to determine additional runtime dependencies.
-If C<$execute> is an array reference, runs the files contained
-in it instead of C<@files>.
+If C<$execute> is an array reference, passes C<@$execute>
+as arguments to each file in C<@files> when it is run.
If performance of the scanning process is a concern, C<cache_file> can be
set to a filename. The scanning results will be cached and written to the
@@ -200,7 +200,7 @@ C<$Module::ScanDeps::ScanFileRE = qr/./>
=head1 CAVEATS
-This module intentially ignores the B<BSDPAN> hack on FreeBSD -- the
+This module intentionally ignores the B<BSDPAN> hack on FreeBSD -- the
additional directory is removed from C<@INC> altogether.
The static-scanning heuristic is not likely to be 100% accurate, especially
@@ -219,12 +219,14 @@ But this one does not:
=cut
my $SeenTk;
+my %SeenRuntimeLoader;
# Pre-loaded module dependencies {{{
my %Preload;
%Preload = (
'AnyDBM_File.pm' => [qw( SDBM_File.pm )],
'Authen/SASL.pm' => 'sub',
+ 'B/Hooks/EndOfScope.pm' => [qw( B/Hooks/EndOfScope/PP.pm B/Hooks/EndOfScope/XS.pm )],
'Bio/AlignIO.pm' => 'sub',
'Bio/Assembly/IO.pm' => 'sub',
'Bio/Biblio/IO.pm' => 'sub',
@@ -256,7 +258,9 @@ my %Preload;
'Catalyst/Engine.pm' => 'sub',
'CGI/Application/Plugin/Authentication.pm' => [qw( CGI/Application/Plugin/Authentication/Store/Cookie.pm )],
'CGI/Application/Plugin/AutoRunmode.pm' => [qw( Attribute/Handlers.pm )],
-
+ 'charnames.pm' => sub {
+ _find_in_inc('unicore/Name.pl') ? 'unicore/Name.pl' : 'unicode/Name.pl'
+ },
'Class/Load.pm' => [qw( Class/Load/PP.pm )],
'Class/MakeMethods.pm' => 'sub',
'Class/MethodMaker.pm' => 'sub',
@@ -289,6 +293,37 @@ my %Preload;
'Device/SerialPort.pm' => [ qw(
termios.ph asm/termios.ph sys/termiox.ph sys/termios.ph sys/ttycom.ph
) ],
+ 'diagnostics.pm' => sub {
+ # shamelessly taken and adapted from diagnostics.pm
+ use Config;
+ my($privlib, $archlib) = @Config{qw(privlibexp archlibexp)};
+ if ($^O eq 'VMS') {
+ require VMS::Filespec;
+ $privlib = VMS::Filespec::unixify($privlib);
+ $archlib = VMS::Filespec::unixify($archlib);
+ }
+
+ for (
+ "pod/perldiag.pod",
+ "Pod/perldiag.pod",
+ "pod/perldiag-$Config{version}.pod",
+ "Pod/perldiag-$Config{version}.pod",
+ "pods/perldiag.pod",
+ "pods/perldiag-$Config{version}.pod",
+ ) {
+ return $_ if _find_in_inc($_);
+ }
+
+ for (
+ "$archlib/pods/perldiag.pod",
+ "$privlib/pods/perldiag-$Config{version}.pod",
+ "$privlib/pods/perldiag.pod",
+ ) {
+ return $_ if -f $_;
+ }
+
+ return 'pod/perldiag.pod';
+ },
'Email/Send.pm' => 'sub',
'Event.pm' => [ map "Event/$_.pm", qw(idle io signal timer var)],
'ExtUtils/MakeMaker.pm' => sub {
@@ -327,16 +362,11 @@ my %Preload;
# but accept JSON::XS, too (because JSON.pm might use it if present)
return( grep /^JSON\/(PP|XS)/, _glob_in_inc('JSON', 1) );
},
- 'Log/Log4perl.pm' => 'sub',
+ 'Locale/Maketext/Lexicon.pm' => 'sub',
+ 'Locale/Maketext/GutsLoader.pm' => [qw( Locale/Maketext/Guts.pm )],
'Log/Any.pm' => 'sub',
+ 'Log/Log4perl.pm' => 'sub',
'Log/Report/Dispatcher.pm' => 'sub',
- 'LWP/UserAgent.pm' => sub {
- return(
- qw( URI/URL.pm URI/http.pm LWP/Protocol/http.pm ),
- _glob_in_inc("LWP/Authen", 1),
- _glob_in_inc("LWP/Protocol", 1),
- );
- },
'LWP/Parallel.pm' => sub {
_glob_in_inc( 'LWP/Parallel', 1 ),
qw(
@@ -348,17 +378,22 @@ my %Preload;
qw( LWP/Parallel.pm ),
@{ _get_preload('LWP/Parallel.pm') }
},
- 'Locale/Maketext/Lexicon.pm' => 'sub',
- 'Locale/Maketext/GutsLoader.pm' => [qw( Locale/Maketext/Guts.pm )],
+ 'LWP/UserAgent.pm' => sub {
+ return(
+ qw( URI/URL.pm URI/http.pm LWP/Protocol/http.pm ),
+ _glob_in_inc("LWP/Authen", 1),
+ _glob_in_inc("LWP/Protocol", 1),
+ );
+ },
'Mail/Audit.pm' => 'sub',
'Math/BigInt.pm' => 'sub',
'Math/BigFloat.pm' => 'sub',
'Math/Symbolic.pm' => 'sub',
+ 'MIME/Decoder.pm' => 'sub',
'Module/Build.pm' => 'sub',
'Module/Pluggable.pm' => sub {
_glob_in_inc('$CurrentPackage/Plugin', 1);
},
- 'MIME/Decoder.pm' => 'sub',
'Moose.pm' => sub {
_glob_in_inc('Moose', 1),
_glob_in_inc('Class/MOP', 1),
@@ -372,8 +407,11 @@ my %Preload;
qw( MozRepl/Log.pm MozRepl/Client.pm Module/Pluggable/Fast.pm ),
_glob_in_inc('MozRepl/Plugin', 1),
},
+ 'Module/Implementation.pm' => \&_warn_of_runtime_loader,
+ 'Module/Runtime.pm' => \&_warn_of_runtime_loader,
'Net/DNS/RR.pm' => 'sub',
'Net/FTP.pm' => 'sub',
+ 'Net/HTTPS.pm' => [qw( IO/Socket/SSL.pm Net/SSL.pm )],
'Net/Server.pm' => 'sub',
'Net/SSH/Perl.pm' => 'sub',
'Package/Stash.pm' => [qw( Package/Stash/PP.pm Package/Stash/XS.pm )],
@@ -383,13 +421,16 @@ my %Preload;
'Params/Validate.pm' => 'sub',
'Parse/AFP.pm' => 'sub',
'Parse/Binary.pm' => 'sub',
- 'Perl/Critic.pm' => 'sub', #not only Perl/Critic/Policy
- 'PerlIO.pm' => [ 'PerlIO/scalar.pm' ],
'PDF/API2/Resource/Font.pm' => 'sub',
'PDF/API2/Basic/TTF/Font.pm' => sub {
_glob_in_inc('PDF/API2/Basic/TTF', 1);
},
'PDF/Writer.pm' => 'sub',
+ 'Perl/Critic.pm' => 'sub', #not only Perl/Critic/Policy
+ 'PerlIO.pm' => [ 'PerlIO/scalar.pm' ],
+ 'Pod/Usage.pm' => sub { # from Pod::Usage (as of 1.61)
+ $] >= 5.005_58 ? 'Pod/Text.pm' : 'Pod/PlainText.pm'
+ },
'POE.pm' => [qw( POE/Kernel.pm POE/Session.pm )],
'POE/Component/Client/HTTP.pm' => sub {
_glob_in_inc('POE/Component/Client/HTTP', 1),
@@ -436,6 +477,9 @@ my %Preload;
'Template.pm' => 'sub',
'Term/ReadLine.pm' => 'sub',
'Test/Deep.pm' => 'sub',
+ 'threads/shared.pm' => [qw( attributes.pm )],
+ # anybody using threads::shared is likely to declare variables
+ # with attribute :shared
'Tk.pm' => sub {
$SeenTk = 1;
qw( Tk/FileSelect.pm Encode/Unicode.pm );
@@ -457,6 +501,11 @@ my %Preload;
'URI.pm' => sub {
grep !/urn/, _glob_in_inc('URI', 1);
},
+ 'utf8.pm' => sub {
+ # Perl 5.6.x: "unicode", Perl 5.8.x and up: "unicore"
+ my $unicore = _find_in_inc('unicore/Name.pl') ? 'unicore' : 'unicode';
+ return ('utf8_heavy.pl', map $_->{name}, _glob_in_inc($unicore, 0));
+ },
'Win32/EventLog.pm' => [qw( Win32/IPC.pm )],
'Win32/Exe.pm' => 'sub',
'Win32/TieRegistry.pm' => [qw( Win32API/Registry.pm )],
@@ -473,48 +522,16 @@ my %Preload;
'XMLRPC/Lite.pm' => sub {
_glob_in_inc('XMLRPC/Transport', 1),;
},
- 'YAML.pm' => [qw( YAML/Loader.pm YAML/Dumper.pm )],
- 'diagnostics.pm' => sub {
- # shamelessly taken and adapted from diagnostics.pm
- use Config;
- my($privlib, $archlib) = @Config{qw(privlibexp archlibexp)};
- if ($^O eq 'VMS') {
- require VMS::Filespec;
- $privlib = VMS::Filespec::unixify($privlib);
- $archlib = VMS::Filespec::unixify($archlib);
+ 'YAML.pm' => [qw( YAML/Loader.pm YAML/Dumper.pm )],
+ 'YAML/Any.pm' => sub {
+ # try to figure out what YAML::Any would have used
+ my $impl = eval "use YAML::Any; YAML::Any->implementation;";
+ unless ($@)
+ {
+ $impl =~ s!::!/!g;
+ return "$impl.pm";
}
-
- for (
- "pod/perldiag.pod",
- "Pod/perldiag.pod",
- "pod/perldiag-$Config{version}.pod",
- "Pod/perldiag-$Config{version}.pod",
- "pods/perldiag.pod",
- "pods/perldiag-$Config{version}.pod",
- ) {
- return $_ if _find_in_inc($_);
- }
-
- for (
- "$archlib/pods/perldiag.pod",
- "$privlib/pods/perldiag-$Config{version}.pod",
- "$privlib/pods/perldiag.pod",
- ) {
- return $_ if -f $_;
- }
-
- return 'pod/perldiag.pod';
- },
- 'threads/shared.pm' => [qw( attributes.pm )],
- # anybody using threads::shared is likely to declare variables
- # with attribute :shared
- 'utf8.pm' => sub {
- # Perl 5.6.x: "unicode", Perl 5.8.x and up: "unicore"
- my $unicore = _find_in_inc('unicore/Name.pl') ? 'unicore' : 'unicode';
- return ('utf8_heavy.pl', map $_->{name}, _glob_in_inc($unicore, 0));
- },
- 'charnames.pm' => sub {
- _find_in_inc('unicore/Name.pl') ? 'unicore/Name.pl' : 'unicode/Name.pl'
+ _glob_in_inc('YAML', 1); # fallback
},
);
@@ -527,8 +544,8 @@ sub path_to_inc_name($$) {
if ($path =~ m/\.pm$/io) {
die "$path doesn't exist" unless (-f $path);
- my $module_info = Module::Build::ModuleInfo->new_from_file($path);
- die "Module::Build::ModuleInfo error: $!" unless defined($module_info);
+ my $module_info = Module::Metadata->new_from_file($path);
+ die "Module::Metadata error: $!" unless defined($module_info);
$inc_name = $module_info->name();
if (defined($inc_name)) {
$inc_name =~ s|\:\:|\/|og;
@@ -716,32 +733,26 @@ sub scan_deps_runtime {
$files = (ref($files)) ? $files : [$files];
- my ($inchash, $incarray, $dl_shared_objects) = ({}, [], []);
if ($compile) {
- my $file;
-
- foreach $file (@$files) {
+ foreach my $file (@$files) {
next unless $file =~ $ScanFileRE;
- ($inchash, $dl_shared_objects, $incarray) = ({}, [], []);
- _compile_or_execute($compile, $perl, $file, $inchash, $dl_shared_objects, $incarray);
+ my ($inchash, $dl_shared_objects, $incarray) = ({}, [], []);
+ _compile_or_execute($perl, $file, undef,
+ $inchash, $dl_shared_objects, $incarray);
- my $rv_sub = _make_rv($inchash, $dl_shared_objects, $incarray);
- _merge_rv($rv_sub, $rv);
+ _merge_rv(_make_rv($inchash, $dl_shared_objects, $incarray), $rv);
}
}
elsif ($execute) {
- my $excarray = (ref($execute)) ? $execute : [@$files];
- my $exc;
- foreach $exc (@$excarray) {
- ($inchash, $dl_shared_objects, $incarray) = ({}, [], []);
- _compile_or_execute($compile, $perl, $exc, $inchash, $dl_shared_objects, $incarray);
- }
+ foreach my $file (@$files) {
+ $execute = [] unless ref $execute; # make sure it's an array ref
+ my ($inchash, $dl_shared_objects, $incarray) = ({}, [], []);
+ _compile_or_execute($perl, $file, $execute,
+ $inchash, $dl_shared_objects, $incarray);
- # XXX only retains data from last execute ... Why? I suspect
- # the above loop was added later. Needs test cases --Eric
- my $rv_sub = _make_rv($inchash, $dl_shared_objects, $incarray);
- _merge_rv($rv_sub, $rv);
+ _merge_rv(_make_rv($inchash, $dl_shared_objects, $incarray), $rv);
+ }
}
return ($rv);
@@ -813,8 +824,34 @@ sub scan_line {
if (my ($pragma, $args) = /^use \s+ (autouse|if) \s+ (.+)/x)
{
- my @args = do { no strict; no warnings; eval $args };
- my $module = $pragma eq "autouse" ? $args[0] : $args[1];
+ # NOTE: There are different ways the MODULE may
+ # be specified for the "autouse" and "if" pragmas, e.g.
+ # use autouse Module => qw(func1 func2);
+ # use autouse "Module", qw(func1);
+ # To avoid to parse them ourself, we simply try to eval the
+ # string after the pragma (in a list context). The MODULE
+ # should be the first ("autouse") or second ("if") element
+ # of the list.
+ my $module;
+ {
+ no strict; no warnings;
+ if ($pragma eq "autouse") {
+ ($module) = eval $args;
+ }
+ else {
+ # The syntax of the "if" pragma is
+ # use if COND, MODULE => ARGUMENTS
+ # The COND may contain undefined functions (i.e. undefined
+ # in Module::ScanDeps' context) which would throw an
+ # exception. Sneak "1 || " in front of COND so that
+ # COND will not be evaluated. This will work in most
+ # cases, but there are operators with lower precedence
+ # than "||" which will cause this trick to fail.
+ (undef, $module) = eval "1 || $args";
+ }
+ # punt if there was a syntax error
+ return if $@ or !defined $module;
+ };
$module =~ s{::}{/}g;
return ("$pragma.pm", "$module.pm");
}
@@ -917,14 +954,20 @@ sub scan_chunk {
my $diamond = $1;
return "File/Glob.pm" if $diamond =~ /[*?\[\]{}~\\]/;
}
+
return "DBD/$1.pm" if /\b[Dd][Bb][Ii]:(\w+):/;
- if (/(?:(:encoding)|\b(?:en|de)code)\(\s*['"]?([-\w]+)/) {
- my $mod = _find_encoding($2);
- my @mods = ( 'Encoding.pm' ); # always needed
- push @mods, 'PerlIO.pm' if $1; # needed for ":encoding(...)"
+
+ # check for stuff like
+ # decode("klingon", ...)
+ # open FH, "<:encoding(klingon)", ...
+ if (my ($io_layer, $encoding) = /(?:(:encoding)|\b(?:en|de)code)\(\s*['"]?([-\w]+)/) {
+ my @mods;
+ my $mod = _find_encoding($encoding);
push @mods, $mod if $mod; # "external" Encode module
+ push @mods, qw( PerlIO.pm PerlIO/encoding.pm ) if $io_layer;
return \@mods;
}
+
return $1 if /^(?:do|require)\s+[^"]*"(.*?)"/;
return $1 if /^(?:do|require)\s+[^']*'(.*?)'/;
return $1 if /[^\$]\b([\w:]+)->\w/ and $1 ne 'Tk' and $1 ne 'shift';
@@ -1076,7 +1119,7 @@ sub add_deps {
type => $type );
}
- ### Now, handle module and distribudion share dirs
+ ### Now, handle module and distribution share dirs
# convert 'Module/Name' to 'Module-Name'
my $modname = $path;
$modname =~ s|/|-|g;
@@ -1238,8 +1281,10 @@ sub get_files {
# scan_deps_runtime utility functions
+# compile $file if $execute is undef,
+# otherwise execute $file with arguments @$execute
sub _compile_or_execute {
- my ($compile, $perl, $file, $inchash, $dl_shared_objects, $incarray) = @_;
+ my ($perl, $file, $execute, $inchash, $dl_shared_objects, $incarray) = @_;
require Module::ScanDeps::DataFeed;
# ... so we can find it's full pathname in %INC
@@ -1258,7 +1303,7 @@ sub _compile_or_execute {
"*0 = \\\$Module::ScanDeps::DataFeed::_0;\n",
"}\n";
- print $feed_fh $compile ? "CHECK {\n" : "END {\n";
+ print $feed_fh $execute ? "END {\n" : "CHECK {\n" ;
# NOTE: When compiling the block will run as the last CHECK block;
# when executing the block will run as the first END block and
# the programs continues.
@@ -1268,7 +1313,7 @@ sub _compile_or_execute {
[ $INC{"Module/ScanDeps/DataFeed.pm"}, $dump_file ],
[ qw( datafeedpm dump_file ) ]);
- # save %INC etc so that further requires dont't pollute them
+ # save %INC etc so that further requires don't pollute them
print $feed_fh <<'...';
%Module::ScanDeps::DataFeed::_INC = %INC;
@Module::ScanDeps::DataFeed::_INC = @INC;
@@ -1281,7 +1326,7 @@ sub _compile_or_execute {
}
...
- # append the file to compile
+ # append the file to compile or execute
{
open my $fhin, "<", $file or die "Couldn't open $file: $!";
print $feed_fh qq[#line 1 "$file"\n], <$fhin>;
@@ -1292,16 +1337,18 @@ sub _compile_or_execute {
File::Path::rmtree( ['_Inline'], 0, 1); # XXX hack
my @cmd = ($perl);
- push @cmd, "-c" if $compile;
+ push @cmd, "-c" unless $execute;
push @cmd, map { "-I$_" } @IncludeLibs;
- my $rc = system(@cmd, $feed_file);
+ push @cmd, $feed_file;
+ push @cmd, @$execute if $execute;
+ my $rc = system(@cmd);
_extract_info($dump_file, $inchash, $dl_shared_objects, $incarray)
if $rc == 0;
unlink($feed_file, $dump_file);
- die $compile
- ? "SYSTEM ERROR in compiling $file: $rc"
- : "SYSTEM ERROR in executing $file: $rc"
+ die $execute
+ ? "SYSTEM ERROR in executing $file @$execute: $rc"
+ : "SYSTEM ERROR in compiling $file: $rc"
unless $rc == 0;
}
@@ -1428,6 +1475,15 @@ sub _abs_path {
}
+sub _warn_of_runtime_loader {
+ my $module = shift;
+ return if $SeenRuntimeLoader{$module}++;
+ $module =~ s/\.pm$//;
+ $module =~ s|/|::|g;
+ warn "# Use of runtime loader module $module detected. Results of static scanning may be incomplete.\n";
+ return;
+}
+
sub _warn_of_missing_module {
my $module = shift;
my $warn = shift;
@@ -4,13 +4,22 @@ $VERSION = '0.76';
use strict;
use Config;
-use Getopt::Std;
+use Getopt::Long qw(:config bundling no_ignore_case);
use Module::ScanDeps;
use ExtUtils::MakeMaker;
use subs qw( _name _modtree );
my %opts;
-getopts('BVRxce:C:', \%opts);
+GetOptions(\%opts,
+ "B|bundle",
+ "C|cachedeps=s",
+ "c|compile".
+ "e|eval=s",
+ "xargs=s",
+ "R|no-recurse",
+ "V|verbose",
+ "x|execute",
+);
my (%map, %skip);
my $core = $opts{B};
@@ -26,6 +35,11 @@ if ($eval) {
push @ARGV, $filename;
}
+if ($opts{x} && defined $opts{xargs}) {
+ require Text::ParseWords;
+ $opts{x} = [ Text::ParseWords::shellwords($opts{xargs}) ];
+}
+
die "Usage: $0 [ -B ] [ -V ] [ -x | -c ] [ -R ] [-C FILE ] [ -e STRING | FILE ... ]\n" unless @ARGV;
my @files = @ARGV;
@@ -37,7 +51,7 @@ while (<>) {
my $map = scan_deps(
files => \@files,
recurse => $recurse,
- $opts{x} ? ( execute => 1 ) :
+ $opts{x} ? ( execute => $opts{x} ) :
$opts{c} ? ( compile => 1 ) : (),
$opts{V} ? ( warn_missing => 1 ) : (),
$opts{C} ? ( cache_file => $opts{C}) : (),
@@ -175,27 +189,33 @@ up by the heuristic anyway.
=over 4
-=item -e STRING
+=item B<-e>, B<--eval>=I<STRING>
Scan I<STRING> as a string containing perl code.
-=item -c
+=item B<-c>, B<--compile>
Compiles the code and inspects its C<%INC>, in addition to static scanning.
-=item -x
+=item B<-x>, B<--execute>
Executes the code and inspects its C<%INC>, in addition to static scanning.
-=item -B
+=item B<--xargs>=I<STRING>
+
+If B<-x> is given, splits the C<STRING> using the function
+C<shellwords> from L<Text::ParseWords> and passes the result
+as C<@ARGV> when executing the code.
+
+=item B<-B>, B<--bundle>
Include core modules in the output and the recursive search list.
-=item -R
+=item B<-R>, B<--no-recurse>
Only show dependencies found in the files listed and do not recurse.
-=item -V
+=item B<-V>, B<--verbose>
Verbose mode: Output all files found during the process;
show dependencies between modules and availability.
@@ -204,7 +224,7 @@ Additionally, warns of any missing dependencies. If you find missing
dependencies that aren't really dependencies, you have probably found
false positives.
-=item -C CACHEFILE
+=item B<-C>, B<--cachedeps>=I<CACHEFILE>
Use CACHEFILE to speed up the scanning process by caching dependencies.
Creates CACHEFILE if it does not exist yet.
@@ -1,6 +1,6 @@
use strict;
use Test::More;
-eval "use Test::Pod 1.00";
-plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
+use Test::Requires { "Test::Pod" => "1.00" };
+
all_pod_files_ok();
@@ -3,21 +3,19 @@
use strict;
use warnings;
+use Test::More;
+use Test::Requires qw( prefork );
+
use lib 't';
+use Utils;
+
BEGIN {
- require Test::More;
- if (not eval "require prefork; 1;" or $@) {
- Test::More->import(skip_all => "This test requires prefork.pm which is not installed. Skipping.");
- exit(0);
- }
- else {
# Mwuahahaha!
delete $INC{"prefork.pm"};
%prefork:: = ();
- }
+
+ plan 'no_plan'; # no_plan because the number of objects in the dependency tree (and hence the number of tests) can change
}
-use Test::More qw(no_plan); # no_plan because the number of objects in the dependency tree (and hence the number of tests) can change
-use Utils;
my $rv;
my $root;
@@ -3,16 +3,9 @@
use strict;
use warnings;
-use Test::More tests => 12;
+use Test::More;
my $rv;
-my $root;
-
-##############################################################
-# Tests compilation of Module::ScanDeps
-##############################################################
-BEGIN { use_ok( 'Module::ScanDeps' ); }
-
##############################################################
# Tests static dependency scanning on a real set of modules.
@@ -20,12 +13,23 @@ BEGIN { use_ok( 'Module::ScanDeps' ); }
# majority of files scanned aren't fixed, the checks are
# necessarily loose.
##############################################################
-$root = $0;
my @deps = qw(
- Carp.pm Config.pm Exporter.pm Test/More.pm
- base.pm constant.pm strict.pm vars.pm
+ Carp.pm
+ Config.pm
+ Exporter.pm
+ Test/More.pm
+ constant.pm
+ strict.pm
+ vars.pm
Module/ScanDeps.pm
);
+plan tests => @deps + 3;
+
+##############################################################
+# Tests compilation of Module::ScanDeps
+##############################################################
+use_ok( 'Module::ScanDeps' );
+
my $obj = Module::ScanDeps->new;
$obj->set_file($0);
@@ -5,21 +5,17 @@ use strict;
use warnings;
use Test::More qw(no_plan); # no_plan because the number of objects in the dependency tree (and hence the number of tests) can change
+use Test::Requires qw( Module::Pluggable );
+
use lib qw(t t/data/pluggable);
use Utils;
-if (eval {require Module::Pluggable}) {
- my $rv = scan_deps(
- files => ['t/data/pluggable/Foo.pm'],
- recurse => 1,
- );
-
- my @deps = qw(Module/Pluggable.pm Foo/Plugin/Bar.pm Foo/Plugin/Baz.pm);
- generic_scandeps_rv_test($rv, ['t/data/pluggable/Foo.pm'], \@deps);
+my $rv = scan_deps(
+ files => ['t/data/pluggable/Foo.pm'],
+ recurse => 1,
+);
-} else {
- diag("Module::Pluggable not installed, skipping all tests");
- pass("Marking test as passed because Module::Pluggable is not available.");
-}
+my @deps = qw(Module/Pluggable.pm Foo/Plugin/Bar.pm Foo/Plugin/Baz.pm);
+generic_scandeps_rv_test($rv, ['t/data/pluggable/Foo.pm'], \@deps);
__END__
@@ -1,10 +1,10 @@
#!/usr/bin/perl
-use Test;
-BEGIN { plan tests => 2 }
+use strict;
+use warnings;
+use Test::More tests => 2;
use Module::ScanDeps;
-
use lib qw(t/data);
my $map = scan_deps(
@@ -20,13 +20,13 @@ plan skip_all => "No dynamic module found (tried @try_mods)"
unless @dyna_mods;
diag "dynamic modules used for test: @dyna_mods";
-plan tests => 3 * 2 * @dyna_mods;
+plan tests => 4 * 2 * @dyna_mods;
foreach my $module (@dyna_mods)
{
- # cf. XSLoader.pm
+ # cf. DynaLoader.pm
my @modparts = split(/::/,$module);
- my $modfname = $modparts[-1];
+ my $modfname = defined &DynaLoader::mod2fname ? DynaLoader::mod2fname(\@modparts) : $modparts[-1];
my $auto_path = join('/', 'auto', @modparts, "$modfname.$Config::Config{dlext}");
check_bundle_path($module, $auto_path, ".pl", <<"...",
@@ -61,6 +61,18 @@ exit(0);
execute => 1);
}
);
+ check_bundle_path($module, $auto_path, ".pl", <<"...",
+# no way in hell can this detected by static analysis :)
+my \$req = join("", qw( r e q u i r e ));
+eval "\$req \$_" foreach \@ARGV;
+exit(0);
+...
+ sub { scan_deps_runtime(
+ files => [ $_[0] ],
+ recurse => 0,
+ execute => [ $module ]);
+ }
+ );
}
exit(0);
@@ -0,0 +1,7 @@
+# some forms of "use autouse ..."
+use autouse TestA => qw(foo bar);
+use autouse "TestB", qw(foo bar);
+
+# "use if ..." (note the function call in COND)
+sub frobnicate { 1 }
+use if frobnicate(), TestC => qw(quux);
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use Module::ScanDeps qw(scan_deps);
+use lib qw(t/data/static);
+
+my @expected_modules = qw( TestA TestB TestC );
+plan tests => scalar @expected_modules;
+
+my $rv = scan_deps("t/data/rt90869.pl");
+foreach (@expected_modules)
+{
+ ok(exists $rv->{"$_.pm"}, "expected module $_ found");
+}