line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package SemVer;
|
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
53064
|
use 5.008001;
|
|
1
|
|
|
|
|
3
|
|
4
|
1
|
|
|
1
|
|
4
|
use strict;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
17
|
|
5
|
1
|
|
|
1
|
|
352
|
use version 0.82;
|
|
1
|
|
|
|
|
1461
|
|
|
1
|
|
|
|
|
5
|
|
6
|
1
|
|
|
1
|
|
55
|
use Scalar::Util ();
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
18
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use overload (
|
9
|
1
|
|
|
|
|
12
|
'""' => 'stringify',
|
10
|
|
|
|
|
|
|
'<=>' => 'vcmp',
|
11
|
|
|
|
|
|
|
'cmp' => 'vcmp',
|
12
|
1
|
|
|
1
|
|
869
|
);
|
|
1
|
|
|
|
|
700
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our @ISA = qw(version);
|
15
|
|
|
|
|
|
|
our $VERSION = '0.7.0'; # For Module::Build
|
16
|
|
|
|
|
|
|
|
17
|
9
|
|
|
9
|
|
55
|
sub _die { require Carp; Carp::croak(@_) }
|
|
9
|
|
|
|
|
953
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Prevent version.pm from mucking with our internals.
|
20
|
|
|
|
1
|
|
|
sub import {}
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Adapted from version.pm.
|
23
|
|
|
|
|
|
|
my $STRICT_INTEGER_PART = qr/0|[1-9][0-9]*/;
|
24
|
|
|
|
|
|
|
my $DOT_SEPARATOR = qr/\./;
|
25
|
|
|
|
|
|
|
my $PLUS_SEPARATOR = qr/\+/;
|
26
|
|
|
|
|
|
|
my $DASH_SEPARATOR = qr/-/;
|
27
|
|
|
|
|
|
|
my $STRICT_DOTTED_INTEGER_PART = qr/$DOT_SEPARATOR$STRICT_INTEGER_PART/;
|
28
|
|
|
|
|
|
|
my $STRICT_DOTTED_INTEGER_VERSION = qr/ $STRICT_INTEGER_PART $STRICT_DOTTED_INTEGER_PART{2,} /x;
|
29
|
|
|
|
|
|
|
my $IDENTIFIER = qr/[-0-9A-Za-z]+/;
|
30
|
|
|
|
|
|
|
my $DOTTED_IDENTIFIER = qr/(?:$DOT_SEPARATOR$IDENTIFIER)*/;
|
31
|
|
|
|
|
|
|
my $PRERELEASE = qr/$IDENTIFIER$DOTTED_IDENTIFIER/;
|
32
|
|
|
|
|
|
|
my $METADATA = qr/$IDENTIFIER$DOTTED_IDENTIFIER/;
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my $OPTIONAL_EXTRA_PART = qr/$PRERELEASE($PLUS_SEPARATOR$METADATA)?/;
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub new {
|
37
|
596
|
|
|
596
|
1
|
57157
|
my ($class, $ival) = @_;
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# Handle vstring.
|
40
|
596
|
100
|
|
|
|
1509
|
return $class->SUPER::new($ival) if Scalar::Util::isvstring($ival);
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Let version handle cloning.
|
43
|
591
|
100
|
|
|
|
759
|
if (eval { $ival->isa('version') }) {
|
|
591
|
|
|
|
|
2340
|
|
44
|
315
|
|
|
|
|
1432
|
my $self = $class->SUPER::new($ival);
|
45
|
315
|
|
|
|
|
628
|
$self->{extra} = $ival->{extra};
|
46
|
315
|
|
|
|
|
431
|
$self->{dash} = $ival->{dash};
|
47
|
315
|
|
|
|
|
633
|
$self->_evalPreRelease($self->{extra});
|
48
|
315
|
|
|
|
|
705
|
return $self;
|
49
|
|
|
|
|
|
|
}
|
50
|
|
|
|
|
|
|
|
51
|
276
|
|
|
|
|
2839
|
my ($val, $dash, $extra) = (
|
52
|
|
|
|
|
|
|
$ival =~ /^v?($STRICT_DOTTED_INTEGER_VERSION)(?:($DASH_SEPARATOR)($OPTIONAL_EXTRA_PART))?$/
|
53
|
|
|
|
|
|
|
);
|
54
|
276
|
100
|
|
|
|
726
|
_die qq{Invalid semantic version string format: "$ival"}
|
55
|
|
|
|
|
|
|
unless defined $val;
|
56
|
|
|
|
|
|
|
|
57
|
268
|
|
|
|
|
1582
|
my $self = $class->SUPER::new($val);
|
58
|
268
|
|
|
|
|
677
|
$self->{dash} = $dash;
|
59
|
268
|
|
|
|
|
416
|
$self->{extra} = $extra;
|
60
|
268
|
|
|
|
|
692
|
$self->_evalPreRelease($self->{extra});
|
61
|
|
|
|
|
|
|
|
62
|
268
|
|
|
|
|
606
|
return $self;
|
63
|
|
|
|
|
|
|
}
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Internal function to split up given string into prerelease- and patch-components
|
66
|
|
|
|
|
|
|
sub _evalPreRelease {
|
67
|
1
|
|
|
1
|
|
387
|
no warnings 'uninitialized';
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
761
|
|
68
|
643
|
|
|
643
|
|
730
|
my $self = shift;
|
69
|
643
|
|
|
|
|
729
|
my $v = shift;
|
70
|
643
|
|
|
|
|
3366
|
my ($preRelease, $plus, $patch) = (
|
71
|
|
|
|
|
|
|
$v =~ /^($PRERELEASE)(?:($PLUS_SEPARATOR)($METADATA))?$/
|
72
|
|
|
|
|
|
|
);
|
73
|
643
|
|
|
|
|
1609
|
@{$self->{prerelease}} = split $DOT_SEPARATOR,$preRelease;
|
|
643
|
|
|
|
|
1939
|
|
74
|
643
|
|
|
|
|
1041
|
$self->{plus} = $plus;
|
75
|
643
|
|
50
|
|
|
1926
|
@{$self->{patch}} = (split $DOT_SEPARATOR, $patch || undef);
|
|
643
|
|
|
|
|
1617
|
|
76
|
643
|
|
|
|
|
1025
|
return;
|
77
|
|
|
|
|
|
|
}
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
$VERSION = __PACKAGE__->new($VERSION); # For ourselves.
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub declare {
|
82
|
347
|
|
|
347
|
1
|
3553
|
my ($class, $ival) = @_;
|
83
|
|
|
|
|
|
|
return $class->new($ival) if Scalar::Util::isvstring($ival)
|
84
|
347
|
100
|
100
|
|
|
908
|
or eval { $ival->isa('version') };
|
|
345
|
|
|
|
|
1621
|
|
85
|
|
|
|
|
|
|
|
86
|
51
|
|
|
|
|
336
|
(my $v = $ival) =~ s/^v?$STRICT_DOTTED_INTEGER_VERSION(?:($DASH_SEPARATOR)($OPTIONAL_EXTRA_PART))[[:space:]]*$//;
|
87
|
51
|
|
|
|
|
92
|
my $dash = $1;
|
88
|
51
|
|
|
|
|
62
|
my $extra = $2;
|
89
|
51
|
100
|
|
|
|
102
|
$v += 0 if $v =~ s/_//g; # ignore underscores.
|
90
|
51
|
|
|
|
|
337
|
my $self = $class->SUPER::declare($v);
|
91
|
44
|
|
|
|
|
108
|
$self->{dash} = $dash;
|
92
|
44
|
|
|
|
|
50
|
$self->{extra} = $extra;
|
93
|
44
|
|
|
|
|
83
|
$self->_evalPreRelease($self->{extra});
|
94
|
44
|
|
|
|
|
125
|
return $self;
|
95
|
|
|
|
|
|
|
}
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub parse {
|
98
|
17
|
|
|
17
|
1
|
52
|
my ($class, $ival) = @_;
|
99
|
|
|
|
|
|
|
return $class->new($ival) if Scalar::Util::isvstring($ival)
|
100
|
17
|
100
|
66
|
|
|
76
|
or eval { $ival->isa('version') };
|
|
16
|
|
|
|
|
135
|
|
101
|
|
|
|
|
|
|
|
102
|
16
|
|
|
|
|
194
|
(my $v = $ival) =~ s/^v?$STRICT_DOTTED_INTEGER_VERSION(?:($DASH_SEPARATOR)($OPTIONAL_EXTRA_PART))[[:space:]]*$//;
|
103
|
16
|
|
|
|
|
47
|
my $dash = $1;
|
104
|
16
|
|
|
|
|
34
|
my $extra = $2;
|
105
|
16
|
100
|
|
|
|
69
|
$v += 0 if $v =~ s/_//g; # ignore underscores.
|
106
|
16
|
|
|
|
|
139
|
my $self = $class->SUPER::parse($v);
|
107
|
16
|
|
|
|
|
47
|
$self->{dash} = $dash;
|
108
|
16
|
|
|
|
|
32
|
$self->{extra} = $extra;
|
109
|
16
|
|
|
|
|
46
|
$self->_evalPreRelease($self->{extra});
|
110
|
16
|
|
|
|
|
83
|
return $self;
|
111
|
|
|
|
|
|
|
}
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub stringify {
|
114
|
665
|
|
|
665
|
1
|
1333
|
my $self = shift;
|
115
|
665
|
|
|
|
|
1940
|
my $str = $self->SUPER::stringify;
|
116
|
|
|
|
|
|
|
# This is purely for SemVers constructed from version objects.
|
117
|
665
|
100
|
|
|
|
1717
|
$str += 0 if $str =~ s/_//g; # ignore underscores.
|
118
|
665
|
|
100
|
|
|
4243
|
return $str . ($self->{dash} || '') . ($self->{extra} || '');
|
|
|
|
100
|
|
|
|
|
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub normal {
|
122
|
111
|
|
|
111
|
1
|
6893
|
my $self = shift;
|
123
|
111
|
|
|
|
|
874
|
(my $norm = $self->SUPER::normal) =~ s/^v//;
|
124
|
111
|
|
|
|
|
282
|
$norm =~ s/_/./g;
|
125
|
111
|
100
|
|
|
|
683
|
return $norm . ($self->{extra} ? "-$self->{extra}" : '');
|
126
|
|
|
|
|
|
|
}
|
127
|
|
|
|
|
|
|
|
128
|
1
|
|
|
1
|
1
|
4
|
sub numify { _die 'Semantic versions cannot be numified'; }
|
129
|
12
|
|
|
12
|
1
|
7441
|
sub is_alpha { !!shift->{extra} }
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# Sort Ordering:
|
133
|
|
|
|
|
|
|
# Precedence refers to how versions are compared to each other when ordered. Precedence MUST be calculated by
|
134
|
|
|
|
|
|
|
# separating the version into major, minor, patch and pre-release identifiers in that order (Build metadata does not figure into precedence).
|
135
|
|
|
|
|
|
|
# Precedence is determined by the first difference when comparing each of these identifiers from left to right as follows:
|
136
|
|
|
|
|
|
|
# 1. Major, minor, and patch versions are always compared numerically. Example: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1.
|
137
|
|
|
|
|
|
|
# 2. When major, minor, and patch are equal, a pre-release version has lower precedence than a normal version.
|
138
|
|
|
|
|
|
|
# Example: 1.0.0-alpha < 1.0.0.
|
139
|
|
|
|
|
|
|
# 3. Precedence for two pre-release versions with the same major, minor, and patch version MUST be determined by
|
140
|
|
|
|
|
|
|
# comparing each dot separated identifier from left to right until a difference is found as follows:
|
141
|
|
|
|
|
|
|
# 3.a. identifiers consisting of only digits are compared numerically and identifiers with letters or hyphens are
|
142
|
|
|
|
|
|
|
# compared lexically in ASCII sort order.
|
143
|
|
|
|
|
|
|
# 3.b. Numeric identifiers always have lower precedence than non-numeric identifiers.
|
144
|
|
|
|
|
|
|
# 3.c. A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
|
145
|
|
|
|
|
|
|
# Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.
|
146
|
|
|
|
|
|
|
sub vcmp {
|
147
|
321
|
|
|
321
|
1
|
34574
|
my $left = shift;
|
148
|
321
|
|
|
|
|
776
|
my $right = ref($left)->declare(shift);
|
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# Reverse?
|
151
|
321
|
100
|
|
|
|
674
|
($left, $right) = shift() ? ($right, $left): ($left, $right);
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# Major and minor win. - case 1.
|
154
|
321
|
100
|
|
|
|
947
|
if (my $ret = $left->SUPER::vcmp($right, 0)) {
|
155
|
108
|
|
|
|
|
982
|
return $ret;
|
156
|
|
|
|
|
|
|
} else { #cases 2, 3
|
157
|
213
|
|
|
|
|
226
|
my $lenLeft = 0;
|
158
|
213
|
|
|
|
|
191
|
my $lenRight = 0;
|
159
|
213
|
100
|
|
|
|
370
|
if (defined $left->{prerelease}) {
|
160
|
211
|
|
|
|
|
192
|
$lenLeft = scalar(@{$left->{prerelease}});
|
|
211
|
|
|
|
|
253
|
|
161
|
|
|
|
|
|
|
}
|
162
|
213
|
50
|
|
|
|
297
|
if (defined $right->{prerelease}) {
|
163
|
213
|
|
|
|
|
194
|
$lenRight = scalar(@{$right->{prerelease}});
|
|
213
|
|
|
|
|
218
|
|
164
|
|
|
|
|
|
|
}
|
165
|
213
|
|
|
|
|
267
|
my $lenMin = ($lenLeft, $lenRight)[$lenLeft > $lenRight];
|
166
|
213
|
100
|
|
|
|
273
|
if ( $lenLeft == 0) {
|
167
|
108
|
100
|
|
|
|
118
|
if ($lenRight == 0) {
|
168
|
100
|
|
|
|
|
929
|
return 0; # Neither LEFT nor RIGHT have prerelease identifiers - versions are equal
|
169
|
|
|
|
|
|
|
} else {
|
170
|
|
|
|
|
|
|
# Case 2: When major, minor, and patch are equal, a pre-release version has lower precedence than a normal version.
|
171
|
8
|
|
|
|
|
117
|
return 1; # Only RIGHT has prelease - not LEFT -> LEFT wins
|
172
|
|
|
|
|
|
|
}
|
173
|
|
|
|
|
|
|
} else {
|
174
|
105
|
100
|
|
|
|
149
|
if ($lenRight == 0) {
|
175
|
|
|
|
|
|
|
# Case 2: When major, minor, and patch are equal, a pre-release version has lower precedence than a normal version.
|
176
|
17
|
|
|
|
|
176
|
return -1; # Only LEFT has prelease identifiers - not RIGHT -> RIGHT wins
|
177
|
|
|
|
|
|
|
} else {
|
178
|
|
|
|
|
|
|
# LEFT and RIGHT have prelease identifiers - compare each part separately
|
179
|
88
|
|
|
|
|
141
|
for (my $i = 0; $i < $lenMin; $i++) {
|
180
|
95
|
|
|
|
|
208
|
my $isNumLeft = Scalar::Util::looks_like_number($left->{prerelease}->[$i]);
|
181
|
95
|
|
|
|
|
131
|
my $isNumRight = Scalar::Util::looks_like_number($right->{prerelease}->[$i]);
|
182
|
|
|
|
|
|
|
# Case 3.b: Numeric identifiers always have lower precedence than non-numeric identifiers
|
183
|
95
|
50
|
66
|
|
|
329
|
if (!$isNumLeft && $isNumRight) {
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
184
|
0
|
|
|
|
|
0
|
return 1; # LEFT identifier is Non-numeric - RIGHT identifier is numeric -> LEFT wins
|
185
|
|
|
|
|
|
|
} elsif ($isNumLeft && !$isNumRight) {
|
186
|
1
|
|
|
|
|
12
|
return -1; # LEFT identifier is numeric - RIGHT identifier is non-numeric -> RIGHT wins
|
187
|
|
|
|
|
|
|
} elsif ($isNumLeft && $isNumRight) {
|
188
|
|
|
|
|
|
|
# Case 3.a.1: identifiers consisting of only digits are compared numerically
|
189
|
6
|
50
|
|
|
|
22
|
if ($left->{prerelease}->[$i] == $right->{prerelease}->[$i] ) {
|
|
|
50
|
|
|
|
|
|
190
|
0
|
|
|
|
|
0
|
next; # LEFT identifier and RIGHT identifier are equal - step to next part
|
191
|
|
|
|
|
|
|
} elsif ($left->{prerelease}->[$i] > $right->{prerelease}->[$i] ) {
|
192
|
0
|
|
|
|
|
0
|
return 1; # LEFT identifier is bigger than RIGHT identifier -> LEFT wins
|
193
|
|
|
|
|
|
|
} else {
|
194
|
6
|
|
|
|
|
76
|
return -1; return 1; # LEFT identifier is smaller than RIGHT identifier -> RIGHT wins
|
|
0
|
|
|
|
|
0
|
|
195
|
|
|
|
|
|
|
}
|
196
|
|
|
|
|
|
|
} else {
|
197
|
|
|
|
|
|
|
# Case 3.a.2: identifiers with letters or hyphens are compared lexically in ASCII sort order.
|
198
|
88
|
100
|
|
|
|
215
|
if (lc $left->{prerelease}->[$i] eq lc $right->{prerelease}->[$i] ) {
|
|
|
100
|
|
|
|
|
|
199
|
39
|
|
|
|
|
65
|
next; # LEFT identifier and RIGHT identifier are equal - step to next part
|
200
|
|
|
|
|
|
|
} elsif (lc $left->{prerelease}->[$i] gt lc $right->{prerelease}->[$i] ) {
|
201
|
10
|
|
|
|
|
95
|
return 1; # LEFT identifier is bigger than RIGHT identifier -> LEFT wins
|
202
|
|
|
|
|
|
|
} else {
|
203
|
39
|
|
|
|
|
403
|
return -1; return 1; # LEFT identifier is smaller than RIGHT identifier -> RIGHT wins
|
|
0
|
|
|
|
|
0
|
|
204
|
|
|
|
|
|
|
}
|
205
|
|
|
|
|
|
|
}
|
206
|
|
|
|
|
|
|
}
|
207
|
|
|
|
|
|
|
# Case 3.c: A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal
|
208
|
32
|
50
|
|
|
|
54
|
if ($lenLeft > $lenRight) {
|
|
|
100
|
|
|
|
|
|
209
|
0
|
|
|
|
|
0
|
return 1; # All existing identifiers are equal, but LEFT has more identifiers -> LEFT wins
|
210
|
|
|
|
|
|
|
} elsif ($lenLeft < $lenRight) {
|
211
|
6
|
|
|
|
|
63
|
return -1; # All existing identifiers are equal, but RIGHT has more identifiers -> RIGHT wins
|
212
|
|
|
|
|
|
|
}
|
213
|
|
|
|
|
|
|
# All identifiers are equal
|
214
|
26
|
|
|
|
|
213
|
return 0;
|
215
|
|
|
|
|
|
|
}
|
216
|
|
|
|
|
|
|
}
|
217
|
|
|
|
|
|
|
}
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
1;
|
221
|
|
|
|
|
|
|
__END__
|