File Coverage

lib/Dist/Zilla/Plugin/Prereqs/SyncVersions.pm
Criterion Covered Total %
statement 77 80 96.2
branch 8 12 66.6
condition 1 2 50.0
subroutine 17 17 100.0
pod 2 2 100.0
total 105 113 92.9


line stmt bran cond sub pod time code
1 2     2   780119 use 5.006; # our
  2         5  
  2         69  
2 2     2   8 use strict;
  2         4  
  2         57  
3 2     2   8 use warnings;
  2         9  
  2         141  
4              
5             package Dist::Zilla::Plugin::Prereqs::SyncVersions;
6              
7             # ABSTRACT: (DEPRECATED) Homogenize prerequisites so dependency versions are consistent
8              
9             our $VERSION = '0.003001';
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 2     2   480 use Moose qw( has with around );
  2         360707  
  2         17  
14 2     2   10035 use MooseX::Types::Moose qw( HashRef ArrayRef Str );
  2         43463  
  2         23  
15 2     2   9601 use Dist::Zilla::Util::ConfigDumper qw( config_dumper );
  2         2786  
  2         17  
16             with 'Dist::Zilla::Role::PrereqSource';
17              
18              
19              
20              
21              
22              
23              
24              
25              
26              
27              
28              
29              
30              
31              
32              
33              
34              
35              
36              
37              
38              
39              
40              
41              
42              
43              
44              
45              
46              
47              
48              
49              
50              
51              
52             has applyto_phase => (
53             is => ro =>,
54             isa => ArrayRef [Str] =>,
55             lazy => 1,
56             default => sub { [qw(build test runtime configure)] },
57             );
58              
59              
60              
61              
62              
63              
64              
65              
66              
67              
68              
69              
70              
71              
72              
73              
74              
75              
76              
77             has applyto_relation => (
78             is => ro =>,
79             isa => ArrayRef [Str],
80             lazy => 1,
81             default => sub { [qw(requires)] },
82             );
83              
84              
85              
86              
87              
88              
89              
90              
91              
92              
93              
94              
95              
96              
97              
98             has applyto => (
99             is => ro =>,
100             isa => ArrayRef [Str] =>,
101             lazy => 1,
102             builder => _build_applyto =>,
103             );
104              
105             has _applyto_list => (
106             is => ro =>,
107             isa => ArrayRef [ ArrayRef [Str] ],
108             lazy => 1,
109             builder => _build__applyto_list =>,
110             );
111              
112             has _max_versions => (
113             is => ro =>,
114             isa => HashRef,
115             lazy => 1,
116             default => sub { {} },
117             );
118              
119             sub _versionify {
120 2     2   4 my ( undef, $version ) = @_;
121 2 50       6 return $version if ref $version;
122 2         12 require version;
123 2         50 return version->parse($version);
124             }
125              
126             sub _set_module_version {
127 2     2   3 my ( $self, $module, $version ) = @_;
128 2 100       81 if ( not exists $self->_max_versions->{$module} ) {
129 1         4 $self->_max_versions->{$module} = $self->_versionify($version);
130 1         5 return;
131             }
132 1         3 my $comparator = $self->_versionify($version);
133 1         37 my $current = $self->_max_versions->{$module};
134 1 50       6 if ( $current < $comparator ) {
135 0         0 $self->log_debug( [ 'Version upgrade on : %s', $module ] );
136 0         0 $self->_max_versions->{$module} = $comparator;
137             }
138 1         4 return;
139             }
140              
141             sub _get_module_version {
142 2     2   3 my ( $self, $module ) = @_;
143 2         79 return $self->_max_versions->{$module};
144             }
145              
146             sub _build_applyto {
147 1     1   6 my $self = shift;
148 1         4 my @out;
149 1         2 for my $phase ( @{ $self->applyto_phase } ) {
  1         39  
150 4         2 for my $relation ( @{ $self->applyto_relation } ) {
  4         151  
151 4         13 push @out, $phase . q[.] . $relation;
152             }
153             }
154 1         35 return \@out;
155             }
156              
157             sub _build__applyto_list {
158 1     1   2 my $self = shift;
159 1         2 my @out;
160 1         3 for my $type ( @{ $self->applyto } ) {
  1         38  
161 4 50       16 if ( $type =~ /^ ([^.]+) [.] ([^.]+) $/msx ) {
162 4         8 push @out, [ "$1", "$2" ];
163 4         7 next;
164             }
165 0         0 return $self->log_fatal( [ q[<<%s>> does not match << <phase>.<relation> >>], $type ] );
166             }
167 1         38 return \@out;
168             }
169              
170              
171              
172              
173              
174              
175              
176              
177              
178              
179              
180 1     1 1 180 sub mvp_multivalue_args { return qw( applyto applyto_relation applyto_phase ) }
181              
182             around dump_config => config_dumper( __PACKAGE__, qw( applyto_phase applyto_relation applyto ) );
183              
184             __PACKAGE__->meta->make_immutable;
185 2     2   1216 no Moose;
  2         3  
  2         15  
