File Coverage

blib/lib/Module/Mapper.pm
Criterion Covered Total %
statement 128 135 94.8
branch 69 126 54.7
condition 33 63 52.3
subroutine 10 10 100.0
pod 1 1 100.0
total 241 335 71.9


line stmt bran cond sub pod time code
1             package Module::Mapper;
2              
3 2     2   32370 use Getopt::Long qw(:config no_ignore_case permute);
  2         31710  
  2         15  
4 2     2   2419 use File::Spec::Functions qw(splitpath catpath);
  2         1648  
  2         147  
5 2     2   24 use File::Path;
  2         4  
  2         121  
6 2     2   10 use File::Find;
  2         4  
  2         103  
7 2     2   2894 use Pod::Usage;
  2         174613  
  2         298  
8              
9 2     2   22 use base ('Exporter');
  2         4  
  2         232  
10              
11             @EXPORT = ('find_sources');
12             $VERSION = '1.01';
13              
14 2     2   10 use strict;
  2         3  
  2         61  
15 2     2   10 use warnings;
  2         3  
  2         4656  
16              
17             sub find_sources {
18 3     3 1 2662 my %options = @_;
19              
20 3         8 my $all = $options{All};
21 3         8 my $path = $options{Output};
22 3         6 my $verbose = $options{Verbose};
23 3 100       11 my @modules = $options{Modules} ? @{$options{Modules}} : ();
  2         5  
24 3 100       10 my @localdirs = $options{Libs} ? @{$options{Libs}} : ();
  2         5  
25 3 100       9 my @exes = $options{Scripts} ? @{$options{Scripts}} : ();
  2         5  
26 3         4 my $useINC = $options{UseINC};
27 3         7 my $usepod = $options{IncludePOD};
28 3   50     17 my $projdir = $options{Project} || '.';
29              
30 3 50 33     11 $@ = "-verbose must be a coderef\n",
31             return undef
32             if $verbose && (ref $verbose ne 'CODE');
33             #
34             # normalize and test for the directories
35             #
36 3         8 foreach (@localdirs) {
37 2         6 s![/\\]$!!;
38 2 50       37 $@ = "Cannot find directory $_, exitting.\n",
39             return undef
40             unless -d;
41             }
42              
43 3 0 66     19 $@ = "Nothing to do, exitting (perhaps you forgot -exes or -modules ?).",
      33        
      33        
44             return undef
45             if $useINC && (! scalar @localdirs) && (! scalar @modules) && (! scalar @exes);
46              
47 3         4 my $havepath = defined $path;
48 3         5 my @files = ();
49 3         6 my %exes = ();
50 3         4 my %modules = ();
51 3 50 66     16 if ((! scalar @modules) && (! scalar @exes)) {
52             #
53             # project mode
54             #
55 1         4 $projdir=~s!/$!!;
56 1 50 33     30 $@ = "No local project directories",
57             return undef
58             unless -d "$projdir/bin" || -d "$projdir/lib";
59 1 50       4 $verbose->("Project mode: Scanning $projdir/bin and $projdir/lib...\n") if $verbose;
60 1 50       49 if (opendir(INDIR, "$projdir/bin")) {
61 1         22 while (my $file = readdir(INDIR)) {
62 3 50       62 $exes{"$projdir/bin/$file"} = $havepath ? "$path/bin/$file" : 1
    100          
63             unless -d "$projdir/bin/$file";
64             }
65 1         16 closedir INDIR;
66             }
67            
68 1         10 _collectFiles("$projdir/lib", $usepod, \%modules, "$path/blib", '');
69            
70 1 50       6 if ($verbose) {
71 0 0       0 if ($havepath) {
72             $verbose->("$_ maps to $exes{$_}\n")
73 0         0 foreach (sort keys %exes);
74             }
75             else {
76             $verbose->("Found $_\n")
77 0         0 foreach (sort keys %exes);
78             }
79             }
80             #
81             # trim any empty namespaces
82             #
83 1         11 foreach (sort keys %modules) {
84 1         6 delete $modules{$_},
85             next
86 1 50       2 unless ($#{$modules{$_}} > -1);
87 1 0       6 $verbose->(defined $modules{$_}[0] ?
    0          
    0          
    50          
88             ($havepath ?
89             "$_ found in $modules{$_}[0] maps to $modules{$_}[1]\n" :
90             "$_ found in $modules{$_}[0]\n") :
91             ($havepath ?
92             "$_ found in $modules{$_}[2] maps to $modules{$_}[3]\n" :
93             "$_ found in $modules{$_}[2]\n"))
94             if $verbose;
95             }
96              
97             $modules{$_} = [ $_, $exes{$_} ]
98 1         6 foreach (keys %exes);
99              
100 1         7 return \%modules;
101             }
102             #
103             # process exes first
104             #
105 2         5 foreach (@exes) {
106 2 50 33     32 $verbose->("$_ not found\n") unless -e || (! $verbose);
107              
108 2 50       18 $@ = "$_ not a file\n",
109             return undef
110             if -d;
111 2         11 my ($volume, $subdir, $file) = splitpath( $_ );
112 2 50       44 $exes{$_} = $havepath ? "$path/bin/$file" : 1;
113             }
114             #
115             # now modules
116             #
117 2         4 foreach my $module (@modules) {
118 3         6 my $srcfile = "$module.pm";
119 3         7 my $podfile = "$module.pod";
120 3         4 my $root = $module;
121 3         9 $srcfile=~s!\:\:!/!g;
122 3         8 $podfile=~s!\:\:!/!g;
123 3         6 $root=~s!\:\:!/!g;
124 3 50       9 my $outroot = $havepath ? "$path/$root" : undef;
125 3         4 my $hasdir;
126            
127 3         6 foreach (@localdirs) {
128 3 50       9 $verbose->("Scanning $_ for $module...\n") if $verbose;
129 3 50       51 $modules{$module} = [ "$_/$srcfile", ($havepath ? "$path/blib/$srcfile" : 1) ]
    100          
130             if -e "$_/$srcfile";
131            
132 1         8 $modules{$module} ||= [ undef, undef ],
133 3 50 50     47 push @{$modules{$module}}, "$_/$podfile", ($havepath ? "$path/blib/$podfile" : 1)
    100 66        
134             if $usepod && (-e "$_/$podfile");
135             #
136             # might be namespace parent
137             #
138 3 100 50     38 $modules{$module} ||= []
139             if (-d "$_/$root");
140              
141 3 100       13 $outroot = "$path/blib/$root",
142             $root = "$_/$root",
143             last
144             if exists $modules{$module};
145             }
146 3 100 66     16 if ($useINC && (! exists $modules{$module})) {
147 1         3 foreach (@INC) {
148 10 50       28 $verbose->("Scanning $_ for $module...\n") if $verbose;
149 10 50       319 $modules{$module} = [ "$_/$srcfile", ($havepath ? "$path/lib/$srcfile" : 1) ]
    100          
150             if -e "$_/$srcfile";
151            
152 0         0 $modules{$module} ||= [ undef, undef ],
153 10 0 0     253 push @{$modules{$module}}, "$_/$podfile", ($havepath ? "$path/lib/$podfile" : 1)
    50 33        
154             if $usepod && (-e "$_/$podfile");
155             #
156             # might be namespace parent
157             #
158 10 50 0     213 $modules{$module} ||= []
159             if (-d "$_/$root");
160 10 50 66     219 $outroot = ($havepath ? "$path/lib/$root" : undef),
    100          
161             $root = "$_/$root",
162             last
163             if exists $modules{$module} || (-d "$_/$root");
164             }
165             }
166 3 100 66     13 unless ($all && exists $modules{$module}) {
167 2 50       4 $verbose->("$module not found\n") if $verbose;
168 2         6 next;
169             }
170              
171 1 50       4 next unless $all;
172             #
173             # recurse into subdirs and collect all the package/pods
174             #
175 1 50       3 $verbose->("$module found, scanning for children...\n") if $verbose;
176 1         5 _collectFiles($root, $usepod, \%modules, $outroot, $module);
177 1 50       2 if ($#{$modules{$module}} == -1) {
  1         5  
178             #
179             # check if any children found
180             #
181 1         2 my $childcnt = 0;
182 1         3 $module .= '::';
183 1         5 while (my ($m, $c) = each %modules) {
184 2 50 66     21 $childcnt++, last
      66        
185             if ($#$c > -1) &&
186             (length($m) > 2 + length($module)) &&
187             (substr($m, 0, length($module)) eq $module);
188             }
189 1 50 33     7 $verbose->("$module namespace is empty\n") unless $childcnt || (! $verbose);
190             }
191             }
192              
193 2 50       6 if ($verbose) {
194 0 0       0 if ($havepath) {
195             $verbose->("$projdir/bin/$_ maps to $exes{$_}\n")
196 0         0 foreach (sort keys %exes);
197             }
198             else {
199             $verbose->("Found $_ in $projdir/bin\n")
200 0         0 foreach (sort keys %exes);
201             }
202             }
203 2         11 foreach (sort keys %modules) {
204             #
205             # trim any empty namespaces
206             #
207 4         15 delete $modules{$_},
208             next
209 4 100       4 unless ($#{$modules{$_}} > -1);
210              
211 3 0       14 $verbose->(defined $modules{$_}[0] ?
    0          
    0          
    50          
212             ($havepath ?
213             "$_ found in $modules{$_}[0]\n\tmaps to $modules{$_}[1]\n" :
214             "$_ found in $modules{$_}[0]\n") :
215             ($havepath ?
216             "$_ found in $modules{$_}[2]\n\tmaps to $modules{$_}[3]\n" :
217             "$_ found in $modules{$_}[2]\n"))
218             if $verbose;
219             }
220              
221             $modules{$_} = [ $_, $exes{$_} ]
222 2         12 foreach (keys %exes);
223              
224 2         13 return \%modules;
225             }
226              
227             sub _collectFiles {
228 3     3   8 my ($dir, $usepod, $modules, $outpath, $pkgroot) = @_;
229 3         6 my @children = ();
230 3 50       70 opendir(INDIR, $dir) or return $modules;
231 3         39 while (my $child = readdir(INDIR)) {
232 11 100 100     118 push (@children, $child)
233             if (substr($child, 0, 1) ne '.') && -d "$dir/$child";
234              
235             next
236 11 100       204 if -d "$dir/$child";
237              
238 4 50 66     34 if ((substr($child, -3) eq '.pm') || (substr($child, -4) eq '.pod')) {
239 4         24 $child=~s/\.(pm|pod)$//;
240 4 50       13 my $module = $pkgroot ? "$pkgroot\::$child" : $child;
241 4   100     36 $modules->{$module} ||= [];
242 4 100       14 if ($1 eq 'pm') {
243 2         9 $modules->{$module}[0] = "$dir/$child.pm";
244 2 50       15 $modules->{$module}[1] = $outpath ? "$outpath/$child.pm" : 1;
245             }
246             else {
247 2         7 $modules->{$module}[2] = "$dir/$child.pod";
248 2 50       15 $modules->{$module}[3] = $outpath ? "$outpath/$child.pod" : 1;
249             }
250             }
251             }
252 3         30 closedir INDIR;
253             _collectFiles("$dir/$_", $usepod, $modules, ($outpath ? "$outpath/$_" : undef),
254             ($pkgroot ? "$pkgroot\::$_" : $_) )
255 3 50       22 foreach (@children);
    50          
256 3         8 return $modules;
257             }
258              
259             1;