File Coverage

blib/lib/File/Find/Rule/Perl.pm
Criterion Covered Total %
statement 81 96 84.3
branch 29 40 72.5
condition 10 15 66.6
subroutine 15 20 75.0
pod 0 6 0.0
total 135 177 76.2


line stmt bran cond sub pod time code
1             package File::Find::Rule::Perl;
2              
3             =pod
4              
5             =head1 NAME
6              
7             File::Find::Rule::Perl - Common rules for searching for Perl things
8              
9             =head1 SYNOPSIS
10              
11             use File::Find::Rule ();
12             use File::Find::Rule::Perl ();
13            
14             # Find all Perl files smaller than 10k
15             my @files = File::Find::Rule->perl_file
16             ->size('<10Ki')
17             ->in('dir');
18            
19             # Locate all the modules that PAUSE will index
20             my @mod = File::Find::Rule->no_index
21             ->perl_module
22             ->in('My-Distribution');
23              
24             =head1 DESCRIPTION
25              
26             I write a lot of things that muck with Perl files. And it always annoyed
27             me that finding "perl files" requires a moderately complex
28             L pattern.
29              
30             B provides methods for finding various
31             types Perl-related files, or replicating search queries run on a
32             distribution in various parts of the CPAN ecosystem.
33              
34             =head1 METHODS
35              
36             =cut
37              
38 3     3   46808 use 5.006;
  3         9  
  3         96  
39 3     3   12 use strict;
  3         4  
  3         77  
40 3     3   18 use warnings;
  3         3  
  3         86  
41 3     3   12 use Carp;
  3         3  
  3         239  
42 3     3   14 use File::Spec 0.82 ();
  3         62  
  3         55  
43 3     3   24 use File::Spec::Unix ();
  3         8  
  3         67  
44 3     3   460 use File::Find::Rule 0.20 ();
  3         5659  
  3         64  
45 3     3   1616 use Params::Util 0.38 ();
  3         10114  
  3         81  
46 3     3   1281 use Parse::CPAN::Meta 1.38 ();
  3         2291  
  3         84  
47              
48             our $VERSION = '1.14';
49 3     3   23 use base 'File::Find::Rule';
  3         4  
  3         408  
50             our @EXPORT = @File::Find::Rule::EXPORT;
51              
52 3     3   17 use constant FFR => 'File::Find::Rule';
  3         4  
  3         2401  
