File Coverage

blib/lib/Dist/Zilla/Plugin/FileFinder/ByName.pm
Criterion Covered Total %
statement 43 43 100.0
branch 7 8 87.5
condition 12 12 100.0
subroutine 10 10 100.0
pod 0 3 0.0
total 72 76 94.7


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::FileFinder::ByName 6.030;
2             # ABSTRACT: FileFinder matching on pathnames
3              
4 2     2   1984 use Moose;
  2         6  
  2         18  
5             with 'Dist::Zilla::Role::FileFinder';
6              
7 2     2   14189 use Dist::Zilla::Pragmas;
  2         6  
  2         20  
8              
9 2     2   16 use namespace::autoclean;
  2         6  
  2         22  
10              
11             #pod =head1 SYNOPSIS
12             #pod
13             #pod In your F<dist.ini>:
14             #pod
15             #pod [FileFinder::ByName / MyFiles]
16             #pod dir = bin ; look in the bin/ directory
17             #pod dir = lib ; and the lib/ directory
18             #pod file = *.pl ; for .pl files
19             #pod match = \.pm$ ; and for .pm files
20             #pod skip = ignore ; that don't have "ignore" in the path
21             #pod
22             #pod =head1 CREDITS
23             #pod
24             #pod This plugin was originally contributed by Christopher J. Madsen.
25             #pod
26             #pod =cut
27              
28 2     2   222 use Moose::Util::TypeConstraints;
  2         5  
  2         23  
29 2     2   4846 use MooseX::Types::Moose qw(ArrayRef RegexpRef Str);
  2         5  
  2         29  
30              
31 2     2   12402 use Text::Glob 0.08 qw(glob_to_regex_string);
  2         1153  
  2         1761  
