File Coverage

lib/Dist/Zilla/Plugin/Prereqs/Soften.pm
Criterion Covered Total %
statement 86 88 97.7
branch 8 10 80.0
condition n/a
subroutine 17 17 100.0
pod 0 3 0.0
total 111 118 94.0


line stmt bran cond sub pod time code
1 7     7   4959559 use 5.006;
  7         27  
2 7     7   37 use strict;
  7         18  
  7         177  
3 7     7   35 use warnings;
  7         21  
  7         570  
4              
5             package Dist::Zilla::Plugin::Prereqs::Soften;
6              
7             our $VERSION = '0.006001';
8              
9             # ABSTRACT: Downgrade listed dependencies to recommendations if present.
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 7     7   1086 use Moose qw( with has around );
  7         465154  
  7         63  
14 7     7   39208 use MooseX::Types::Moose qw( ArrayRef HashRef Str Bool );
  7         62051  
  7         129  
15 7     7   43528 use Dist::Zilla::Util::ConfigDumper qw( config_dumper );
  7         8350  
  7         40  
16             with 'Dist::Zilla::Role::PrereqSource';
17              
18              
19              
20              
21              
22              
23              
24             has 'modules' => (
25             is => ro =>,
26             isa => ArrayRef [Str],
27             lazy => 1,
28             default => sub { [] },
29             );
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42              
43              
44              
45              
46              
47              
48              
49 7     7   1002 use Moose::Util::TypeConstraints qw(enum);
  7         14  
  7         81  
50              
51             has 'to_relationship' => (
52             is => ro =>,
53             isa => enum( [qw(none requires recommends suggests conflicts)] ),
54             lazy => 1,
55             default => sub { 'recommends' },
56             );
57              
58 7     7   2863 no Moose::Util::TypeConstraints;
  7         14  
  7         39  
59              
60              
61              
62              
63              
64              
65              
66              
67              
68              
69              
70              
71              
72              
73              
74              
75              
76              
77              
78              
79              
80              
81              
82              
83              
84              
85              
86              
87              
88              
89              
90              
91             has 'copy_to' => (
92             is => 'ro',
93             isa => ArrayRef [Str],
94             lazy => 1,
95             default => sub { [] },
96             );
97              
98             has '_copy_to_extras' => (
99             is => 'ro',
100             isa => ArrayRef [HashRef],
101             lazy => 1,
102             builder => '_build__copy_to_extras',
103             );
104              
105              
106              
107              
108              
109              
110              
111              
112              
113              
114              
115              
116              
117              
118              
119              
120              
121              
122              
123              
124             has 'modules_from_features' => (
125             is => ro =>,
126             isa => Bool,
127             lazy => 1,
128             default => sub { return },
129             );
130              
131             has '_modules_hash' => (
132             is => ro =>,
133             isa => HashRef,
134             lazy => 1,
135             builder => _build__modules_hash =>,
136             );
137 6     6 0 1309 sub mvp_multivalue_args { return qw(modules copy_to) }
138 6     6 0 1033 sub mvp_aliases { return { 'module' => 'modules' } }
139              
140             sub _build__copy_to_extras {
141 6     6   15 my $self = shift;
142 6         17 my $to = [];
143 6         15 for my $copy ( @{ $self->copy_to } ) {
  6         263  
144 3 100       28 if ( my ( $copy_phase, $copy_rel ) = $copy =~ /\A([^.]+)[.](.+)\z/msx ) {
145 2         3 push @{$to}, { phase => $copy_phase, relation => $copy_rel };
  2         9  
146 2         6 next;
147             }
148 1         7 return $self->log_fatal(['copy_to contained value not in form: phase.relation, got %s', $copy ]);
149             }
150 5         204 return $to;
151             }
152              
153             sub _get_feature_modules {
154 1     1   3 my ($self) = @_;
155 1         2 my $hash = {};
156 1         32 my $meta = $self->zilla->distmeta;
157 1 50       51431 if ( not exists $meta->{optional_features} ) {
158 0         0 $self->log('No optional_features detected');
159 0         0 return $hash;
160             }
161 1         3 for my $feature_name ( keys %{ $meta->{optional_features} } ) {
  1         4  
162 1         4 my $feature = $meta->{optional_features}->{$feature_name};
163 1         4 for my $rel_name ( keys %{ $feature->{prereqs} } ) {
  1         4  
164 1         2 my $rel = $feature->{prereqs}->{$rel_name};
165 1         3 for my $phase_name ( keys %{$rel} ) {
  1         3  
166 1         3 my $phase = $rel->{$phase_name};
167 1         3 for my $module ( keys %{$phase} ) {
  1         4  
168 1         4 $hash->{$module} = 1;
169             }
170             }
171             }
172             }
173 1         60 return keys %{$hash};
  1         6  
174             }
175              
176             sub _build__modules_hash {
177 5     5   12 my ($self) = @_;
178 5         12 my $hash = {};
179 5         8 $hash->{$_} = 1 for @{ $self->modules };
  5         220  
180 5 100       218 return $hash unless $self->modules_from_features;
181 1         5 $hash->{$_} = 1 for $self->_get_feature_modules;
182 1         45 return $hash;
183             }
184              
185             sub _user_wants_softening_on {
186 5     5   14 my ( $self, $module ) = @_;
187 5         250 return exists $self->_modules_hash->{$module};
188             }
189              
190             around dump_config => config_dumper( __PACKAGE__, qw( modules to_relationship copy_to modules_from_features ) );
191              
192             sub _soften_prereqs {
193 15     15   28 my ( $self, $conf ) = @_;
194 15         483 my $prereqs = $self->zilla->prereqs;
195              
196 15         487 my $source_reqs = $prereqs->requirements_for( $conf->{from_phase}, $conf->{from_relation} );
197              
198 15         1073 my @target_reqs;
199              
200 15         22 for my $target ( @{ $conf->{to} } ) {
  15         35  
201 21 100       272 next if 'none' eq $target->{relation};
202 18         54 push @target_reqs, $prereqs->requirements_for( $target->{phase}, $target->{relation} );
203             }
204              
205 15         1204 for my $module ( $source_reqs->required_modules ) {
206 5 50       57 next unless $self->_user_wants_softening_on($module);
207 5         31 my $reqstring = $source_reqs->requirements_for_module($module);
208 5         190 $source_reqs->clear_requirement($module);
209 5         102 for my $target (@target_reqs) {
210 6         153 $target->add_string_requirement( $module, $reqstring );
211             }
212             }
213 15         607 return $self;
214             }
215              
216             sub register_prereqs {
217 6     6 0 1272591 my ($self) = @_;
218              
219 6         24 for my $phase (qw( build test runtime )) {
220 16         32 for my $relation (qw( requires )) {
221             $self->_soften_prereqs(
222             {
223             from_phase => $phase,
224             from_relation => $relation,
225 16         717 to => [ { phase => $phase, relation => $self->to_relationship }, @{ $self->_copy_to_extras }, ],
  16         667  
226             },
227             );
228             }
229             }
230 5         22 return;
231             }
232              
233             __PACKAGE__->meta->make_immutable;
234 7     7   6566 no Moose;
  7         16  
  7         43  
