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.037;
2             # ABSTRACT: FileFinder matching on pathnames
3              
4 2     2   3198 use Moose;
  2         6  
  2         20  
5             with 'Dist::Zilla::Role::FileFinder';
6              
7 2     2   19092 use Dist::Zilla::Pragmas;
  2         7  
  2         21  
8              
9 2     2   21 use namespace::autoclean;
  2         5  
  2         21  
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   256 use Moose::Util::TypeConstraints;
  2         5  
  2         32  
29 2     2   5836 use MooseX::Types::Moose qw(ArrayRef RegexpRef Str);
  2         5  
  2         39  
30              
31 2     2   15847 use Text::Glob 0.08 qw(glob_to_regex_string);
  2         1138  
  2         2439  
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 1528 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 2743 sub mvp_multivalue_args { qw(dirs files matches skips) }
97              
98             sub _join_re {
99 39     39   96 my $list = shift;
100 39 100       121 return undef unless @$list;
101             # Special case to avoid stringify+compile
102 22 100       127 return $list->[0] if @$list == 1;
103             # Wrap each element to ensure that alternations are isolated
104 8         33 my $re = join('|', map { "(?:$_)" } @$list);
  16         98  
105 8         460 qr/$re/
106             }
107              
108             sub find_files {
109 13     13 0 48 my $self = shift;
110              
111 13         720 my $skip = _join_re($self->skips);
112 13         36 my $dir = _join_re([ map { qr!^\Q$_/! } @{ $self->dirs } ]);
  10         328  
  13         880  
113             my $match = _join_re([
114 8         45 (map { my $re = glob_to_regex_string($_); qr!(?:\A|/)$re\z! }
  8         1172  
115 13         629 @{ $self->files }),
116 13         42 @{ $self->matches }
  13         614  
117             ]);
118              
119 13         657 my $files = $self->zilla->files;
120              
121             $files = [ grep {
122 13         43 my $name = $_->name;
  455         1374  
123 455 100 100     5978 (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       54 $self->log_debug("No files found") unless @$files;
129 13         70 $self->log_debug("Found " . $_->name) for @$files;
130              
131 13         632 $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.037
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
225             released in the last two to three years. (That is, if the most recently
226             released version is v5.40, then this module should work on both v5.40 and
227             v5.38.)
228              
229             Although it may work on older versions of perl, no guarantee is made that the
230             minimum required version will not be increased. The version may be increased
231             for any reason, and there is no promise that patches will be accepted to
232             lower the minimum required perl.
233              
234             =head1 ATTRIBUTES
235              
236             =head2 dir
237              
238             The file must be located in one of the specified directories (relative
239             to the root directory of the dist).
240              
241             =head2 file
242              
243             The filename must match one of the specified patterns (which are
244             converted to regexs using L<Text::Glob> and combined with any C<match>
245             rules).
246              
247             =head2 match
248              
249             The pathname must match one of these regular expressions.
250              
251             =head2 skip
252              
253             The pathname must I<not> match any of these regular expressions.
254              
255             =head1 CREDITS
256              
257             This plugin was originally contributed by Christopher J. Madsen.
258              
259             =for Pod::Coverage mvp_aliases
260             mvp_multivalue_args
261             find_files
262              
263             =head1 AUTHOR
264              
265             Ricardo SIGNES 😏 <cpan@semiotic.systems>
266              
267             =head1 COPYRIGHT AND LICENSE
268              
269             This software is copyright (c) 2026 by Ricardo SIGNES.
270              
271             This is free software; you can redistribute it and/or modify it under
272             the same terms as the Perl 5 programming language system itself.
273              
274             =cut