File Coverage

blib/lib/Dist/Zilla/Plugin/GitVersionCheckCJM.pm
Criterion Covered Total %
statement 54 60 90.0
branch 23 28 82.1
condition 1 3 33.3
subroutine 7 7 100.0
pod 0 2 0.0
total 85 100 85.0


line stmt bran cond sub pod time code
1             #---------------------------------------------------------------------
2             package Dist::Zilla::Plugin::GitVersionCheckCJM;
3             #
4             # Copyright 2009 Christopher J. Madsen
5             #
6             # Author: Christopher J. Madsen <perl@cjmweb.net>
7             # Created: 15 Nov 2009
8             #
9             # This program is free software; you can redistribute it and/or modify
10             # it under the same terms as Perl itself.
11             #
12             # This program is distributed in the hope that it will be useful,
13             # but WITHOUT ANY WARRANTY; without even the implied warranty of
14             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the
15             # GNU General Public License or the Artistic License for more details.
16             #
17             # ABSTRACT: Ensure version numbers are up-to-date
18             #---------------------------------------------------------------------
19              
20             our $VERSION = '4.27';
21             # This file is part of Dist-Zilla-Plugins-CJM 4.27 (August 29, 2015)
22              
23              
24 2     2   33558 use version 0.77 ();
  2         51  
  2         55  
25 2     2   11 use Moose;
  2         3  
  2         19  
26             with(
27             'Dist::Zilla::Role::FileMunger',
28             'Dist::Zilla::Role::ModuleInfo',
29             'Dist::Zilla::Role::FileFinderUser' => {
30             default_finders => [ qw(:InstallModules :IncModules :ExecFiles) ],
31             },
32             );
33              
34              
35             has single_version => (
36             is => 'ro',
37             isa => 'Bool',
38             default => 0,
39             );
40              
41             # RECOMMEND PREREQ: Git::Wrapper
42 2     2   15655 use Git::Wrapper (); # AutoPrereqs skips this
  2         3  
  2         1339  
43              
44             #---------------------------------------------------------------------
45             # Helper sub to run a git command and split on NULs:
46              
47             sub _git0
48             {
49 18     18   128 my ($git, $command, @args) = @_;
50              
51 18         50 my ($result) = do { local $/; $git->$command(@args) };
  18         106  
  18         225  
52              
53 18 100       193784 return unless defined $result;
54              
55 8         241 split(/\0/, $result);
56             } # end _git0
57              
58             #---------------------------------------------------------------------
59             # Main entry point:
60              
61             sub munge_files {
62 9     9 0 7364 my ($self) = @_;
63              
64             # Get the released versions:
65 9         453 my $git = Git::Wrapper->new( $self->zilla->root->stringify );
66              
67 9 50       1012 my %released = map { /^v?([\d._]+)$/ ? ($1, 1) : () } $git->tag;
  36         84182  
68              
69             # Get the list of modified but not-checked-in files:
70 9         114 my %modified = map { $self->log_debug("mod: $_"); $_ => 1 } (
  13         173  
  13         7102  
71             # Files that need to be committed:
72             _git0($git, qw( diff_index -z HEAD --name-only )),
73             # Files that are not tracked by git yet:
74             _git0($git, qw( ls_files -oz --exclude-standard )),
75             );
76              
77             # Get the list of modules:
78 9         407 my $files = $self->found_files;
79              
80             # Check each module:
81 9         29924 my $errors = 0;
82 9         24 foreach my $file (@{ $files }) {
  9         35  
83 25 100       188 ++$errors if $self->munge_file($file, $git, \%modified, \%released);
84             } # end foreach $file
85              
86 8 100       450 die "Stopped because of errors\n" if $errors;
87             } # end munge_files
88              
89             #---------------------------------------------------------------------
90             # Check the version of a module:
91              
92             sub munge_file
93             {
94 25     25 0 70 my ($self, $file, $git, $modifiedRef, $releasedRef) = @_;
95              
96             # Extract information from the module:
97 25         192 my $pmFile = $file->name;
98 25         2505 $self->log_debug("checking $pmFile");
99 25         12390 my $pm_info = $self->get_module_info($file);
100              
101 25 100       38301 my $version = $pm_info->version
102             or $self->log_fatal("ERROR: Can't find version in $pmFile");
103              
104 24         2206 my $distver = version->parse($self->zilla->version);
105              
106             # If module version matches dist version, it's current:
107             # (unless that dist has already been released)
108 24 100       1475 if ($version == $distver) {
109 11 100       168 return unless $releasedRef->{$version};
110             }
111              
112             # If the module version is greater than the dist version, that's a problem:
113 17 100       102 if ($version > $distver) {
114 1         14 $self->log("ERROR: $pmFile: $version exceeds dist version $distver");
115 1         400 return 1;
116             }
117              
118             # If all modules must have the same version,
119             # and the module version is less than the dist version, that's a problem:
120 16 50 33     849 if ($self->single_version and $version < $distver) {
121 0         0 $self->log("ERROR: $pmFile: $version needs to be updated");
122 0         0 return 1;
123             }
124              
125             # If the module hasn't been committed yet, it needs updating:
126             # (since it doesn't match the dist version)
127 16 100       87 if ($modifiedRef->{$pmFile}) {
128 3 100       37 if ($version == $distver) {
129 1         21 $self->log("ERROR: $pmFile: dist version $version needs to be updated");
130             } else {
131 2         33 $self->log("ERROR: $pmFile: $version needs to be updated");
132             }
133 3         1394 return 1;
134             }
135              
136             # If the module's version doesn't match the dist, and that version
137             # hasn't been released, that's a problem:
138 13 100       93 unless ($releasedRef->{$version}) {
139 1         24 $self->log("ERROR: $pmFile: $version does not seem to have been released, but is not current");
140 1         463 return 1;
141             }
142              
143             # See if we checked in the module without updating the version:
144 12         167 my ($lastChangedRev) = $git->rev_list(qw(-n1 HEAD --) => $pmFile);
145              
146 12         173940 my ($inRelease) = $git->name_rev(
147             qw(--refs), "refs/tags/$version",
148             $lastChangedRev
149             );
150              
151             # We're ok if the last change was part of the indicated release:
152 12 50       139590 return if $inRelease =~ m! tags/\Q$version\E!;
153              
154 0 0         if ($version == $distver) {
155 0           $self->log("ERROR: $pmFile: dist version $version needs to be updated");
156             } else {
157 0           $self->log("ERROR: $pmFile: $version needs to be updated");
158             }
159 0           return 1;
160             } # end munge_file
161              
162             #---------------------------------------------------------------------
163 2     2   13 no Moose;
  2         5  
  2         14  
