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   38251 use 5.006;
  3         7  
  3         72  
39 3     3   9 use strict;
  3         1  
  3         54  
40 3     3   11 use warnings;
  3         3  
  3         58  
41 3     3   8 use Carp;
  3         3  
  3         142  
42 3     3   9 use File::Spec 0.82 ();
  3         44  
  3         35  
43 3     3   9 use File::Spec::Unix ();
  3         1  
  3         34  
44 3     3   382 use File::Find::Rule 0.20 ();
  3         4939  
  3         46  
45 3     3   1171 use Params::Util 0.38 ();
  3         8515  
  3         59  
46 3     3   1136 use Parse::CPAN::Meta 1.38 ();
  3         2260  
  3         97  
47              
48             our $VERSION = '1.15';
49 3     3   28 use base 'File::Find::Rule';
  3         3  
  3         275  
50             our @EXPORT = @File::Find::Rule::EXPORT;
51              
52 3     3   13 use constant FFR => 'File::Find::Rule';
  3         3  
  3         2159  
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 1657 my $self = shift()->_force_object;
151 2         17 $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 10665 my $find = shift()->_force_object;
185              
186             # Variables we'll need in the closure
187 10         49 my $rule = undef;
188 10         10 my $root = undef;
189              
190             # Handle the various param options
191 10 100       41 if ( @_ == 0 ) {
    100          
    50          
192             # No params means we auto-calculate
193 5         5 $rule = undef;
194              
195             } elsif ( Params::Util::_HASHLIKE($_[0]) ) {
196 3         8 $rule = _no_index($_[0]);
197              
198             } elsif ( defined Params::Util::_STRING($_[0]) ) {
199 2         3 my $path = shift;
200 2 100       31 if ( -d $path ) {
201             # This is probably a dist directory
202 1         12 my $meta = File::Spec->catfile($path, 'META.yml');
203 1 50       10 $path = $meta if -f $meta;
204             }
205 2 50       11 if ( -f $path ) {
206             # This is a META.yml file
207 2         6 my $meta = Parse::CPAN::Meta::LoadFile($path);
208              
209             # Shortcut if there's nothing to do
210 2         2467 my $no_index = $meta->{no_index};
211 2 50       7 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   30142 my $shortname = $_[0];
222 368         327 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       592 unless ( defined $root ) {
227 10 100       48 if ( File::Spec->file_name_is_absolute($fullname) ) {
228 3         4 $root = $fullname;
229             } else {
230 7         121 $root = File::Spec->rel2abs(
231             File::Spec->curdir
232             );
233             }
234             }
235 368 100       534 unless ( defined $rule ) {
236 5         5 $rule = '';
237 5         30 my $meta = File::Spec->catfile( $root, 'META.yml' );
238 5 50       74 if ( -f $meta ) {
239 5         11 my $yaml = Parse::CPAN::Meta::LoadFile($meta);
240 5 50 33     35222 if ( $yaml and $yaml->{no_index} ) {
241 5         11 $rule = _no_index( $yaml->{no_index} );
242             }
243             }
244             }
245              
246             # Shortcut when there is no META.yml
247 368 50       525 return 0 unless $rule;
248              
249             # Derive the META.yml-relative unix path
250 368 100       4590 my $absname = File::Spec->file_name_is_absolute($fullname)
251             ? $fullname
252             : File::Spec->rel2abs($shortname);
253 368         16500 my $relpath = File::Spec->abs2rel($absname, $root);
254              
255             # Attempt to match a META.yml entry
256 368 100 66     1968 if ( ($rule->{directory}->{$relpath} or $rule->{directory}->{$absname} ) and -d $absname ) {
      66        
257 8         155 return 1;
258             }
259 360 100 100     1387 if ( ( $rule->{file}->{$relpath} or $rule->{file}->{$absname} ) and -f $absname ) {
      66        
260 2         57 return 1;
261             }
262 358         8257 return 0;
263 10         45 };
264              
265             # Generate the rule
266 10         39 return $find->or(
267             FFR->exec( $function )->prune->discard,
268             FFR->new,
269             );
270             }
271              
272             sub _no_index {
273 10     10   17 my $param = shift;
274              
275             # Index the directory and file entries for faster access
276 2         9 my %file = $param->{file} ? (
277 10 100       24 map { $_ => 1 } @{$param->{file}}
  2         5  
278             ) : ();
279 17         35 my %directory = $param->{directory} ? (
280 10 100       24 map { $_ => 1 } @{$param->{directory}}
  8         35  
281             ) : ();
282              
283             return {
284 10         63 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