53              
54              
55              
56              
57              
58             #####################################################################
59             # File::Find::Rule Method Addition
60              
61             =pod
62              
63             =head2 perl_module
64              
65             The C rule locates perl modules. That is, files that
66             are named C<*.pm>.
67              
68             This rule is equivalent to C<-E>file-Ename( '*.pm' )> and is
69             included primarily for completeness.
70              
71             =cut
72              
73             sub File::Find::Rule::perl_module {
74 0     0 0 0 my $find = $_[0]->_force_object;
75 0         0 return $find->name('*.pm')->file;
76             }
77              
78             =pod
79              
80             =head2 perl_test
81              
82             The C rule locates perl test scripts. That is, files that
83             are named C<*.t>.
84              
85             This rule is equivalent to C<-E>file-Ename( '*.t' )> and is
86             included primarily for completeness.
87              
88             =cut
89              
90             sub File::Find::Rule::perl_test {
91 0     0 0 0 my $find = $_[0]->_force_object;
92 0         0 return $find->name('*.t')->file;
93             }
94              
95             =pod
96              
97             =head2 perl_installer
98              
99             The C rule locates perl distribution installers. That is,
100             it locates C and C files.
101              
102             =cut
103              
104             sub File::Find::Rule::perl_installer {
105 0     0 0 0 my $self = shift()->_force_object;
106 0         0 return $self->file->name( 'Makefile.PL', 'Build.PL' );
107             }
108              
109             =pod
110              
111             =head2 perl_script
112              
113             The C rule locates perl scripts.
114              
115             This is any file that ends in F<.pl>, or any files without extensions
116             that have a perl "hash-bang" line.
117              
118             =cut
119              
120             sub File::Find::Rule::perl_script {
121 0     0 0 0 my $self = shift()->_force_object;
122 0         0 $self->or(
123             FFR->name( '*.pl' )->file,
124             FFR->name( qr/^[^.]+$/ )->file
125             ->exec( \&File::Find::Rule::Perl::_shebang ),
126             );
127             }
128              
129             sub File::Find::Rule::Perl::_shebang {
130 0     0   0 local *SEARCHFILE;
131 0 0       0 open SEARCHFILE, $_ or return !1;
132 0         0 my $first_line = ;
133 0         0 close SEARCHFILE;
134 0 0       0 return !1 unless defined $first_line;
135 0         0 return $first_line =~ /^#!.*\bperl\b/;
136             }
137              
138             =pod
139              
140             =head2 perl_file
141              
142             The C rule locates all files containing Perl code.
143              
144             This includes all the files matching the above C,
145             C, C and C rules.
146              
147             =cut
148              
149             sub File::Find::Rule::perl_file {
150 2     2 0 1980 my $self = shift()->_force_object;
151 2         24 $self->or(
152             FFR->name('*.pm', '*.t', '*.pl', 'Makefile.PL', 'Build.PL')->file,
153             FFR->name( qr/^[^.]+$/ )->file
154             ->exec( \&File::Find::Rule::Perl::_shebang ),
155             );
156             }
157              
158             =pod
159              
160             =head2 no_index
161              
162             # Provide the rules directly
163             $rule->no_index(
164             directory => [ 'inc', 't', 'examples' ],
165             file => [ 'Foo.pm', 'lib/Foo.pm' ],
166             );
167            
168             # Provide a META.yml to use
169             $rule->no_index( 'META.yml' );
170            
171             # Provide a dist root directory to look for a META.yml in
172             $rule->no_index( 'My-Distribution' );
173            
174             # Automatically pick up a META.yml from the target directory
175             $rule->no_index->in( 'My-Distribution' );
176              
177             The C method applies a set of rules as per the no_index section
178             in a C file.
179              
180             =cut
181              
182             # There's probably some bugs in this process somewhere,
183             sub File::Find::Rule::no_index {
184 10     10 0 8663 my $find = shift()->_force_object;
185              
186             # Variables we'll need in the closure
187 10         40 my $rule = undef;
188 10         8 my $root = undef;
189              
190             # Handle the various param options
191 10 100       34 if ( @_ == 0 ) {
    100          
    50          
192             # No params means we auto-calculate
193 5         4 $rule = undef;
194              
195             } elsif ( Params::Util::_HASHLIKE($_[0]) ) {
196 3         5 $rule = _no_index($_[0]);
197              
198             } elsif ( defined Params::Util::_STRING($_[0]) ) {
199 2         2 my $path = shift;
200 2 100       21 if ( -d $path ) {
201             # This is probably a dist directory
202 1         8 my $meta = File::Spec->catfile($path, 'META.yml');
203 1 50       7 $path = $meta if -f $meta;
204             }
205 2 50       10 if ( -f $path ) {
206             # This is a META.yml file
207 2         5 my $meta = Parse::CPAN::Meta::LoadFile($path);
208              
209             # Shortcut if there's nothing to do
210 2         2336 my $no_index = $meta->{no_index};
211 2 50       5 if ( $no_index ) {
212 2         4 $rule = _no_index($no_index);
213             }
214             }
215             } else {
216 0         0 Carp::croak("Invalid or unsupported parameter type");
217             }
218              
219             # Generate the subroutine in advance
220             my $function = sub {
221 368     368   23229 my $shortname = $_[0];
222 368         306 my $fullname = $_[2];
223              
224             # In the automated case the first time we are
225             # called we are passed the META.yml-relative root.
226 368 100       522 unless ( defined $root ) {
227 10 100       36 if ( File::Spec->file_name_is_absolute($fullname) ) {
228 3         3 $root = $fullname;
229             } else {
230 7         108 $root = File::Spec->rel2abs(
231             File::Spec->curdir
232             );
233             }
234             }
235 368 100       450 unless ( defined $rule ) {
236 5         3 $rule = '';
237 5         27 my $meta = File::Spec->catfile( $root, 'META.yml' );
238 5 50       67 if ( -f $meta ) {
239 5         13 my $yaml = Parse::CPAN::Meta::LoadFile($meta);
240 5 50 33     14972 if ( $yaml and $yaml->{no_index} ) {
241 5         12 $rule = _no_index( $yaml->{no_index} );
242             }
243             }
244             }
245              
246             # Shortcut when there is no META.yml
247 368 50       450 return 0 unless $rule;
248              
249             # Derive the META.yml-relative unix path
250 368 100       3405 my $absname = File::Spec->file_name_is_absolute($fullname)
251             ? $fullname
252             : File::Spec->rel2abs($shortname);
253 368         11828 my $relpath = File::Spec->abs2rel($absname, $root);
254              
255             # Attempt to match a META.yml entry
256 368 100 66     1594 if ( ($rule->{directory}->{$relpath} or $rule->{directory}->{$absname} ) and -d $absname ) {
      66        
257 8         138 return 1;
258             }
259 360 100 100     1092 if ( ( $rule->{file}->{$relpath} or $rule->{file}->{$absname} ) and -f $absname ) {
      66        
260 2         36 return 1;
261             }
262 358         5698 return 0;
263 10         35 };
264              
265             # Generate the rule
266 10         30 return $find->or(
267             FFR->exec( $function )->prune->discard,
268             FFR->new,
269             );
270             }
271              
272             sub _no_index {
273 10     10   9 my $param = shift;
274              
275             # Index the directory and file entries for faster access
276 2         8 my %file = $param->{file} ? (
277 10 100       19 map { $_ => 1 } @{$param->{file}}
  2         3  
278             ) : ();
279 17         32 my %directory = $param->{directory} ? (
280 10 100       17 map { $_ => 1 } @{$param->{directory}}
  8         31  
281             ) : ();
282              
283             return {
284 10         53 file => \%file,
285             directory => \%directory,
286             };
287             }
288              
289             1;
290              
291             =pod
292              
293             =head1 SUPPORT
294              
295             Bugs should always be submitted via the CPAN bug tracker
296              
297             L
298              
299             For other issues, contact the maintainer
300              
301             =head1 AUTHOR
302              
303             Adam Kennedy Eadamk@cpan.orgE
304              
305             =head1 SEE ALSO
306              
307             L, L, L
308              
309             =head1 COPYRIGHT
310              
311             Copyright 2006 - 2012 Adam Kennedy.
312              
313             This program is free software; you can redistribute
314             it and/or modify it under the same terms as Perl itself.
315              
316             The full text of the license can be found in the
317             LICENSE file included with this module.
318              
319             =cut