186              
187             sub _foreach_phase_rel {
188 2     2   4 my ( $self, $prereqs, $callback ) = @_;
189 2         3 for my $applyto ( @{ $self->_applyto_list } ) {
  2         77  
190 8         398 my ( $phase, $rel ) = @{$applyto};
  8         10  
191 8 100       22 next if not exists $prereqs->{$phase};
192 4 50       10 next if not exists $prereqs->{$phase}->{$rel};
193 4         15 $callback->( $phase, $rel, $prereqs->{$phase}->{$rel}->as_string_hash );
194             }
195 2         3 return;
196             }
197              
198              
199              
200              
201              
202              
203              
204              
205             sub register_prereqs {
206 1     1 1 48870 my ($self) = @_;
207 1         37 my $zilla = $self->zilla;
208 1         27 my $prereqs = $zilla->prereqs;
209 1   50     30 my $guts = $prereqs->cpan_meta_prereqs->{prereqs} || {};
210              
211             $self->_foreach_phase_rel(
212             $guts => sub {
213 2     2   45 my ( undef, undef, $reqs ) = @_;
214 2         3 for my $module ( keys %{$reqs} ) {
  2         4  
215 2         7 $self->_set_module_version( $module, $reqs->{$module} );
216             }
217             },
218 1         14 );
219             $self->_foreach_phase_rel(
220             $guts => sub {
221 2     2   29 my ( $phase, $rel, $reqs ) = @_;
222 2         3 for my $module ( keys %{$reqs} ) {
  2         5  
223 2         6 my $v = $self->_get_module_version( $module, $reqs->{$module} );
224 2         12 $zilla->register_prereqs( { phase => $phase, type => $rel }, $module, $v );
225             }
226             },
227 1         7 );
228 1         6 return $prereqs;
229             }
230              
231             1;
232              
233             __END__
234              
235             =pod
236              
237             =encoding UTF-8
238              
239             =head1 NAME
240              
241             Dist::Zilla::Plugin::Prereqs::SyncVersions - (DEPRECATED) Homogenize prerequisites so dependency versions are consistent
242              
243             =head1 VERSION
244              
245             version 0.003001
246              
247             =head1 DEPRECATED
248              
249             This module is deprecated as equivalent behavior is now part of C<Dist::Zilla>.
250              
251             However, this module will keep maintained for anyone who wants this behavior without upgrading to C<DZil 5>
252              
253             =head1 SYNOPSIS
254              
255             ; <bunch of metaprereq providing modules>
256              
257             [Prereqs::SyncVersions]
258              
259             Note: This must come B<after> packages that add their own prerequisites in order to work as intended.
260              
261             =head1 DESCRIPTION
262              
263             This module exists to pose mostly as a workaround for potential bugs in downstream tool-chains.
264              
265             Namely, C<CPAN.pm> is confused when it sees:
266              
267             runtime.requires : Foo >= 5.0
268             test.requires : Foo >= 6.0
269              
270             It doesn't know what to do.
271              
272             This is an easy enough problem to solve if you're using C<[Prereqs]> directly,
273             and C<[AutoPrereqs]> already does the right thing, but it gets messier
274             when you're working with L<< plugins that inject their own prerequisites|https://github.com/dagolden/Path-Tiny/commit/c620171db96597456a182ea6088a24d8de5debf6 >>
275              
276             So this plugin will homogenize dependencies to be the same version in all phases
277             which infer the dependency, matching the largest one found, so the above becomes:
278              
279             runtime.requires : Foo >= 6.0
280             test.requires : Foo >= 6.0
281              
282             =head1 METHODS
283              
284             =head2 C<mvp_multivalue_args>
285              
286             The following attributes exist, and may be specified more than once:
287              
288             applyto
289             applyto_relation
290             applyto_phase
291              
292             =head2 C<register_prereqs>
293              
294             This method is called during C<Dist::Zilla> prerequisite generation,
295             and it injects supplementary prerequisites to make things match up.
296              
297             =head1 ATTRIBUTES
298              
299             =head2 C<applyto_phase>
300              
301             A multi-value attribute that specifies which phases to iterate and homogenize.
302              
303             By default, this is:
304              
305             applyto_phase = build
306             applyto_phase = test
307             applyto_phase = runtime
308             applyto_phase = configure
309              
310             However, you could extend it further to include C<develop> if you wanted to.
311              
312             applyto_phase = build
313             applyto_phase = test
314             applyto_phase = runtime
315             applyto_phase = configure
316             appyyto_phase = develop
317              
318             =head2 C<applyto_relation>
319              
320             A multi-value attribute that specifies which relations to iterate and homogenize.
321              
322             By default, this is:
323              
324             applyto_relation = requires
325              
326             However, you could extend it further to include C<suggests> and C<recommends> if you wanted to.
327             You could even add C<conflicts> ... but you really shouldn't.
328              
329             applyto_relation = requires
330             applyto_relation = suggests
331             applyto_relation = recommends
332             applyto_relation = conflicts ; Danger will robinson.
333              
334             =head2 C<applyto>
335              
336             A multi-value attribute that by default composites the values of
337              
338             C<applyto_relation> and C<applyto_phase>.
339              
340             This is if you want to be granular about how you specify phase/relations to process.
341              
342             applyto = runtime.requires
343             applyto = develop.requires
344             applyto = test.suggests
345              
346             =begin MetaPOD::JSON v1.1.0
347              
348             {
349             "namespace":"Dist::Zilla::Plugin::Prereqs::SyncVersions",
350             "interface":"class",
351             "inherits":"Moose::Object",
352             "does":"Dist::Zilla::Role::PrereqSource"
353             }
354              
355              
356             =end MetaPOD::JSON
357              
358             =head1 AUTHOR
359              
360             Kent Fredric <kentnl@cpan.org>
361              
362             =head1 COPYRIGHT AND LICENSE
363              
364             This software is copyright (c) 2015 by Kent Fredric <kentfredric@gmail.com>.
365              
366             This is free software; you can redistribute it and/or modify it under
367             the same terms as the Perl 5 programming language system itself.
368              
369             =cut