diff --git a/.gitignore b/.gitignore index 3c4a0ae..ac034b2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ MANIFEST.bak blib/ pm_to_blib *.tar.gz +.vstags +local \ No newline at end of file diff --git a/lib/Module/ScanDeps.pm b/lib/Module/ScanDeps.pm index eaa7c03..e06c322 100644 --- a/lib/Module/ScanDeps.pm +++ b/lib/Module/ScanDeps.pm @@ -603,6 +603,7 @@ sub scan_deps { modules => [path_to_inc_name($path, $args{warn_missing})], skip => undef, warn_missing => $args{warn_missing}, + include_missing => $args{include_missing}, ); } else { @@ -686,6 +687,7 @@ sub scan_deps_static { modules => [$pm], skip => $args->{skip}, warn_missing => $args->{warn_missing}, + include_missing => $args->{include_missing}, ); my @preload = _get_preload($pm) or next; @@ -696,6 +698,7 @@ sub scan_deps_static { modules => \@preload, skip => $args->{skip}, warn_missing => $args->{warn_missing}, + include_missing => $args->{include_missing}, ); } } @@ -1035,12 +1038,13 @@ sub _find_encoding { sub _add_info { my %args = @_; my ($rv, $module, $file, $used_by, $type) = @args{qw/rv module file used_by type/}; - return unless defined($module) and defined($file); # Ensure file is always absolute - $file = File::Spec->rel2abs($file); - $file =~ s|\\|\/|go; + if($file ne 'MISSING') { + $file = File::Spec->rel2abs($file); + $file =~ s|\\|\/|go; + } # Avoid duplicates that can arise due to case differences that don't actually # matter on a case tolerant system @@ -1095,8 +1099,10 @@ sub add_deps { my $used_by = $args{used_by}; foreach my $module (@{ $args{modules} }) { - my $file = _find_in_inc($module) - or _warn_of_missing_module($module, $args{warn_missing}), next; + my $file = _find_in_inc($module, $args{include_missing}); + + _warn_of_missing_module($module, $args{warn_missing}) if(!$file || $file eq 'MISSING'); + next if !$file; next if $skip->{$file}; if (exists $rv->{$module}) { @@ -1144,6 +1150,8 @@ sub add_deps { sub _find_in_inc { my $file = shift; + my $include_missing = shift ? 'MISSING' : ''; + return unless defined $file; foreach my $dir (grep !/\bBSDPAN\b/, @INC, @IncludeLibs) { @@ -1151,9 +1159,7 @@ sub _find_in_inc { } # absolute file names - return $file if -f $file; - - return; + return -f $file ? $file : $include_missing; } sub _glob_in_inc { @@ -1504,6 +1510,7 @@ sub _info2rv { sub _gettype { my $name = shift; + return 'missing' if $name eq 'MISSING'; return 'autoload' if $name =~ /\.(?:ix|al|bs)$/i; return 'module' if $name =~ /\.p[mh]$/i; return 'shared' if $name =~ /\.\Q$Config{dlext}\E$/i; diff --git a/script/scandeps.pl b/script/scandeps.pl index bed7668..b2e971a 100644 --- a/script/scandeps.pl +++ b/script/scandeps.pl @@ -7,6 +7,7 @@ use Getopt::Long qw(:config bundling no_ignore_case); use Module::ScanDeps; use ExtUtils::MakeMaker; +use File::Find; use subs qw( _name _modtree ); my $usage = "Usage: $0 [ -B ] [ -V ] [ -T ] [ -x [ --xargs STRING ] | -c ] [ -R ] [-C FILE ] [ -e STRING | FILE ... ]\n"; @@ -22,8 +23,17 @@ "T|modtree", "V|verbose", "x|execute", + "m|include-missing", + "like-cpanfile", + "save-cpanfile", + "no-versions", + "force", + "files-from-workdir", ) or die $usage; +die 'Use `--save-cpanfile` only with `--like-cpanfile` option' if ($opts{'save-cpanfile'} and not $opts{'like-cpanfile'}); +die 'Use `--force` only with `--save-cpanfile` option' if ($opts{'force'} and not $opts{'save-cpanfile'}); + my (%map, %skip); my $core = $opts{B}; my $verbose = $opts{V}; @@ -31,6 +41,21 @@ my $recurse = $opts{R} ? 0 : 1; my $modtree = {} unless $opts{T}; # i.e. disable it unless explicitly requested +if($opts{'files-from-workdir'}) { #todo make custom filemask + # use lib 'lib'; + finddepth({ + wanted => sub { push @ARGV, $_ if /\.pl$/ }, + no_chdir => 1, + }, 'bin'); + + finddepth({ + wanted => sub { push @ARGV, $_ if /\.pm$/ }, + no_chdir => 1, + }, 'lib'); + + # warn "Files found: ", join ", ", @ARGV; +} + if ($eval) { require File::Temp; my ($fh, $filename) = File::Temp::tempfile( UNLINK => 1 ); @@ -59,9 +84,9 @@ $opts{c} ? ( compile => 1 ) : (), $opts{V} ? ( warn_missing => 1 ) : (), $opts{C} ? ( cache_file => $opts{C}) : (), + $opts{m} ? ( include_missing => $opts{m}) : (), ); - my $len = 0; my @todo; my (%seen, %dist, %core, %bin); @@ -79,7 +104,11 @@ $bin{$key}++; } - next unless $mod->{type} eq 'module'; + # warn $mod->{type}; + if($mod->{type} ne 'module') { + if ($opts{m}) { next if $mod->{type} ne 'missing'; } + else { next } + } next if $skip{$name}; @@ -107,10 +136,27 @@ print "#\n# Legend: [C]ore [X]ternal [S]ubmodule [?]NotOnCPAN\n" if $verbose; -foreach my $mod (sort { $a->{name} cmp $b->{name} } @todo ) { - my $version = MM->parse_version($mod->{file}); +my $cpanfile_fh; +if ($opts{'save-cpanfile'} and $opts{'like-cpanfile'}) { + die "Attention! cpanfile already exists. Use `--force` option to overwrite it." if -f 'cpanfile' and not $opts{force}; + open($cpanfile_fh, '>', "cpanfile") or die "Attention! Cant open cpanfile. $!."; +} - if (!$verbose) { +foreach my $mod (sort { $a->{name} cmp $b->{name} } @todo ) { + # warn Dumper $mod; + my $version = ($opts{m} and $mod->{type} eq 'missing') ? 0 : MM->parse_version($mod->{file}); + # warn $version; + if($opts{'like-cpanfile'}) { + $version = 0 if $opts{'no-versions'}; + # use Data::Dumper; warn Dumper $mod; + my $cpanfile_str = sprintf "requires '%s', '%s';\n", $mod->{name}, ($version eq 'undef' ? 0 : $version); + + if($cpanfile_fh) { print $cpanfile_fh $cpanfile_str } + else { print $cpanfile_str } + + next; + } + elsif (!$verbose) { printf "%-${len}s => '$version',", "'$mod->{name}'" if $version; } else { printf "%-${len}s => '0', # ", "'$mod->{name}'"; @@ -234,6 +280,35 @@ =head1 OPTIONS Retrieves module information from CPAN if you have B installed. +no-versions +force + +=item B<--files-from-workdir> + +Finds *.pm files from C<$PWD/lib> and *.pl files from C<$PWD/bin>. + +=back + +=item B<-m>, B<--include-missing> + +Shows missing modules too. + +=item B<--no-versions> + +All versions will be set to 0. + +=item B<--like-cpanfile> + +Shows dependencies in cpanfile syntax. + +=item B<--save-cpanfile> + +Could be used only with C<--like-cpanfile> option. Saves cpanfile to the working directory. + +=item B<--force> + +Could be used only with C<--like-cpanfile> and C<--save-cpanfile> options. Overwrites cpanfile to the working directory. + =back =head1 SEE ALSO