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