164             __PACKAGE__->meta->make_immutable;
165             1;
166              
167             __END__
168              
169             =head1 NAME
170              
171             Dist::Zilla::Plugin::GitVersionCheckCJM - Ensure version numbers are up-to-date
172              
173             =head1 VERSION
174              
175             This document describes version 4.27 of
176             Dist::Zilla::Plugin::GitVersionCheckCJM, released August 29, 2015
177             as part of Dist-Zilla-Plugins-CJM version 4.27.
178              
179             =head1 SYNOPSIS
180              
181             In your F<dist.ini>:
182              
183             [GitVersionCheckCJM]
184              
185             =head1 DESCRIPTION
186              
187             This plugin makes sure that module version numbers are updated as
188             necessary. In a distribution with multiple module, I like to update a
189             module's version only when a change is made to that module. In other
190             words, a module's version is the version of the last distribution
191             release in which it was modified.
192              
193             This plugin checks each module in the distribution, and makes sure
194             that it matches one of two conditions:
195              
196             =over
197              
198             =item 1.
199              
200             There is a tag matching the version, and the last commit on that
201             module is included in that tag.
202              
203             =item 2.
204              
205             The version matches the distribution's version, and that version has
206             not been tagged yet (i.e., the distribution has not been released).
207              
208             =back
209              
210             If neither condition holds, it prints an error message. After
211             checking all modules, it aborts the build if any module had an error.
212              
213              
214             =for Pod::Coverage
215             munge_file
216             munge_files
217              
218             =head1 ATTRIBUTES
219              
220             =head2 finder
221              
222             This FileFinder provides the list of modules that will be checked.
223             The default is C<:InstallModules>. The C<finder> attribute may be
224             listed any number of times.
225              
226              
227             =head2 single_version
228              
229             If set to a true value, all modules in the distribution must have
230             the distribution's version. The default is false, which allows
231             unchanged modules to retain the version of the distribution in which
232             they were last changed.
233              
234             =head1 DEPENDENCIES
235              
236             GitVersionCheckCJM requires L<Dist::Zilla> (4.300009 or later).
237             It also requires L<Git::Wrapper>, although it
238             is only listed as a recommended dependency for the distribution (to
239             allow people who don't use Git to use the other plugins.)
240              
241             =head1 INCOMPATIBILITIES
242              
243             None reported.
244              
245             =head1 BUGS AND LIMITATIONS
246              
247             No bugs have been reported.
248              
249             =head1 AUTHOR
250              
251             Christopher J. Madsen S<C<< <perl AT cjmweb.net> >>>
252              
253             Please report any bugs or feature requests
254             to S<C<< <bug-Dist-Zilla-Plugins-CJM AT rt.cpan.org> >>>
255             or through the web interface at
256             L<< http://rt.cpan.org/Public/Bug/Report.html?Queue=Dist-Zilla-Plugins-CJM >>.
257              
258             You can follow or contribute to Dist-Zilla-Plugins-CJM's development at
259             L<< https://github.com/madsen/dist-zilla-plugins-cjm >>.
260              
261             =head1 COPYRIGHT AND LICENSE
262              
263             This software is copyright (c) 2015 by Christopher J. Madsen.
264              
265             This is free software; you can redistribute it and/or modify it under
266             the same terms as the Perl 5 programming language system itself.
267              
268             =head1 DISCLAIMER OF WARRANTY
269              
270             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
271             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
272             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
273             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
274             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
275             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
276             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
277             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
278             NECESSARY SERVICING, REPAIR, OR CORRECTION.
279              
280             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
281             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
282             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
283             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
284             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
285             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
286             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
287             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
288             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
289             SUCH DAMAGES.
290              
291             =cut