File Coverage

blib/lib/Dist/Zilla/Plugin/AutoPrereqsFast.pm
Criterion Covered Total %
statement 47 50 94.0
branch 12 16 75.0
condition 3 3 100.0
subroutine 4 4 100.0
pod 0 2 0.0
total 66 75 88.0


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::AutoPrereqsFast;
2             $Dist::Zilla::Plugin::AutoPrereqsFast::VERSION = '0.003';
3 1     1   1883260 use Moose;
  1         1  
  1         6  
4             with(
5             'Dist::Zilla::Role::PrereqSource',
6             'Dist::Zilla::Role::FileFinderUser' => {
7             default_finders => [ ':InstallModules', ':ExecFiles' ],
8             },
9             'Dist::Zilla::Role::FileFinderUser' => {
10             method => 'found_test_files',
11             finder_arg_names => [ 'test_finder' ],
12             default_finders => [ ':TestFiles' ],
13             },
14             'Dist::Zilla::Role::FileFinderUser' => {
15             method => 'found_configure_files',
16             finder_arg_names => [ 'configure_finder' ],
17             default_finders => [],
18             },
19             );
20              
21             sub mvp_multivalue_args { qw(extra_scanners skips) }
22             sub mvp_aliases {
23             return {
24 2     2 0 278 extra_scanner => 'extra_scanners',
25             skip => 'skips'
26             }
27             }
28              
29             has extra_scanners => (
30             is => 'ro',
31             isa => 'ArrayRef[Str]',
32             default => sub { [ 'Moose' ] },
33             );
34              
35             has skips => (
36             is => 'ro',
37             isa => 'ArrayRef[Str]',
38             );
39              
40             sub register_prereqs {
41 2     2 0 187381 my $self = shift;
42              
43 2         568 require Perl::PrereqScanner::Lite;
44 2         7303 require CPAN::Meta::Requirements;
45 2         7 require List::Util; # uniq
46              
47 2         4 my @modules;
48              
49 2         8 my @sets = (
50             [ configure => 'found_configure_files' ], # must come before runtime
51             [ runtime => 'found_files' ],
52             [ test => 'found_test_files' ],
53             );
54              
55 2         5 my %runtime_final;
56              
57 2         6 for my $fileset (@sets) {
58 6         2388 my ($phase, $method) = @$fileset;
59              
60 6         241 my $scanner = Perl::PrereqScanner::Lite->new({ extra_scanners => $self->extra_scanners });
61 6         1442 my $req = CPAN::Meta::Requirements->new;
62              
63 6         61 my $files = $self->$method;
64              
65 6         6053 foreach my $file (@$files) {
66             # skip binary files
67 9 100       1062 next if $file->is_bytes;
68             # parse only perl files
69 8 100 100     319 next unless $file->name =~ /\.(?:pm|pl|t|psgi)$/i
70             || $file->content =~ /^#!(?:.*)perl(?:$|\s)/;
71             # RT#76305 skip extra tests produced by ExtraTests plugin
72 7 50       1486 next if $file->name =~ m{^t/(?:author|release)-[^/]*\.t$};
73              
74             # store module name, to trim it from require list later on
75 7         227 my @this_thing = $file->name;
76              
77             # t/lib/Foo.pm is treated as providing t::lib::Foo, lib::Foo, and Foo
78 7 50       204 if ($this_thing[0] =~ /^t/) {
79 0         0 push @this_thing, ($this_thing[0]) x 2;
80 0         0 $this_thing[1] =~ s{^t/}{};
81 0         0 $this_thing[2] =~ s{^t/lib/}{};
82             } else {
83 7         18 $this_thing[0] =~ s{^lib/}{};
84             }
85 7         24 s{\.pm$}{} for @this_thing;
86 7         19 s{/}{::}g for @this_thing;
87              
88 7         19 push @this_thing, $file->content =~ /package\s+([^\s;]+)/g;
89 7         2692 push @modules, List::Util::uniq(@this_thing);
90              
91             # parse a file, and merge with existing prereqs
92 7         21 $self->log_debug([ 'scanning %s for %s prereqs', $file->name, $phase ]);
93 7         584 my $file_req = $scanner->scan_string($file->content);
94              
95 7         4837 $req->add_requirements($file_req);
96             }
97              
98             # remove prereqs shipped with current dist
99 6         2314 $req->clear_requirement($_) for @modules;
100              
101 6         84 $req->clear_requirement($_) for qw(Config Errno); # never indexed
102              
103             # remove prereqs from skiplist
104 6 50       49 for my $skip (@{ $self->skips || [] }) {
  6         200  
105 6         33 my $re = qr/$skip/;
106              
107 6         16 foreach my $k ($req->required_modules) {
108 48 100       162 $req->clear_requirement($k) if $k =~ $re;
109             }
110             }
111              
112             # we're done, return what we've found
113 6         21 my %got = %{ $req->as_string_hash };
  6         14  
114 6 100       265 if ($phase eq 'runtime') {
115 2         13 %runtime_final = %got;
116             } else {
117 4         12 delete $got{$_} for
118 42 50       58 grep { exists $got{$_} and $runtime_final{$_} ge $got{$_} }
119             keys %runtime_final;
120             }
121              
122 6         154 $self->zilla->register_prereqs({ phase => $phase }, %got);
123             }
124             }
125              
126             __PACKAGE__->meta->make_immutable;
127 1     1   4678 no Moose;
  1         1  
  1         4  
