File Coverage

blib/lib/Version/Next.pm
Criterion Covered Total %
statement 59 59 100.0
branch 29 30 96.6
condition 5 6 83.3
subroutine 7 7 100.0
pod 1 1 100.0
total 101 103 98.0


line stmt bran cond sub pod time code
1 1     1   863 use strict;
  1         2  
  1         40  
2 1     1   5 use warnings;
  1         2  
  1         74  
3              
4             package Version::Next;
5             # ABSTRACT: increment module version numbers simply and correctly
6             our $VERSION = '0.004'; # VERSION
7              
8             # Dependencies
9 1     1   958 use version 0.81 ();
  1         2527  
  1         26  
10 1     1   6 use Carp ();
  1         2  
  1         29  
11              
12             # Exporting
13 1     1   10093 use Sub::Exporter 0 ( -setup => { exports => ['next_version'] } );
  1         21673  
  1         9  
14              
15             # lax versions are too lax
16             sub _cleanup {
17 106     106   140 my $version = shift;
18              
19             # treat 'undef' as 0
20 106 100       213 if ( $version eq 'undef' ) {
21 1         2 return "0";
22             }
23              
24             # fix leading dots
25 105 100       224 if ( $version =~ /^\./ ) {
26 4         19 my $num_dots =()= $version =~ /(\.)/g;
27 4 100       43 return $num_dots > 1 ? version->parse($version)->normal : "0$version";
28             }
29              
30             # fix trailing dots
31 101 100       225 if ( $version =~ /\.$/ ) {
32             # is_lax already prevents dotted-decimal with trailing dot
33 1         3 return "${version}0";
34             }
35              
36             # otherwise, it should be fine
37 100         182 return $version;
38             }
39              
40             sub next_version {
41 115     115 1 68675 my $version = shift;
42 115 50       307 return "0" unless defined $version;
43              
44 115 100       917 Carp::croak("Doesn't look like a version number: '$version'")
45             unless version::is_lax($version);
46              
47 106         1762 $version = _cleanup($version);
48              
49 106         125 my $new_ver;
50 106         408 my $num_dots =()= $version =~ /(\.)/g;
51 106         225 my $has_v = $version =~ /^v/;
52 106         245 my $is_alpha = $version =~ /\A[^_]+_\d+\z/;
53              
54 106 100 100     363 if ( $has_v || $num_dots > 1 ) { # vstring
55 63 100       216 $version =~ s{^v}{} if $has_v;
56 63         187 my @parts = split /\./, $version;
57 63 100       189 if ($is_alpha) { # vstring with alpha
58 28         89 push @parts, split /_/, pop @parts;
59             }
60 63         69 my @new_ver;
61 63         118 while (@parts) {
62 89         125 my $p = pop @parts;
63 89 100 66     282 if ( $p < 999 || !@parts ) {
64 63         90 unshift @new_ver, $p + 1;
65 63         79 last;
66             }
67             else {
68 26         69 unshift @new_ver, 0;
69             }
70             }
71 63 100       108 $new_ver = $has_v ? 'v' : '';
72 63         92 $new_ver .= join( ".", map { 0+ $_ } @parts, @new_ver );
  187         412  
73 63 100       163 if ($is_alpha) {
74 28         214 $new_ver =~ s{\A(.*)\.(\d+)}{$1_$2};
75             }
76             }
77             else { # decimal fraction
78 43         43 my $alpha_neg_offset;
79 43 100       78 if ($is_alpha) {
80 20         43 $alpha_neg_offset = index( $version, "_" ) + 1 - length($version);
81 20         55 $version =~ s{_}{};
82             }
83 43         141 my ($fraction) = $version =~ m{\.(\d+)$};
84 43 100       94 my $n = defined $fraction ? length($fraction) : 0;
85 43         458 $new_ver = sprintf( "%.${n}f", $version + ( 10**-$n ) );
86 43 100       99 if ($is_alpha) {
87 20         41 substr( $new_ver, $alpha_neg_offset, 0, "_" );
88             }
89             }
90 106         477 return $new_ver;
91              
92             }
93              
94             1;
95              
96             __END__