File Coverage

blib/lib/Versioning/Scheme/Semantic.pm
Criterion Covered Total %
statement 47 47 100.0
branch 33 34 97.0
condition 26 30 86.6
subroutine 10 10 100.0
pod 5 5 100.0
total 121 126 96.0


line stmt bran cond sub pod time code
1             package Versioning::Scheme::Semantic;
2              
3             our $DATE = '2019-04-14'; # DATE
4             our $VERSION = '0.009'; # VERSION
5              
6 1     1   58718 use 5.010001;
  1         11  
7 1     1   5 use strict;
  1         1  
  1         26  
8 1     1   5 use warnings;
  1         2  
  1         28  
9              
10 1     1   443 use Role::Tiny;
  1         3678  
  1         4  
11 1     1   468 use Role::Tiny::With;
  1         218  
  1         566  
12             with 'Role::Versioning::Scheme';
13              
14             our $re = qr/
15             \A
16             ([0-9]|[1-9][0-9]*)\. # 1=major
17             ([0-9]|[1-9][0-9]*)\. # 2=minor
18             ([0-9]|[1-9][0-9]*) # 3=major
19             (?:-([0-9]|[1-9][0-9]*|[A-Za-z-][0-9A-Za-z-]*))? # 4=pre-release identifier
20             (?:\+([0-9A-Za-z-]+))? # 5=metadata
21             \z
22             /x;
23              
24             sub is_valid_version {
25 17     17 1 1121 my ($self, $v) = @_;
26 17 100       164 $v =~ $re ? 1:0;
27             }
28              
29             sub parse_version {
30 1     1 1 2069 my ($self, $v) = @_;
31 1 50       11 $v =~ $re or return undef;
32             return {
33 1         23 major => $1,
34             minor => $2,
35             patch => $3,
36             prerelease => $4,
37             metadata => $5,
38             };
39             }
40              
41             sub normalize_version {
42 2     2 1 2417 my ($self, $v, $opts) = @_;
43 2   50     12 $opts //= {};
44              
45 2 100       6 die "Invalid version '$v'" unless $self->is_valid_version($v);
46 1         6 $v;
47             }
48              
49             sub cmp_version {
50 10     10 1 2638 my ($self, $v1, $v2) = @_;
51              
52 10 100       91 die "Invalid version '$v1'" unless my ($x1, $y1, $z1, $pre1) = $v1 =~ $re;
53 9 100       60 die "Invalid version '$v2'" unless my ($x2, $y2, $z2, $pre2) = $v2 =~ $re;
54              
55 8 100 100     93 ($x1 <=> $x2) || ($y1 <=> $y2) || ($z1 <=> $z2) ||
    100 100        
    100 100        
      66        
      100        
56             ((defined($pre1) ? 0:1) <=> (defined($pre2) ? 0:1)) ||
57             (($pre1//'') cmp ($pre2//''));
58             }
59              
60             sub bump_version {
61 14     14 1 2531 my ($self, $v, $opts) = @_;
62 14   100     38 $opts //= {};
63 14   100     37 $opts->{num} //= 1;
64 14   100     40 $opts->{part} //= -1;
65 14   100     42 $opts->{reset_smaller} //= 1;
66              
67 14 100       121 die "Invalid version '$v'" unless my ($x, $y, $z, $pre, $meta) = $v =~ $re;
68 13 100       44 die "Invalid 'num', must be non-zero" unless $opts->{num} != 0;
69 12         25 my @parts = ($x, $y, $z);
70             die "Invalid 'part', must not be larger than ".$#parts
71 12 100       33 if $opts->{part} > $#parts;
72             die "Invalid 'part', must not be smaller than -".@parts
73 11 100       30 if $opts->{part} < -@parts;
74              
75 10         14 my $idx = $opts->{part};
76 10   50     20 $parts[$idx] //= 0;
77             die "Cannot decrease version, would result in a negative number part"
78 10 100       31 if $parts[$idx] + $opts->{num} < 0;
79 9         11 $parts[$idx] = $parts[$idx]+$opts->{num};
80 9 100 100     30 if ($opts->{reset_smaller} && $opts->{num} > 0) {
81 5 100       12 $idx = @parts + $idx if $idx < 0;
82 5         13 for my $i ($idx+1 .. $#parts) {
83 3   50     8 $parts[$i] //= 0;
84 3         13 $parts[$i] = sprintf("%0".length($parts[$i])."d", 0);
85             }
86             }
87 9 100       59 join("",
    100          
88             $parts[0], ".", $parts[1], ".", $parts[2],
89             (defined $pre ? "-$pre" : ""),
90             (defined $meta ? "+$meta" : ""),
91             );
92             }
93              
94             1;
95             # ABSTRACT: Semantic versioning
96              
97             __END__