128              
129             1;
130              
131              
132             # ABSTRACT: Automatically extract prereqs from your modules, but faster
133              
134             __END__
135              
136             =pod
137              
138             =encoding UTF-8
139              
140             =head1 NAME
141              
142             Dist::Zilla::Plugin::AutoPrereqsFast - Automatically extract prereqs from your modules, but faster
143              
144             =head1 VERSION
145              
146             version 0.003
147              
148             =head1 SYNOPSIS
149              
150             In your F<dist.ini>:
151              
152             [AutoPrereqsFast]
153             skip = ^Foo|Bar$
154             skip = ^Other::Dist
155              
156             =head1 DESCRIPTION
157              
158             This plugin will extract loosely your distribution prerequisites from
159             your files using L<Perl::PrereqScanner::Lite>.
160              
161             If some prereqs are not found, you can still add them manually with the
162             L<Prereqs|Dist::Zilla::Plugin::Prereqs> plugin.
163              
164             This plugin will skip the modules shipped within your dist.
165              
166             =head1 ATTRIBUTES
167              
168             =head2 finder
169              
170             This is the name of a L<FileFinder|Dist::Zilla::Role::FileFinder>
171             whose files will be scanned to determine runtime prerequisites. It
172             may be specified multiple times. The default value is
173             C<:InstallModules> and C<:ExecFiles>.
174              
175             =head2 test_finder
176              
177             Just like C<finder>, but for test-phase prerequisites. The default
178             value is C<:TestFiles>.
179              
180             =head2 configure_finder
181              
182             Just like C<finder>, but for configure-phase prerequisites. There is
183             no default value; AutoPrereqs will not determine configure-phase
184             prerequisites unless you set configure_finder.
185              
186             =head2 extra_scanners
187              
188             This is an arrayref of scanner names (as expected by Perl::PrereqScanner::Lite).
189             It will be passed as the C<extra_scanners> parameter to Perl::PrereqScanner::Lite.
190              
191             =head2 skips
192              
193             This is an arrayref of regular expressions, derived from all the 'skip' lines
194             in the configuration. Any module names matching any of these regexes will not
195             be registered as prerequisites.
196              
197             =head1 SEE ALSO
198              
199             L<Prereqs|Dist::Zilla::Plugin::Prereqs>, L<Perl::PrereqScanner::Lite>.
200              
201             =head1 CREDITS
202              
203             This plugin includes code by Jerome Quelin and Ricardo Signes
204              
205             =head1 AUTHOR
206              
207             Leon Timmermans <leont@cpan.org>
208              
209             =head1 COPYRIGHT AND LICENSE
210              
211             This software is copyright (c) 2015 by Leon Timmermans.
212              
213             This is free software; you can redistribute it and/or modify it under
214             the same terms as the Perl 5 programming language system itself.
215              
216             =cut