File Coverage

blib/lib/Dist/Zilla/Plugin/Prereqs/SyncVersions.pm
Criterion Covered Total %
statement 73 76 96.0
branch 8 12 66.6
condition 1 2 50.0
subroutine 16 16 100.0
pod 2 2 100.0
total 100 108 92.5


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