File Coverage

blib/lib/SemVer.pm
Criterion Covered Total %
statement 73 73 100.0
branch 27 28 96.4
condition 7 10 70.0
subroutine 15 15 100.0
pod 8 8 100.0
total 130 134 97.0


line stmt bran cond sub pod time code
1             package SemVer;
2              
3 1     1   28066 use 5.008001;
  1         4  
  1         35  
4 1     1   6 use strict;
  1         2  
  1         57  
5 1     1   466 use version 0.82;
  1         1482  
  1         5  
6 1     1   70 use Scalar::Util ();
  1         2  
  1         25  
7              
8             use overload (
9 1         5 '""' => 'stringify',
10             '<=>' => 'vcmp',
11             'cmp' => 'vcmp',
12 1     1   1032 );
  1         788  
13              
14             our @ISA = qw(version);
15             our $VERSION = '0.6.0'; # For Module::Build
16              
17 9     9   49 sub _die { require Carp; Carp::croak(@_) }
  9         1167  
18              
19             # Prevent version.pm from mucking with our internals.
20 1     1   14 sub import {}
21              
22             # Adapted from version.pm.
23             my $STRICT_INTEGER_PART = qr/0|[1-9][0-9]*/;
24             my $STRICT_DOTTED_INTEGER_PART = qr/\.$STRICT_INTEGER_PART/;
25             my $STRICT_DOTTED_INTEGER_VERSION =
26             qr/ $STRICT_INTEGER_PART $STRICT_DOTTED_INTEGER_PART{2,} /x;
27             my $OPTIONAL_EXTRA_PART = qr/[a-zA-Z][-0-9A-Za-z]*/;
28              
29             sub new {
30 331     331 1 40937 my ($class, $ival) = @_;
31              
32             # Handle vstring.
33 331 100       706 return $class->SUPER::new($ival) if Scalar::Util::isvstring($ival);
34              
35             # Let version handle cloning.
36 330 100       368 if (eval { $ival->isa('version') }) {
  330         1213  
37 229         1369 my $self = $class->SUPER::new($ival);
38 229         456 $self->{extra} = $ival->{extra};
39 229         288 $self->{dash} = $ival->{dash};
40 229         472 return $self;
41             }
42              
43 101         1021 my ($val, $dash, $extra) = (
44             $ival =~ /^v?($STRICT_DOTTED_INTEGER_VERSION)(?:(-)($OPTIONAL_EXTRA_PART))?$/
45             );
46 101 100       467 _die qq{Invalid semantic version string format: "$ival"}
47             unless defined $val;
48              
49 93         605 my $self = $class->SUPER::new($val);
50 93         274 $self->{dash} = $dash;
51 93         119 $self->{extra} = $extra;
52 93         263 return $self;
53             }
54              
55             $VERSION = __PACKAGE__->new($VERSION); # For ourselves.
56              
57             sub declare {
58 267     267 1 348 my ($class, $ival) = @_;
59             return $class->new($ival) if Scalar::Util::isvstring($ival)
60 267 100 66     885 or eval { $ival->isa('version') };
  267         1539  
61              
62 58         326 (my $v = $ival) =~ s/(?:(-?)($OPTIONAL_EXTRA_PART))[[:space:]]*$//;
63 58         92 my $dash = $1;
64 58         55 my $extra = $2;
65 58 100       114 $v += 0 if $v =~ s/_//g; # ignore underscores.
66 58         384 my $self = $class->SUPER::declare($v);
67 58         149 $self->{dash} = $dash;
68 58         69 $self->{extra} = $extra;
69 58         181 return $self;
70             }
71              
72             sub parse {
73 23     23 1 33 my ($class, $ival) = @_;
74             return $class->new($ival) if Scalar::Util::isvstring($ival)
75 23 50 33     81 or eval { $ival->isa('version') };
  23         148  
76              
77 23         208 (my $v = $ival) =~ s/(?:(-?)($OPTIONAL_EXTRA_PART))[[:space:]]*$//;
78 23         44 my $dash = $1;
79 23         28 my $extra = $2;
80 23 100       52 $v += 0 if $v =~ s/_//g; # ignore underscores.
81 23         158 my $self = $class->SUPER::parse($v);
82 23         58 $self->{dash} = $dash;
83 23         29 $self->{extra} = $extra;
84 23         110 return $self;
85             }
86              
87             sub stringify {
88 505     505 1 556 my $self = shift;
89 505         1412 my $str = $self->SUPER::stringify;
90             # This is purely for SemVers constructed from version objects.
91 505 100       1133 $str += 0 if $str =~ s/_//g; # ignore underscores.
92 505   100     3427 return $str . ($self->{dash} || '') . ($self->{extra} || '');
      100        
93             }
94              
95             sub normal {
96 119     119 1 5517 my $self = shift;
97 119         909 (my $norm = $self->SUPER::normal) =~ s/^v//;
98 119         176 $norm =~ s/_/./g;
99 119 100       670 return $norm . ($self->{extra} ? "-$self->{extra}" : '');
100             }
101              
102 1     1 1 3 sub numify { _die 'Semantic versions cannot be numified'; }
103 12     12 1 8594 sub is_alpha { !!shift->{extra} }
104              
105             sub vcmp {
106 242     242 1 14358 my $left = shift;
107 242         576 my $right = ref($left)->declare(shift);
108              
109             # Reverse?
110 242 100       649 ($left, $right) = shift() ? ($right, $left): ($left, $right);
111              
112             # Major and minor win.
113 242 100       843 if (my $ret = $left->SUPER::vcmp($right, 0)) {
114 62         425 return $ret;
115             } else {
116             # They're equal. Check the extra text stuff.
117 180 100       300 if (my $l = $left->{extra}) {
118 74 100       192 my $r = $right->{extra} or return -1;
119 66         481 return lc $l cmp lc $r;
120             } else {
121 106 100       811 return $right->{extra} ? 1 : 0;
122             }
123             }
124             }
125              
126             1;
127             __END__