32              
33             #pod =attr dir
34             #pod
35             #pod The file must be located in one of the specified directories (relative
36             #pod to the root directory of the dist).
37             #pod
38             #pod =attr file
39             #pod
40             #pod The filename must match one of the specified patterns (which are
41             #pod converted to regexs using L<Text::Glob> and combined with any C<match>
42             #pod rules).
43             #pod
44             #pod =cut
45              
46             has dirs => (
47             is => 'ro',
48             isa => ArrayRef[Str],
49             default => sub { [] },
50             );
51              
52             has files => (
53             is => 'ro',
54             isa => ArrayRef[Str],
55             default => sub { [] },
56             );
57              
58             {
59             my $type = subtype as ArrayRef[RegexpRef];
60             coerce $type, from ArrayRef[Str], via { [map { qr/$_/ } @$_] };
61              
62             #pod =attr match
63             #pod
64             #pod The pathname must match one of these regular expressions.
65             #pod
66             #pod =attr skip
67             #pod
68             #pod The pathname must I<not> match any of these regular expressions.
69             #pod
70             #pod =cut
71              
72             has matches => (
73             is => 'ro',
74             isa => $type,
75             coerce => 1,
76             default => sub { [] },
77             );
78              
79             has skips => (
80             is => 'ro',
81             isa => $type,
82             coerce => 1,
83             default => sub { [] },
84             );
85             }
86              
87 7     7 0 1132 sub mvp_aliases { +{ qw(
88             dir dirs
89             file files
90             match matches
91             matching matches
92             skip skips
93             except skips
94             ) } }
95              
96 7     7 0 1981 sub mvp_multivalue_args { qw(dirs files matches skips) }
97              
98             sub _join_re {
99 39     39   80 my $list = shift;
100 39 100       107 return undef unless @$list;
101             # Special case to avoid stringify+compile
102 22 100       75 return $list->[0] if @$list == 1;
103             # Wrap each element to ensure that alternations are isolated
104 8         22 my $re = join('|', map { "(?:$_)" } @$list);
  16         70  
105 8         312 qr/$re/
106             }
107              
108             sub find_files {
109 13     13 0 52 my $self = shift;
110              
111 13         452 my $skip = _join_re($self->skips);
112 13         8677 my $dir = _join_re([ map { qr!^\Q$_/! } @{ $self->dirs } ]);
  10         329  
  13         443  
113             my $match = _join_re([
114 8         34 (map { my $re = glob_to_regex_string($_); qr!(?:\A|/)$re\z! }
  8         858  
115 13         501 @{ $self->files }),
116 13         39 @{ $self->matches }
  13         464  
117             ]);
118              
119 13         468 my $files = $self->zilla->files;
120              
121             $files = [ grep {
122 13         39 my $name = $_->name;
  455         1247  
123 455 100 100     4500 (not defined $dir or $name =~ $dir) and
      100        
      100        
      100        
124             (not defined $match or $name =~ $match) and
125             (not defined $skip or $name !~ $skip)
126             } @$files ];
127              
128 13 50       46 $self->log_debug("No files found") unless @$files;
129 13         61 $self->log_debug("Found " . $_->name) for @$files;
130              
131 13         326 $files;
132             }
133              
134             __PACKAGE__->meta->make_immutable;
135             1;
136              
137             #pod =head1 DESCRIPTION
138             #pod
139             #pod FileFinder::ByName is a L<FileFinder|Dist::Zilla::Role::FileFinder> that
140             #pod selects files by matching the criteria you specify against the pathname.
141             #pod
142             #pod There are three types of criteria you can use. C<dir> limits the
143             #pod search to a particular directory. C<match> is a regular expression
144             #pod that must match the pathname. C<skip> is a regular expression that
145             #pod must not match the pathname.
146             #pod
147             #pod Each key can be specified multiple times. Multiple occurrences of the
148             #pod same key are ORed together. Different keys are ANDed together. That
149             #pod means that to be selected, a file must be located in one of the
150             #pod C<dir>s, must match one of the C<match> regexs, and must not match any
151             #pod of the C<skip> regexs.
152             #pod
153             #pod Note that C<file> and C<match> are considered to be the I<same> key.
154             #pod They're just different ways to write a regex that the pathname must match.
155             #pod
156             #pod Omitting a particular key means that criterion will not apply to the
157             #pod search. Omitting all keys will select every file in your dist.
158             #pod
159             #pod Note: If you need to OR different types of criteria, then use more
160             #pod than one instance of FileFinder::ByName. A
161             #pod L<FileFinderUser|Dist::Zilla::Role::FileFinderUser> should allow you
162             #pod to specify more than one FileFinder to use.
163             #pod
164             #pod =for Pod::Coverage
165             #pod mvp_aliases
166             #pod mvp_multivalue_args
167             #pod find_files
168              
169             __END__
170              
171             =pod
172              
173             =encoding UTF-8
174              
175             =head1 NAME
176              
177             Dist::Zilla::Plugin::FileFinder::ByName - FileFinder matching on pathnames
178              
179             =head1 VERSION
180              
181             version 6.030
182              
183             =head1 SYNOPSIS
184              
185             In your F<dist.ini>:
186              
187             [FileFinder::ByName / MyFiles]
188             dir = bin ; look in the bin/ directory
189             dir = lib ; and the lib/ directory
190             file = *.pl ; for .pl files
191             match = \.pm$ ; and for .pm files
192             skip = ignore ; that don't have "ignore" in the path
193              
194             =head1 DESCRIPTION
195              
196             FileFinder::ByName is a L<FileFinder|Dist::Zilla::Role::FileFinder> that
197             selects files by matching the criteria you specify against the pathname.
198              
199             There are three types of criteria you can use. C<dir> limits the
200             search to a particular directory. C<match> is a regular expression
201             that must match the pathname. C<skip> is a regular expression that
202             must not match the pathname.
203              
204             Each key can be specified multiple times. Multiple occurrences of the
205             same key are ORed together. Different keys are ANDed together. That
206             means that to be selected, a file must be located in one of the
207             C<dir>s, must match one of the C<match> regexs, and must not match any
208             of the C<skip> regexs.
209              
210             Note that C<file> and C<match> are considered to be the I<same> key.
211             They're just different ways to write a regex that the pathname must match.
212              
213             Omitting a particular key means that criterion will not apply to the
214             search. Omitting all keys will select every file in your dist.
215              
216             Note: If you need to OR different types of criteria, then use more
217             than one instance of FileFinder::ByName. A
218             L<FileFinderUser|Dist::Zilla::Role::FileFinderUser> should allow you
219             to specify more than one FileFinder to use.
220              
221             =head1 PERL VERSION
222              
223             This module should work on any version of perl still receiving updates from
224             the Perl 5 Porters. This means it should work on any version of perl released
225             in the last two to three years. (That is, if the most recently released
226             version is v5.40, then this module should work on both v5.40 and v5.38.)
227              
228             Although it may work on older versions of perl, no guarantee is made that the
229             minimum required version will not be increased. The version may be increased
230             for any reason, and there is no promise that patches will be accepted to lower
231             the minimum required perl.
232              
233             =head1 ATTRIBUTES
234              
235             =head2 dir
236              
237             The file must be located in one of the specified directories (relative
238             to the root directory of the dist).
239              
240             =head2 file
241              
242             The filename must match one of the specified patterns (which are
243             converted to regexs using L<Text::Glob> and combined with any C<match>
244             rules).
245              
246             =head2 match
247              
248             The pathname must match one of these regular expressions.
249              
250             =head2 skip
251              
252             The pathname must I<not> match any of these regular expressions.
253              
254             =head1 CREDITS
255              
256             This plugin was originally contributed by Christopher J. Madsen.
257              
258             =for Pod::Coverage mvp_aliases
259             mvp_multivalue_args
260             find_files
261              
262             =head1 AUTHOR
263              
264             Ricardo SIGNES 😏 <cpan@semiotic.systems>
265              
266             =head1 COPYRIGHT AND LICENSE
267              
268             This software is copyright (c) 2023 by Ricardo SIGNES.
269              
270             This is free software; you can redistribute it and/or modify it under
271             the same terms as the Perl 5 programming language system itself.
272              
273             =cut