235              
236             1;
237              
238             __END__
239              
240             =pod
241              
242             =encoding UTF-8
243              
244             =head1 NAME
245              
246             Dist::Zilla::Plugin::Prereqs::Soften - Downgrade listed dependencies to recommendations if present.
247              
248             =head1 VERSION
249              
250             version 0.006001
251              
252             =head1 SYNOPSIS
253              
254             [Prereqs::Soften]
255             module = Foo
256             module = Bar
257              
258             =head1 DESCRIPTION
259              
260             This module iterates C<build>, C<require> and C<test> dependency lists and migrates dependencies found in C<.requires> and
261             demotes them to C<.recommends>
262              
263             Optionally, it can L<< duplicate softened dependencies to other locations|/copy_to >>
264              
265             =head1 ATTRIBUTES
266              
267             =head2 C<modules>
268              
269             A C<multi-value> argument that specifies a module name to soften in C<prereqs>.
270              
271             =head2 C<to_relationship>
272              
273             The output relationship kind.
274              
275             B<Default:>
276              
277             'recommends'
278              
279             B<Valid Values:>
280              
281             'recommends', 'suggests', 'none', 'requires', 'conflicts'
282              
283             Though the last two are reserved for people with C<< $num_feet > 2 >> or with shotguns that only fire blanks.
284              
285             C<none> is available since C<0.006000> to allow removal of dependencies in conjunction with copying them.
286              
287             =head2 C<copy_to>
288              
289             Additional places to copy the dependency to:
290              
291             B<Default:>
292              
293             []
294              
295             B<Example:>
296              
297             [Prereqs::Soften]
298             copy_to = develop.requires
299             to_relationship = recommends
300             module = Foo
301              
302             This in effect means:
303              
304             remove from: runtime.requires
305             → add to: develop.requires
306             → add to: runtime.recommends
307              
308             remove from: test.requires
309             → add to: develop.requires
310             → add to: test.recommends
311              
312             remove from: build.requires
313             → add to: develop.requires
314             → add to: build.recommends
315              
316             =head2 C<modules_from_features>
317              
318             This is for use in conjunction with L<< C<[OptionalFeature]>|Dist::Zilla::Plugin::OptionalFeature >>, or anything that injects
319             compatible structures into C<distmeta>.
320              
321             Recommended usage as follows:
322              
323             [OptionalFeature / Etc]
324             ...
325              
326             [Prereqs::Soften]
327             modules_from_features = 1
328              
329             In this example, C<copy_to> and C<modules> are both redundant, as C<modules> are propagated from all features,
330             and C<copy_to> is not necessary because L<< C<[OptionalFeature]>|Dist::Zilla::Plugin::OptionalFeature >> automatically adds
331             dependencies to C<develop.requires>
332              
333             =for Pod::Coverage mvp_aliases
334             mvp_multivalue_args
335             register_prereqs
336              
337             =head1 AUTHOR
338              
339             Kent Fredric <kentnl@cpan.org>
340              
341             =head1 COPYRIGHT AND LICENSE
342              
343             This software is copyright (c) 2015 by Kent Fredric <kentfredric@gmail.com>.
344              
345             This is free software; you can redistribute it and/or modify it under
346             the same terms as the Perl 5 programming language system itself.
347              
348             =cut