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 = '2019-04-14'; # DATE
4             our $VERSION = '0.009'; # VERSION
5              
6 1     1   60627 use 5.010001;
  1         11  
7 1     1   5 use strict;
  1         1  
  1         30  
8 1     1   5 use warnings;
  1         2  
  1         31  
9              
10 1     1   464 use Role::Tiny;
  1         3534  
  1         6  
11 1     1   577 use Role::Tiny::With;
  1         230  
  1         722  
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 1176 my ($self, $v) = @_;
18 39 100       360 $v =~ $re ? 1:0;
19             }
20              
21             sub parse_version {
22 2     2 1 2266 my ($self, $v) = @_;
23 2 100       45 $v =~ $re or return undef;
24 1         16 {parts => [split /\./, $v]};
25             }
26              
27             sub normalize_version {
28 7     7 1 3233 my ($self, $v, $opts) = @_;
29 7   100     26 $opts //= {};
30              
31 7 100       17 die "Invalid version '$v'" unless $self->is_valid_version($v);
32              
33 6         20 my @parts = split /\./, $v;
34 6 100       17 if (defined $opts->{parts}) {
35 4 100       18 die "parts must at least be 1" unless $opts->{parts} >= 1;
36 3 100       9 if ($opts->{parts} < @parts) {
37 1         3 splice @parts, $opts->{parts};
38             } else {
39 2   50     11 $parts[$opts->{parts}-1] //= 0;
40             }
41             }
42 5   100     9 join(".", map { $_ // "0" } @parts);
  15         113  
43             }
44              
45             sub cmp_version {
46 7     7 1 2528 my ($self, $v1, $v2) = @_;
47              
48 7 100       14 die "Invalid version '$v1'" unless $self->is_valid_version($v1);
49 6 100       14 die "Invalid version '$v2'" unless $self->is_valid_version($v2);
50              
51 5         17 my @parts1 = split /\./, $v1;
52 5         10 my @parts2 = split /\./, $v2;
53 5 50       12 my $n = @parts1 < @parts2 ? @parts2 : @parts1;
54 5         16 for my $i (0..$n-1) {
55 12   50     34 my $cmp = ($parts1[$i] // 0) <=> ($parts2[$i] // 0);
      100        
56 12 100       29 return $cmp if $cmp;
57             }
58 3         15 0;
59             }
60              
61             sub bump_version {
62 12     12 1 2657 my ($self, $v, $opts) = @_;
63 12   100     33 $opts //= {};
64 12   100     37 $opts->{num} //= 1;
65 12   100     37 $opts->{part} //= -1;
66 12   100     36 $opts->{reset_smaller} //= 1;
67              
68 12 100       23 die "Invalid version '$v'" unless $self->is_valid_version($v);
69 11 100       34 die "Invalid 'num', must be non-zero" unless $opts->{num} != 0;
70 10         26 my @parts = split /\./, $v;
71             die "Invalid 'part', must not be smaller than -".@parts
72 10 100       34 if $opts->{part} < -@parts;
73              
74 9         14 my $idx = $opts->{part};
75 9   50     18 $parts[$idx] //= 0;
76             die "Cannot decrease version, would result in a negative part"
77 9 100       41 if $parts[$idx] + $opts->{num} < 0;
78             $parts[$idx] = sprintf("%0".length($parts[$idx])."d",
79 8         33 $parts[$idx]+$opts->{num});
80 8 100 100     32 if ($opts->{reset_smaller} && $opts->{num} > 0) {
81 4 100       9 $idx = @parts + $idx if $idx < 0;
82 4         12 for my $i ($idx+1 .. $#parts) {
83 3   50     9 $parts[$i] //= 0;
84 3         10 $parts[$i] = sprintf("%0".length($parts[$i])."d", 0);
85             }
86             }
87 8   50     47 join(".", map {$_//0} @parts);
  24         86  
88             }
89              
90             1;
91             # ABSTRACT: Version as dotted numbers
92              
93             __END__