File Coverage

blib/lib/Perl/Metrics/Lite/FileFinder.pm
Criterion Covered Total %
statement 59 61 96.7
branch 12 16 75.0
condition n/a
subroutine 15 15 100.0
pod 3 5 60.0
total 89 97 91.7


line stmt bran cond sub pod time code
1             package Perl::Metrics::Lite::FileFinder;
2 4     4   27 use strict;
  4         8  
  4         113  
3 4     4   18 use warnings;
  4         9  
  4         172  
4 4     4   27 use Carp qw(cluck confess);
  4         8  
  4         232  
5 4     4   1132 use English qw(-no_match_vars);
  4         9281  
  4         32  
6 4     4   1550 use File::Basename qw(fileparse);
  4         10  
  4         247  
7 4     4   25 use File::Find qw(find);
  4         8  
  4         245  
8 4     4   1885 use IO::File;
  4         33732  
  4         470  
9 4     4   1078 use Readonly;
  4         7864  
  4         2805  
10              
11             Readonly::Scalar our $PERL_FILE_SUFFIXES => qr{ \. (:? pl | pm | t ) }sxmi;
12             Readonly::Scalar our $SKIP_LIST_REGEX =>
13             qr{ \.svn | \. git | _darcs | CVS }sxmi;
14             Readonly::Scalar my $PERL_SHEBANG_REGEX => qr/ \A [#] ! .* perl /sxm;
15             Readonly::Scalar my $DOT_FILE_REGEX => qr/ \A [.] /sxm;
16              
17             sub new {
18 7     7 0 3986 my ( $class, %args ) = @_;
19 7         20 my $self = bless( {}, $class );
20 7         22 return $self;
21             }
22              
23             sub find_files {
24 7     7 1 934 my ( $self, @directories_and_files ) = @_;
25 7         18 foreach my $path (@directories_and_files) {
26 7 100       218 if ( !-r $path ) {
27 1         172 confess "Path '$path' is not readable!";
28             }
29             }
30 6         34 my @found = $self->list_perl_files(@directories_and_files);
31 6         34 return \@found;
32             }
33              
34             sub list_perl_files {
35 6     6 1 24 my ( $self, @paths ) = @_;
36 6         10 my @files;
37              
38             my $wanted = sub {
39 36 50   36   150 return if $self->should_be_skipped($File::Find::name);
40 36 100       101 if ( $self->is_perl_file($File::Find::name) ) {
41 18         286 push @files, $File::Find::name; ## no critic (ProhibitPackageVars)
42             }
43 6         38 };
44              
45 6         616 File::Find::find( { wanted => $wanted, no_chdir => 1 }, @paths );
46              
47 6         41 my @sorted_list = sort @files;
48 6         39 return @sorted_list;
49             }
50              
51             sub should_be_skipped {
52 39     39 0 870 my ( $self, $fullpath ) = @_;
53 39         566 my ( $name, $path, $suffix ) = File::Basename::fileparse($fullpath);
54 39         375 return $path =~ $SKIP_LIST_REGEX;
55             }
56              
57             sub is_perl_file {
58 36     36 1 145 my ( $self, $path ) = @_;
59 36 100       1865 return if ( !-f $path );
60 21         723 my ( $name, $path_part, $suffix )
61             = File::Basename::fileparse( $path, $PERL_FILE_SUFFIXES );
62 21 50       130 return if $name =~ $DOT_FILE_REGEX;
63 21 100       72 if ( length $suffix ) {
64 15         48 return 1;
65             }
66 6         22 return _has_perl_shebang($path);
67             }
68              
69             sub _has_perl_shebang {
70 6     6   18 my $path = shift;
71              
72 6         48 my $fh = IO::File->new( $path, '<' );
73 6 50       736 if ( !-r $fh ) {
74 0         0 cluck "Could not open '$path' for reading: $OS_ERROR";
75 0         0 return;
76             }
77 6         140 my $first_line = <$fh>;
78 6         57 $fh->close();
79 6 50       126 return if ( !$first_line );
80 6         144 return $first_line =~ $PERL_SHEBANG_REGEX;
81             }
82              
83             1;
84              
85             __END__