File Coverage

blib/lib/Dist/Zilla/Plugin/OurPkgVersion.pm
Criterion Covered Total %
statement 83 86 96.5
branch 36 42 85.7
condition 8 12 66.6
subroutine 13 13 100.0
pod 3 3 100.0
total 143 156 91.6


line stmt bran cond sub pod time code
1             package Dist::Zilla::Plugin::OurPkgVersion;
2 9     9   37607566 use 5.014;
  9         40  
3 9     9   63 use strict;
  9         22  
  9         252  
4 9     9   56 use warnings;
  9         20  
  9         464  
5              
6             our $VERSION = '0.20'; # VERSION
7              
8 9     9   62 use Moose;
  9         24  
  9         78  
9             with (
10             'Dist::Zilla::Role::FileMunger',
11             'Dist::Zilla::Role::FileFinderUser' => {
12             default_finders => [
13             ':InstallModules',
14             ':PerlExecFiles',
15             ],
16             },
17             'Dist::Zilla::Role::PPI',
18             );
19              
20 9     9   63112 use Carp qw( confess );
  9         27  
  9         601  
21 9     9   5168 use PPI;
  9         913235  
  9         449  
22 9     9   93 use MooseX::Types::Perl qw( LaxVersionStr );
  9         24  
  9         161  
23 9     9   22944 use namespace::autoclean;
  9         27  
  9         103  
