File Coverage

blib/lib/CPANPLUS/Dist/Gentoo/Version.pm
Criterion Covered Total %
statement 91 91 100.0
branch 36 36 100.0
condition 21 23 91.3
subroutine 12 12 100.0
pod 5 5 100.0
total 165 167 98.8


line stmt bran cond sub pod time code
1             package CPANPLUS::Dist::Gentoo::Version;
2              
3 5     5   23343 use strict;
  5         11  
  5         169  
4 5     5   25 use warnings;
  5         9  
  5         213  
5              
6             =head1 NAME
7              
8             CPANPLUS::Dist::Gentoo::Version - Gentoo version object.
9              
10             =head1 VERSION
11              
12             Version 0.12
13              
14             =cut
15              
16             our $VERSION = '0.12';
17              
18             =head1 DESCRIPTION
19              
20             This class models Gentoo versions as described in L.
21              
22             =cut
23              
24 5     5   24 use Scalar::Util ();
  5         8  
  5         160  
25              
26             use overload (
27 5         70 '<=>' => \&_spaceship,
28             '""' => \&_stringify,
29 5     5   1651 );
  5         913  
30              
31             my $int_rx = qr/[0-9]+/;
32             my $letter_rx = qr/[a-zA-Z]/;
33             my $dotted_num_rx = qr/$int_rx(?:\.$int_rx)*/o;
34              
35             my @suffixes = qw;
36             my $suffix_rx = join '|', grep !/^normal$/, @suffixes;
37             $suffix_rx = qr/(?:$suffix_rx)/o;
38              
39             our $version_rx = qr{
40             $dotted_num_rx $letter_rx?
41             (?:_$suffix_rx$int_rx?)*
42             (?:-r$int_rx)?
43             }xo;
44              
45             my $capturing_version_rx = qr{
46             ($dotted_num_rx) ($letter_rx)?
47             ((?:_$suffix_rx$int_rx?)*)
48             (?:-r($int_rx))?
49             }xo;
50              
51             =head1 METHODS
52              
53             =head2 C
54              
55             Creates a new L object from the version string C<$vstring>.
56              
57             =cut
58              
59             sub new {
60 850     850 1 98800 my $class = shift;
61 850   66     2707 $class = ref($class) || $class;
62              
63 850         1117 my $vstring = shift;
64 850 100       1785 if (defined $vstring) {
65 849         1804 $vstring =~ s/^[._]+//g;
66 849         1745 $vstring =~ s/[._]+$//g;
67              
68 849 100       5052 if ($vstring =~ /^$capturing_version_rx$/o) {
69 846         12562 return bless {
70             string => $vstring,
71             version => [ split /\.+/, $1 ],
72             letter => $2,
73             suffixes => [ map /_($suffix_rx)($int_rx)?/go, $3 ],
74             revision => $4,
75             }, $class;
76             }
77              
78 3         22 require Carp;
79 3         352 Carp::croak("Couldn't parse version string '$vstring'");
80             }
81              
82 1         12 require Carp;
83 1         181 Carp::croak('You must specify a version string');
84             }
85              
86             my @parts;
87             BEGIN {
88 5     5   2308 @parts = qw;
89 5     2989 1 4458 eval "sub $_ { \$_[0]->{$_} }" for @parts;
  2989     2425 1 52678  
  2425     2833 1 8899  
  2833     3525 1 51656  
  3525         56258  
90             }
91              
92             =head2 C
93              
94             Read-only accessor for the C part of the version object.
95              
96             =head2 C
97              
98             Read-only accessor for the C part of the version object.
99              
100             =head2 C
101              
102             Read-only accessor for the C part of the version object.
103              
104             =head2 C
105              
106             Read-only accessor for the C part of the version object.
107              
108             =cut
109              
110             my %suffix_grade = do {
111             my $i = 0;
112             map { $_ => ++$i } @suffixes;
113             };
114              
115             sub _spaceship {
116 929     929   25993 my ($v1, $v2, $r) = @_;
117              
118 929 100 66     5149 unless (Scalar::Util::blessed($v2) and $v2->isa(__PACKAGE__)) {
119 389         921 $v2 = $v1->new($v2);
120             }
121              
122 928 100       2417 ($v1, $v2) = ($v2, $v1) if $r;
123              
124             {
125 928         1062 my @a = @{ $v1->version };
  928         961  
  928         36324  
126 928         1228 my @b = @{ $v2->version };
  928         25071  
127              
128             {
129 928         1146 my $x = shift @a;
  928         1424  
130 928         1243 my $y = shift @b;
131 928         1733 my $c = $x <=> $y;
132 928 100       3225 return $c if $c;
133             }
134              
135 798   100     3359 while (@a and @b) {
136 762         1145 my $x = shift @a;
137 762         1028 my $y = shift @b;
138 762         849 my $c;
139 762 100 100     3163 if ($x =~ /^0/ or $y =~ /^0/) {
140 690         4616 s/0+\z// for $x, $y;
141 690         1132 $c = $x cmp $y;
142             } else {
143 72         119 $c = $x <=> $y;
144             }
145 762 100       3355 return $c if $c;
146             }
147              
148 696 100       1516 return 1 if @a;
149 678 100       1633 return -1 if @b;
150             }
151              
152             {
153 660 100       729 my ($l1, $l2) = map { defined() ? ord : 0 } map $_->letter, $v1, $v2;
  660         18794  
  1320         2979  
154              
155 660         1002 my $c = $l1 <=> $l2;
156 660 100       1978 return $c if $c;
157             }
158              
159             {
160 582         583 my @a = @{ $v1->suffixes };
  582         562  
  582         16158  
161 582         808 my @b = @{ $v2->suffixes };
  582         15659  
162              
163 582   100     2386 while (@a or @b) {
164 330   100     931 my $x = $suffix_grade{ shift(@a) || 'normal' };
165 330   100     860 my $y = $suffix_grade{ shift(@b) || 'normal' };
166 330         418 my $c = $x <=> $y;
167 330 100       2014 return $c if $c;
168              
169 168   100     428 $x = shift(@a) || 0;
170 168   100     430 $y = shift(@b) || 0;
171 168         233 $c = $x <=> $y;
172 168 100       1049 return $c if $c;
173             }
174             }
175              
176             {
177 378 100       448 my ($r1, $r2) = map { defined() ? $_ : 0 } map $_->revision, $v1, $v2;
  378         10543  
  756         1648  
178              
179 378         596 my $c = $r1 <=> $r2;
180 378 100       914 return $c if $c;
181             }
182              
183 360         2978 return 0;
184             }
185              
186             sub _stringify {
187 1669     1669   361388 my ($v) = @_;
188              
189 1669         50842 my ($version, $letter, $suffixes, $revision) = map $v->$_, @parts;
190 1669         3895 my @suffixes = @$suffixes;
191              
192 1669         3697 $version = join '.', @$version;
193 1669 100       3517 $version .= $letter if defined $letter;
194 1669         5463 while (my @suffix = splice @suffixes, 0, 2) {
195 492         713 my $s = $suffix[0];
196 492         534 my $n = $suffix[1];
197 492 100       2415 $version .= "_$s" . (defined $n ? $n : '');
198             }
199 1669 100       2958 $version .= "-r$revision" if defined $revision;
200              
201 1669         8505 $version;
202             }
203              
204             =pod
205              
206             This class provides overloaded methods for numerical comparison and stringification.
207              
208             =head1 SEE ALSO
209              
210             L.
211              
212             =head1 AUTHOR
213              
214             Vincent Pit, C<< >>, L.
215              
216             You can contact me by mail or on C (vincent).
217              
218             =head1 BUGS
219              
220             Please report any bugs or feature requests to C, or through the web interface at L.
221             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
222              
223             =head1 SUPPORT
224              
225             You can find documentation for this module with the perldoc command.
226              
227             perldoc CPANPLUS::Dist::Gentoo
228              
229             =head1 COPYRIGHT & LICENSE
230              
231             Copyright 2009,2010,2011,2012 Vincent Pit, all rights reserved.
232              
233             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
234              
235             =cut
236              
237             1; # End of CPANPLUS::Dist::Gentoo::Version