File Coverage

blib/lib/Versioning/Scheme/Dotted.pm
Criterion Covered Total %
statement 60 60 100.0
branch 31 32 96.8
condition 22 27 81.4
subroutine 10 10 100.0
pod 5 5 100.0
total 128 134 95.5


line stmt bran cond sub pod time code
1             package Versioning::Scheme::Dotted;
2              
3             our $DATE = '2020-10-01'; # DATE
4             our $VERSION = '0.011'; # VERSION
5              
6 1     1   74842 use 5.010001;
  1         16  
7 1     1   5 use strict;
  1         2  
  1         37  
8 1     1   6 use warnings;
  1         2  
  1         39  
9              
10 1     1   595 use Role::Tiny;
  1         4728  
  1         5  
11 1     1   619 use Role::Tiny::With;
  1         267  
  1         814  
12             with 'Role::Versioning::Scheme';
13              
14             our $re = qr/\A[0-9]+(?:\.[0-9]+)*\z/;
15              
16             sub is_valid_version {
17 39     39 1 1253 my ($self, $v) = @_;
18 39 100       424 $v =~ $re ? 1:0;
19             }
20              
21             sub parse_version {
22 2     2 1 2406 my ($self, $v) = @_;
23 2 100       24 $v =~ $re or return undef;
24 1         12 {parts => [split /\./, $v]};
25             }
26              
27             sub normalize_version {
28 7     7 1 3093 my ($self, $v, $opts) = @_;
29 7   100     29 $opts //= {};
30              
31 7 100       16 die "Invalid version '$v'" unless $self->is_valid_version($v);
32              
33 6         24 my @parts = split /\./, $v;
34 6 100       17 if (defined $opts->{parts}) {
35 4 100       23 die "parts must at least be 1" unless $opts->{parts} >= 1;
36 3 100       11 if ($opts->{parts} < @parts) {
37 1         3 splice @parts, $opts->{parts};
38             } else {
39 2   50     12 $parts[$opts->{parts}-1] //= 0;
40             }
41             }
42 5   100     12 join(".", map { $_ // "0" } @parts);
  15         67  
43             }
44              
45             sub cmp_version {
46 7     7 1 2980 my ($self, $v1, $v2) = @_;
47              
48 7 100       17 die "Invalid version '$v1'" unless $self->is_valid_version($v1);
49 6 100       15 die "Invalid version '$v2'" unless $self->is_valid_version($v2);
50              
51 5         19 my @parts1 = split /\./, $v1;
52 5         12 my @parts2 = split /\./, $v2;
53 5 50       15 my $n = @parts1 < @parts2 ? @parts2 : @parts1;
54 5         17 for my $i (0..$n-1) {
55 12   50     41 my $cmp = ($parts1[$i] // 0) <=> ($parts2[$i] // 0);
      100        
56 12 100       33 return $cmp if $cmp;
57             }
58 3         15 0;
59             }
60              
61             sub bump_version {
62 12     12 1 2970 my ($self, $v, $opts) = @_;
63 12   100     37 $opts //= {};
64 12   100     40 $opts->{num} //= 1;
65 12   100     41 $opts->{part} //= -1;
66 12   100     43 $opts->{reset_smaller} //= 1;
67              
68 12 100       32 die "Invalid version '$v'" unless $self->is_valid_version($v);
69 11 100       43 die "Invalid 'num', must be non-zero" unless $opts->{num} != 0;
70 10         36 my @parts = split /\./, $v;
71             die "Invalid 'part', must not be smaller than -".@parts
72 10 100       38 if $opts->{part} < -@parts;
73              
74 9         17 my $idx = $opts->{part};
75 9   50     20 $parts[$idx] //= 0;
76             die "Cannot decrease version, would result in a negative part"
77 9 100       40 if $parts[$idx] + $opts->{num} < 0;
78             $parts[$idx] = sprintf("%0".length($parts[$idx])."d",
79 8         41 $parts[$idx]+$opts->{num});
80 8 100 100     35 if ($opts->{reset_smaller} && $opts->{num} > 0) {
81 4 100       13 $idx = @parts + $idx if $idx < 0;
82 4         13 for my $i ($idx+1 .. $#parts) {
83 3   50     9 $parts[$i] //= 0;
84 3         11 $parts[$i] = sprintf("%0".length($parts[$i])."d", 0);
85             }
86             }
87 8   50     17 join(".", map {$_//0} @parts);
  24         124  
88             }
89              
90             1;
91             # ABSTRACT: Version as dotted numbers
92              
93             __END__