24              
25             has underscore_eval_version => (
26             is => 'ro',
27             isa => 'Bool',
28             default => 0,
29             );
30              
31             has semantic_version => (
32             is => 'ro',
33             isa => 'Bool',
34             default => 0,
35             );
36              
37             has skip_main_module => (
38             is => 'ro',
39             isa => 'Bool',
40             default => 0,
41             );
42              
43             has overwrite => (
44             is => 'ro',
45             isa => 'Bool',
46             default => 0,
47             );
48              
49             sub munge_files {
50 8     8 1 1014378 my $self = shift;
51              
52 8         30 $self->munge_file($_) for
53 25 100       40199 grep { $self->skip_main_module ? $_->name ne $self->zilla->main_module->name : 1 }
54 8         71 @{ $self->found_files };
55              
56 8         2184 return;
57             }
58              
59             sub BUILD {
60 9     9 1 24 my $self = shift;
61              
62 9 100 100     395 if ($self->underscore_eval_version && $self->semantic_version) {
63 1         20 confess 'You cannot setup both underscore_eval_version and semantic_version';
64             }
65              
66 8         255 return 1;
67             }
68              
69             sub munge_file {
70 24     24 1 3031 my ( $self, $file ) = @_;
71              
72 24 50       95 if ( $file->name =~ m/\.pod$/ixms ) {
73 0         0 $self->log_debug( 'Skipping: "' . $file->name . '" is pod only');
74 0         0 return;
75             }
76              
77 24         1877 my $version = $self->zilla->version;
78              
79 24 50       917 confess 'invalid characters in version'
80             unless LaxVersionStr->check( $version ); ## no critic (Modules::RequireExplicitInclusion)
81              
82 24         20474 my $doc = $self->ppi_document_for_file($file);
83              
84 24 50       125357 return unless defined $doc;
85              
86 24 100       1131 $doc->index_locations if $self->overwrite; # optimize calls to check line numbers
87 24         2835 my $comments = $doc->find('PPI::Token::Comment');
88              
89 24         21545 my $version_regex
90             = q{
91             ^
92             (\s*) # capture leading whitespace for whole-line comments
93             (
94             \#\#?\s*VERSION # capture # VERSION or ## VERSION
95             \b # and ensure it ends on a word boundary
96             [ # conditionally
97             [:print:] # all printable characters after VERSION
98             \s # any whitespace including newlines - GH #5
99             ]* # as many of the above as there are
100             )
101             $ # until the EOL}
102             ;
103              
104 24         60 my $munged_version = 0;
105 24 100       99 if ( ref($comments) eq 'ARRAY' ) {
106 22         47 foreach ( @{ $comments } ) {
  22         68  
107 38 100       3907 if ( /$version_regex/xms ) {
108 24         451 my ( $ws, $comment ) = ( $1, $2 );
109 24 100       827 $comment =~ s/(?=\bVERSION\b)/TRIAL /x if $self->zilla->is_trial;
110 24         8470 my $code
111             = "$ws"
112             . q{our $VERSION = '}
113             . $version
114             . qq{'; $comment}
115             ;
116              
117 24 100       891 if ( $self->semantic_version ) {
118 1 50       9 confess 'Invalid semantic version syntax declaration in INI file' unless ( $version =~ /^v\d+\.\d+\.\d+$/x );
119 1         5 $code = "use version;\n" . $code;
120             }
121              
122             # If the comment is not a whole-line comment, and if the user wants to overwrite
123             # existing "our $VERSION=...;", then find the other tokens from this line, looking
124             # for our $VERSION = $VALUE. If found, edit only the VALUE.
125 24 100 66     797 if ( $self->overwrite && !$_->line ) {
126 3         31 my $line_no = $_->line_number;
127 3     288   77 my $nodes = $doc->find( sub { $_[1]->line_number == $line_no } );
  288         6426  
128 3   33     100 my $version_value_token = $nodes && $self->_identify_version_value_token(@$nodes);
129 3 50       11 if ( $version_value_token ) {
130 3         46 $version_value_token->set_content(qq{'$version'});
131 3         15 $code = $ws . $comment;
132 3         8 $munged_version++;
133             }
134             }
135              
136 24 100 66     194 if ( $version =~ /_/ && $self->underscore_eval_version ) {
137 1         3 my $eval = "\$VERSION = eval \$VERSION;";
138 1 50       6 $code .= $_->line? "$eval\n" : "\n$eval";
139             }
140              
141 24         163 $_->set_content($code);
142 24         131 $munged_version++;
143             }
144             }
145             }
146              
147 24 100       224 if ( $munged_version ) {
148 20         117 $self->save_ppi_document_to_file( $doc, $file);
149 20         27734 $self->log_debug([ 'adding $VERSION assignment to %s', $file->name ]);
150             }
151             else {
152 4         24 $self->log( 'Skipping: "'
153             . $file->name
154             . '" has no "# VERSION" comment'
155             );
156             }
157 24         4577 return;
158             }
159              
160             sub _identify_version_value_token {
161 3     3   15 my ( $self, @tokens ) = @_;
162 3         6 my $val_tok;
163 3         10 my @want = ('our', '$VERSION', '=', undef, ';');
164 3         7 my $i = 0;
165 3         8 for ( @tokens ) {
166 39 100       320 next if $_->isa('PPI::Token::Whitespace');
167             # If the next thing we want is "undef", this is where we capture the value token.
168 27 100       77 if (!defined $want[$i]) {
    100          
    100          
169 3         7 $val_tok = $_;
170 3         6 ++$i;
171             }
172             # Else if the token matches the current step in the sequence, advance the sequence
173             # If sequence completely matched, return.
174             elsif ($want[$i] eq $_->content) {
175 13         46 ++$i;
176 13 100       45 return $val_tok if $i >= $#want;
177             }
178             # A mismatch restarts the search
179             elsif ($i) {
180 1         6 $i = 0;
181             }
182             }
183 0           return; # no match
184             }
185              
186             __PACKAGE__->meta->make_immutable;
187             1;
188             # ABSTRACT: No line insertion and does Package version with our
189              
190             __END__
191              
192             =pod
193              
194             =head1 NAME
195              
196             Dist::Zilla::Plugin::OurPkgVersion - No line insertion and does Package version with our
197              
198             =head1 VERSION
199              
200             version 0.20
201              
202             =head1 SYNOPSIS
203              
204             in dist.ini
205              
206             [OurPkgVersion]
207              
208             in your modules
209              
210             # VERSION
211              
212             =head1 DESCRIPTION
213              
214             This module was created as an alternative to
215             L<Dist::Zilla::Plugin::PkgVersion> and uses some code from that module. This
216             module is designed to use a the more readable format C<our $VERSION =
217             $version;> as well as not change then number of lines of code in your files,
218             which will keep your repository more in sync with your CPAN release. It also
219             allows you slightly more freedom in how you specify your version.
220              
221             =head2 EXAMPLES
222              
223             in dist.ini
224              
225             ...
226             version = 0.01;
227             [OurPkgVersion]
228              
229             in lib/My/Module.pm
230              
231             package My::Module;
232             # VERSION
233             ...
234              
235             output lib/My/Module.pm
236              
237             package My::Module;
238             our $VERSION = '0.01'; # VERSION
239             ...
240              
241             please note that whitespace before the comment is significant so
242              
243             package My::Module;
244             BEGIN {
245             # VERSION
246             }
247             ...
248              
249             becomes
250              
251             package My::Module;
252             BEGIN {
253             our $VERSION = '0.01'; # VERSION
254             }
255             ...
256              
257             while
258              
259             package My::Module;
260             BEGIN {
261             # VERSION
262             }
263             ...
264              
265             becomes
266              
267             package My::Module;
268             BEGIN {
269             our $VERSION = '0.01'; # VERSION
270             }
271             ...
272              
273             you can also add additional comments to your comment
274              
275             ...
276             # VERSION: generated by DZP::OurPkgVersion
277             ...
278              
279             becomes
280              
281             ...
282             our $VERSION = '0.1.0'; # VERSION: generated by DZP::OurPkgVersion
283             ...
284              
285             you can also use perltidy's default static side comments (##)
286              
287             ...
288             ## VERSION
289             ...
290              
291             becomes
292              
293             ...
294             our $VERSION = '0.1.0'; ## VERSION
295             ...
296              
297             Also note, the package line is not in any way significant, it will insert the
298             C<our $VERSION> line anywhere in the file before C<# VERSION> as many times as
299             you've written C<# VERSION> regardless of whether or not inserting it there is
300             a good idea. OurPkgVersion will not insert a version unless you have C<#
301             VERSION> so it is a bit more work.
302              
303             If you make a trial release, the comment will be altered to say so:
304              
305             # VERSION
306              
307             becomes
308              
309             our $VERSION = '0.01'; # TRIAL VERSION
310              
311             =encoding UTF-8
312              
313             =head1 METHODS
314              
315             =over
316              
317             =item BUILD
318              
319             Provides validations after object creation.
320              
321             =item munge_files
322              
323             Override the default provided by L<Dist::Zilla::Role::FileMunger> to limit
324             the number of files to search to only be modules and executables.
325              
326             =item munge_file
327              
328             tells which files to munge, see L<Dist::Zilla::Role::FileMunger>.
329              
330             =item finder
331              
332             Override the default L<FileFinder|Dist::Zilla::Role::FileFinder> for
333             finding files to check and update. The default value is C<:InstallModules>
334             and C<:PerlExecFiles> (when available; otherwise C<:ExecFiles>)
335             -- see also L<Dist::Zilla::Plugin::ExecDir>, to make sure the script
336             files are properly marked as executables for the installer.
337              
338             =back
339              
340             =head1 PROPERTIES
341              
342             =over
343              
344             =item underscore_eval_version
345              
346             For version numbers that have an underscore in them, add this line
347             immediately after the our version assignment:
348              
349             $VERSION = eval $VERSION;
350              
351             This is arguably the correct thing to do, but changes the line numbering
352             of the generated Perl module or source, and thus optional.
353              
354             =item semantic_version
355              
356             Setting this property to "true" (1) will set the version of the
357             module/distribution to properly use semantic versioning. It will also expect
358             that you setup C<version> with a v-string, without adding quotes. For example:
359              
360             version = v0.0.1
361              
362             Beware you can't setup both C<underscore_eval_version> and C<semantic_version>
363             since both are mutually exclusive: if you try, your code is going to C<die>.
364              
365             For more details, check
366             L<this blog|https://weblog.bulknews.net/how-to-correctly-use-semantic-version-vx-y-z-in-perl-modules-eb08568ab911>
367             for more details about using semantic version with Perl.
368              
369             =item skip_main_module
370              
371             Set to true to ignore the main module in the distribution. This prevents
372             a warning when using L<Dist::Zilla::Plugin::VersionFromMainModule> to
373             obtain the version number instead of the C<dist.ini> file.
374              
375             =item overwrite
376              
377             When enabled, this option causes any match of the C<< # VERSION >> comment
378             to first check for an existing C<< our $VERSION = ...; >> on the same line,
379             and if found, overwrite the value in the existing statement. (the comment
380             still gets modified for trial releases)
381              
382             Currently, the value must be a single Perl token such as a string or number.
383              
384             =back
385              
386             =head1 BUGS
387              
388             Please report any bugs or feature requests on the bugtracker website
389             L<https://github.com/plicease/dist-zilla-plugin-ourpkgversion/issues>
390              
391             When submitting a bug or request, please include a test-file or a
392             patch to an existing test-file that illustrates the bug or desired
393             feature.
394              
395             =head1 CONTRIBUTORS
396              
397             =for stopwords Alceu Rodrigues de Freitas Junior Ian Sealy Michael Conrad Jemmeson Stephan Loyd Alexandr Ciornii Alexei Znamensky Christian Walde Christopher J. Madsen David Golden Graham Ollis Graham✈️✈️
398              
399             =over 4
400              
401             =item *
402              
403             Alceu Rodrigues de Freitas Junior <alceu.junior@quintoandar.com.br>
404              
405             =item *
406              
407             Ian Sealy <git@iansealy.com>
408              
409             =item *
410              
411             Michael Conrad <mike@nrdvana.net>
412              
413             =item *
414              
415             Michael Jemmeson <mjemmeson@cpan.org>
416              
417             =item *
418              
419             Stephan Loyd <stephanloyd9@gmail.com>
420              
421             =item *
422              
423             Alceu Rodrigues de Freitas Junior <arfreitas@cpan.org>
424              
425             =item *
426              
427             Alexandr Ciornii <alexchorny@gmail.com>
428              
429             =item *
430              
431             Alexei Znamensky <russoz@cpan.org>
432              
433             =item *
434              
435             Christian Walde <walde.christian@googlemail.com>
436              
437             =item *
438              
439             Christopher J. Madsen <perl@cjmweb.net>
440              
441             =item *
442              
443             David Golden <dagolden@cpan.org>
444              
445             =item *
446              
447             Graham Ollis <perl@wdlabs.com>
448              
449             =item *
450              
451             Graham Ollis <plicease@cpan.org>
452              
453             =item *
454              
455             Graham✈️✈️ <plicease@cpan.org>
456              
457             =back
458              
459             =head1 AUTHORS
460              
461             =over 4
462              
463             =item *
464              
465             Caleb Cushing <xenoterracide@gmail.com>
466              
467             =item *
468              
469             Grahan Ollis <plicease@cpan.org>
470              
471             =back
472              
473             =head1 COPYRIGHT AND LICENSE
474              
475             This software is Copyright (c) 2019 by Caleb Cushing.
476              
477             This is free software, licensed under:
478              
479             The Artistic License 2.0 (GPL Compatible)
480              
481             =cut