File Coverage

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