| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # Copyright © Colin Watson | 
| 2 |  |  |  |  |  |  | # Copyright © Ian Jackson | 
| 3 |  |  |  |  |  |  | # Copyright © 2007 Don Armstrong . | 
| 4 |  |  |  |  |  |  | # Copyright © 2009 Raphaël Hertzog | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # This program is free software; you can redistribute it and/or modify | 
| 7 |  |  |  |  |  |  | # it under the terms of the GNU General Public License as published by | 
| 8 |  |  |  |  |  |  | # the Free Software Foundation; either version 2 of the License, or | 
| 9 |  |  |  |  |  |  | # (at your option) any later version. | 
| 10 |  |  |  |  |  |  | # | 
| 11 |  |  |  |  |  |  | # This program is distributed in the hope that it will be useful, | 
| 12 |  |  |  |  |  |  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 13 |  |  |  |  |  |  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 14 |  |  |  |  |  |  | # GNU General Public License for more details. | 
| 15 |  |  |  |  |  |  | # | 
| 16 |  |  |  |  |  |  | # You should have received a copy of the GNU General Public License | 
| 17 |  |  |  |  |  |  | # along with this program.  If not, see . | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | package Debian::Dpkg::Version; | 
| 20 |  |  |  |  |  |  |  | 
| 21 | 1 |  |  | 1 |  | 1298 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 38 |  | 
| 22 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 43 |  | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | our $VERSION = '1.15.5.6.1'; | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 1 |  |  | 1 |  | 20 | use Carp; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 77 |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 | 1 |  |  | 1 |  | 4 | use base qw(Exporter); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 134 |  | 
| 29 |  |  |  |  |  |  | our @EXPORT = qw(version_compare version_compare_relation | 
| 30 |  |  |  |  |  |  | version_normalize_relation version_compare_string | 
| 31 |  |  |  |  |  |  | version_compare_part version_split_digits version_check | 
| 32 |  |  |  |  |  |  | REL_LT REL_LE REL_EQ REL_GE REL_GT); | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | use constant { | 
| 35 | 1 |  |  |  |  | 279 | REL_LT => '<<', | 
| 36 |  |  |  |  |  |  | REL_LE => '<=', | 
| 37 |  |  |  |  |  |  | REL_EQ => '=', | 
| 38 |  |  |  |  |  |  | REL_GE => '>=', | 
| 39 |  |  |  |  |  |  | REL_GT => '>>', | 
| 40 | 1 |  |  | 1 |  | 5 | }; | 
|  | 1 |  |  |  |  | 2 |  | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | use overload | 
| 43 |  |  |  |  |  |  | '<=>' => \&comparison, | 
| 44 |  |  |  |  |  |  | 'cmp' => \&comparison, | 
| 45 |  |  |  |  |  |  | '""'  => \&as_string, | 
| 46 | 2236 |  |  | 2236 |  | 5253 | 'bool' => sub { return $_[0]->is_valid(); }, | 
| 47 | 1 |  |  | 1 |  | 7 | 'fallback' => 1; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 14 |  | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | =head1 NAME | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | Debian::Dpkg::Version - handling and comparing dpkg-style version numbers | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | The Debian::Dpkg::Version module provides pure-Perl routines to compare | 
| 56 |  |  |  |  |  |  | dpkg-style version numbers (as used in Debian packages) and also | 
| 57 |  |  |  |  |  |  | an object oriented interface overriding perl operators | 
| 58 |  |  |  |  |  |  | to do the right thing when you compare Debian::Dpkg::Version object between | 
| 59 |  |  |  |  |  |  | them. | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | =head1 OBJECT INTERFACE | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =over 4 | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | =item my $v = Debian::Dpkg::Version->new($version, %opts) | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | Create a new Debian::Dpkg::Version object corresponding to the version indicated in | 
| 68 |  |  |  |  |  |  | the string (scalar) $version. By default it will accepts any string | 
| 69 |  |  |  |  |  |  | and consider it as a valid version. If you pass the option "check => 1", | 
| 70 |  |  |  |  |  |  | it will return undef if the version is invalid (see version_check for | 
| 71 |  |  |  |  |  |  | details). | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | You can always call $v->is_valid() later on to verify that the version is | 
| 74 |  |  |  |  |  |  | valid. | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | =cut | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | sub new { | 
| 79 | 1210 |  |  | 1210 | 1 | 30098 | my ($this, $ver, %opts) = @_; | 
| 80 | 1210 |  | 33 |  |  | 4343 | my $class = ref($this) || $this; | 
| 81 | 1210 | 50 |  |  |  | 2459 | $ver = "$ver" if ref($ver); # Try to stringify objects | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 1210 | 100 |  |  |  | 3963 | if ($opts{'check'}) { | 
| 84 | 1204 | 50 |  |  |  | 2083 | return undef unless version_check($ver); | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  |  | 
| 87 | 1210 |  |  |  |  | 2361 | my $self = {}; | 
| 88 | 1210 | 100 |  |  |  | 2994 | if ($ver =~ /^(\d*):(.+)$/) { | 
| 89 | 126 |  |  |  |  | 425 | $self->{'epoch'} = $1; | 
| 90 | 126 |  |  |  |  | 245 | $ver = $2; | 
| 91 |  |  |  |  |  |  | } else { | 
| 92 | 1084 |  |  |  |  | 2608 | $self->{'epoch'} = 0; | 
| 93 | 1084 |  |  |  |  | 1930 | $self->{'no_epoch'} = 1; | 
| 94 |  |  |  |  |  |  | } | 
| 95 | 1210 | 100 |  |  |  | 3635 | if ($ver =~ /(.+)-(.*)$/) { | 
| 96 | 520 |  |  |  |  | 1905 | $self->{'version'} = $1; | 
| 97 | 520 |  |  |  |  | 1201 | $self->{'revision'} = $2; | 
| 98 |  |  |  |  |  |  | } else { | 
| 99 | 690 |  |  |  |  | 1231 | $self->{'version'} = $ver; | 
| 100 | 690 |  |  |  |  | 1340 | $self->{'revision'} = 0; | 
| 101 | 690 |  |  |  |  | 1241 | $self->{'no_revision'} = 1; | 
| 102 |  |  |  |  |  |  | } | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 1210 |  |  |  |  | 6145 | return bless $self, $class; | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | =item $v->is_valid() | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | Returns true if the version is valid, false otherwise. | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | =cut | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | sub is_valid { | 
| 114 | 2239 |  |  | 2239 | 1 | 3120 | my ($self) = @_; | 
| 115 | 2239 |  |  |  |  | 4452 | return scalar version_check($self); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | =item $v->epoch(), $v->version(), $v->revision() | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | Returns the corresponding part of the full version string. | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =cut | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | sub epoch { | 
| 125 | 2242 |  |  | 2242 | 1 | 2489 | my $self = shift; | 
| 126 | 2242 |  |  |  |  | 16056 | return $self->{'epoch'}; | 
| 127 |  |  |  |  |  |  | } | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | sub version { | 
| 130 | 2086 |  |  | 2086 | 1 | 2130 | my $self = shift; | 
| 131 | 2086 |  |  |  |  | 9224 | return $self->{'version'}; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | sub revision { | 
| 135 | 578 |  |  | 578 | 1 | 627 | my $self = shift; | 
| 136 | 578 |  |  |  |  | 1458 | return $self->{'revision'}; | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | =item $v1 <=> $v2, $v1 < $v2, $v1 <= $v2, $v1 > $v2, $v1 >= $v2 | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | Numerical comparison of various versions numbers. One of the two operands | 
| 142 |  |  |  |  |  |  | needs to be a Debian::Dpkg::Version, the other one can be anything provided that | 
| 143 |  |  |  |  |  |  | its string representation is a version number. | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | =cut | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | sub comparison { | 
| 148 | 1121 |  |  | 1121 | 0 | 2006 | my ($a, $b, $inverted) = @_; | 
| 149 | 1121 | 100 | 66 |  |  | 5964 | if (not ref($b) or not $b->isa("Debian::Dpkg::Version")) { | 
| 150 | 3 |  |  |  |  | 9 | $b = Debian::Dpkg::Version->new($b); | 
| 151 |  |  |  |  |  |  | } | 
| 152 | 1121 | 50 |  |  |  | 2185 | ($a, $b) = ($b, $a) if $inverted; | 
| 153 | 1121 |  |  |  |  | 2073 | my $r = $a->epoch() <=> $b->epoch(); | 
| 154 | 1121 | 100 |  |  |  | 2756 | return $r if $r; | 
| 155 | 1043 |  |  |  |  | 1881 | $r = version_compare_part($a->version(), $b->version()); | 
| 156 | 1043 | 100 |  |  |  | 6206 | return $r if $r; | 
| 157 | 289 |  |  |  |  | 658 | return version_compare_part($a->revision(), $b->revision()); | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | =item "$v" | 
| 161 |  |  |  |  |  |  | =item $v->as_string() | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | Returns the string representation of the version number. | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | =cut | 
| 166 |  |  |  |  |  |  | sub as_string { | 
| 167 | 2326 |  |  | 2326 | 1 | 3017 | my ($self) = @_; | 
| 168 | 2326 |  |  |  |  | 3003 | my $str = ""; | 
| 169 | 2326 | 100 |  |  |  | 5893 | $str .= $self->{epoch} . ":" unless $self->{no_epoch}; | 
| 170 | 2326 |  |  |  |  | 3612 | $str .= $self->{version}; | 
| 171 | 2326 | 100 |  |  |  | 9012 | $str .= "-" . $self->{revision} unless $self->{no_revision}; | 
| 172 | 2326 |  |  |  |  | 6213 | return $str; | 
| 173 |  |  |  |  |  |  | } | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | =back | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | =head1 FUNCTIONS | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | All the functions are exported by default. | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | =over 4 | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | =item version_compare($a, $b) | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | Returns -1 is $a is smaller than $b, 0 if they are equal and 1 if $a | 
| 186 |  |  |  |  |  |  | is bigger than $b. | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | If $a or $b are not valid version numbers, it dies with an error. | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | =cut | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | sub version_compare($$) { | 
| 193 | 559 |  |  | 559 | 1 | 882 | my ($a, $b) = @_; | 
| 194 | 559 |  | 33 |  |  | 1850 | my $va = Debian::Dpkg::Version->new($a, check => 1) || error(_g("%s is not a valid version"), "$a"); | 
| 195 | 559 |  | 33 |  |  | 1473 | my $vb = Debian::Dpkg::Version->new($b, check => 1) || error(_g("%s is not a valid version"), "$b"); | 
| 196 | 559 |  |  |  |  | 1155 | return $va <=> $vb; | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | =item version_compare_relation($a, $rel, $b) | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | Returns the result (0 or 1) of the given comparison operation. This | 
| 202 |  |  |  |  |  |  | function is implemented on top of version_compare(). | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | Allowed values for $rel are the exported constants REL_GT, REL_GE, | 
| 205 |  |  |  |  |  |  | REL_EQ, REL_LE, REL_LT. Use version_normalize_relation() if you | 
| 206 |  |  |  |  |  |  | have an input string containing the operator. | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  | =cut | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | sub version_compare_relation($$$) { | 
| 211 | 516 |  |  | 516 | 1 | 4909 | my ($a, $op, $b) = @_; | 
| 212 | 516 |  |  |  |  | 933 | my $res = version_compare($a, $b); | 
| 213 |  |  |  |  |  |  |  | 
| 214 | 516 | 100 |  |  |  | 2975 | if ($op eq REL_GT) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 215 | 86 |  |  |  |  | 495 | return $res > 0; | 
| 216 |  |  |  |  |  |  | } elsif ($op eq REL_GE) { | 
| 217 | 129 |  |  |  |  | 819 | return $res >= 0; | 
| 218 |  |  |  |  |  |  | } elsif ($op eq REL_EQ) { | 
| 219 | 86 |  |  |  |  | 510 | return $res == 0; | 
| 220 |  |  |  |  |  |  | } elsif ($op eq REL_LE) { | 
| 221 | 129 |  |  |  |  | 744 | return $res <= 0; | 
| 222 |  |  |  |  |  |  | } elsif ($op eq REL_LT) { | 
| 223 | 86 |  |  |  |  | 545 | return $res < 0; | 
| 224 |  |  |  |  |  |  | } else { | 
| 225 | 0 |  |  |  |  | 0 | internerr("unsupported relation for version_compare_relation(): '$op'"); | 
| 226 |  |  |  |  |  |  | } | 
| 227 |  |  |  |  |  |  | } | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | =item my $rel = version_normalize_relation($rel_string) | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | Returns the normalized constant of the relation $rel (a value | 
| 232 |  |  |  |  |  |  | among REL_GT, REL_GE, REL_EQ, REL_LE and REL_LT). Supported | 
| 233 |  |  |  |  |  |  | relations names in input are: "gt", "ge", "eq", "le", "lt", ">>", ">=", | 
| 234 |  |  |  |  |  |  | "=", "<=", "<<". ">" and "<" are also supported but should not be used as | 
| 235 |  |  |  |  |  |  | they are obsolete aliases of ">=" and "<=". | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | =cut | 
| 238 |  |  |  |  |  |  |  | 
| 239 |  |  |  |  |  |  | sub version_normalize_relation($) { | 
| 240 | 516 |  |  | 516 | 1 | 217849 | my $op = shift; | 
| 241 |  |  |  |  |  |  |  | 
| 242 | 516 | 100 | 100 |  |  | 3193 | warning("relation %s is deprecated: use %s or %s", | 
| 243 |  |  |  |  |  |  | $op, "$op$op", "$op=") if ($op eq '>' or $op eq '<'); | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 516 | 100 | 100 |  |  | 6362 | if ($op eq '>>' or $op eq 'gt') { | 
|  |  | 100 | 100 |  |  |  |  | 
|  |  | 100 | 100 |  |  |  |  | 
|  |  | 100 | 100 |  |  |  |  | 
|  |  | 50 | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 246 | 86 |  |  |  |  | 255 | return REL_GT; | 
| 247 |  |  |  |  |  |  | } elsif ($op eq '>=' or $op eq 'ge' or $op eq '>') { | 
| 248 | 129 |  |  |  |  | 350 | return REL_GE; | 
| 249 |  |  |  |  |  |  | } elsif ($op eq '=' or $op eq 'eq') { | 
| 250 | 86 |  |  |  |  | 268 | return REL_EQ; | 
| 251 |  |  |  |  |  |  | } elsif ($op eq '<=' or $op eq 'le' or $op eq '<') { | 
| 252 | 129 |  |  |  |  | 448 | return REL_LE; | 
| 253 |  |  |  |  |  |  | } elsif ($op eq '<<' or $op eq 'lt') { | 
| 254 | 86 |  |  |  |  | 251 | return REL_LT; | 
| 255 |  |  |  |  |  |  | } else { | 
| 256 | 0 |  |  |  |  | 0 | internerr("bad relation '$op'"); | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  | } | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | =item version_compare_string($a, $b) | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | String comparison function used for comparing non-numerical parts of version | 
| 263 |  |  |  |  |  |  | numbers. Returns -1 is $a is smaller than $b, 0 if they are equal and 1 if $a | 
| 264 |  |  |  |  |  |  | is bigger than $b. | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | The "~" character always sort lower than anything else. Digits sort lower | 
| 267 |  |  |  |  |  |  | than non-digits. Among remaining characters alphabetic characters (A-Za-z) | 
| 268 |  |  |  |  |  |  | sort lower than the other ones. Within each range, the ASCII decimal value | 
| 269 |  |  |  |  |  |  | of the character is used to sort between characters. | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | =cut | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | sub version_compare_string($$) { | 
| 274 |  |  |  |  |  |  | sub order { | 
| 275 | 7810 |  |  | 7810 | 0 | 9867 | my ($x) = @_; | 
| 276 | 7810 | 100 |  |  |  | 29788 | if ($x eq '~') { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 277 | 338 |  |  |  |  | 845 | return -1; | 
| 278 |  |  |  |  |  |  | } elsif ($x =~ /^\d$/) { | 
| 279 | 234 |  |  |  |  | 3770 | return $x * 1 + 1; | 
| 280 |  |  |  |  |  |  | } elsif ($x =~ /^[A-Za-z]$/) { | 
| 281 | 5280 |  |  |  |  | 13814 | return ord($x); | 
| 282 |  |  |  |  |  |  | } else { | 
| 283 | 1958 |  |  |  |  | 11183 | return ord($x) + 256; | 
| 284 |  |  |  |  |  |  | } | 
| 285 |  |  |  |  |  |  | } | 
| 286 | 1486 |  |  | 1486 | 1 | 4705 | my @a = map(order($_), split(//, shift)); | 
| 287 | 1486 |  |  |  |  | 11667 | my @b = map(order($_), split(//, shift)); | 
| 288 | 1486 |  |  |  |  | 2326 | while (1) { | 
| 289 | 4559 |  |  |  |  | 7023 | my ($a, $b) = (shift @a, shift @b); | 
| 290 | 4559 | 100 | 66 |  |  | 11509 | return 0 if not defined($a) and not defined($b); | 
| 291 | 3541 |  | 100 |  |  | 19342 | $a ||= 0; # Default order for "no character" | 
| 292 | 3541 |  | 100 |  |  | 6031 | $b ||= 0; | 
| 293 | 3541 | 100 |  |  |  | 6986 | return 1 if $a > $b; | 
| 294 | 3281 | 100 |  |  |  | 7283 | return -1 if $a < $b; | 
| 295 |  |  |  |  |  |  | } | 
| 296 |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | =item version_compare_part($a, $b) | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | Compare two corresponding sub-parts of a version number (either upstream | 
| 301 |  |  |  |  |  |  | version or debian revision). | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | Each parameter is split by version_split_digits() and resulting items | 
| 304 |  |  |  |  |  |  | are compared together.in digits and non-digits items that are compared | 
| 305 |  |  |  |  |  |  | together. As soon as a difference happens, it returns -1 if $a is smaller | 
| 306 |  |  |  |  |  |  | than $b, 0 if they are equal and 1 if $a is bigger than $b. | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | =cut | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | sub version_compare_part($$) { | 
| 311 | 1332 |  |  | 1332 | 1 | 2456 | my @a = version_split_digits(shift); | 
| 312 | 1332 |  |  |  |  | 2533 | my @b = version_split_digits(shift); | 
| 313 | 1332 |  |  |  |  | 1677 | while (1) { | 
| 314 | 3685 |  |  |  |  | 6245 | my ($a, $b) = (shift @a, shift @b); | 
| 315 | 3685 | 100 | 66 |  |  | 9704 | return 0 if not defined($a) and not defined($b); | 
| 316 | 3185 |  | 100 |  |  | 6583 | $a ||= 0; # Default value for lack of version | 
| 317 | 3185 |  | 100 |  |  | 11701 | $b ||= 0; | 
| 318 | 3185 | 100 | 100 |  |  | 15649 | if ($a =~ /^\d+$/ and $b =~ /^\d+$/) { | 
| 319 |  |  |  |  |  |  | # Numerical comparison | 
| 320 | 1699 |  |  |  |  | 2931 | my $cmp = $a <=> $b; | 
| 321 | 1699 | 100 |  |  |  | 4436 | return $cmp if $cmp; | 
| 322 |  |  |  |  |  |  | } else { | 
| 323 |  |  |  |  |  |  | # String comparison | 
| 324 | 1486 |  |  |  |  | 2630 | my $cmp = version_compare_string($a, $b); | 
| 325 | 1486 | 100 |  |  |  | 3890 | return $cmp if $cmp; | 
| 326 |  |  |  |  |  |  | } | 
| 327 |  |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  | } | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | =item my @items = version_split_digits($version) | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | Splits a string in items that are each entirely composed either | 
| 333 |  |  |  |  |  |  | of digits or of non-digits. For instance for "1.024~beta1+svn234" it would | 
| 334 |  |  |  |  |  |  | return ("1", ".", "024", "~beta", "1", "+svn", "234"). | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | =cut | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | sub version_split_digits($) { | 
| 339 | 2664 |  |  | 2664 | 1 | 21005 | return split(/(?<=\d)(?=\D)|(?<=\D)(?=\d)/, $_[0]); | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | =item my ($ok, $msg) = version_check($version) | 
| 343 |  |  |  |  |  |  | =item my $ok = version_check($version) | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | Checks the validity of $version as a version number. Returns 1 in $ok | 
| 346 |  |  |  |  |  |  | if the version is valid, 0 otherwise. In the latter case, $msg | 
| 347 |  |  |  |  |  |  | contains a description of the problem with the $version scalar. | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | =cut | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | sub version_check($) { | 
| 352 | 3443 |  |  | 3443 | 1 | 4253 | my $version = shift; | 
| 353 | 3443 | 100 |  |  |  | 8814 | $version = "$version" if ref($version); | 
| 354 |  |  |  |  |  |  |  | 
| 355 | 3443 | 100 | 33 |  |  | 20384 | if (not defined($version) or not length($version)) { | 
| 356 | 1 |  |  |  |  | 4 | my $msg = _g("version number cannot be empty"); | 
| 357 | 1 | 50 |  |  |  | 13 | return (0, $msg) if wantarray; | 
| 358 | 1 |  |  |  |  | 8 | return 0; | 
| 359 |  |  |  |  |  |  | } | 
| 360 | 3442 | 100 |  |  |  | 10276 | if ($version =~ m/([^-+:.0-9a-zA-Z~])/o) { | 
| 361 | 1 |  |  |  |  | 3 | my $msg = sprintf(_g("version number contains illegal character `%s'"), $1); | 
| 362 | 1 | 50 |  |  |  | 3 | return (0, $msg) if wantarray; | 
| 363 | 1 |  |  |  |  | 5 | return 0; | 
| 364 |  |  |  |  |  |  | } | 
| 365 | 3441 | 100 | 100 |  |  | 10584 | if ($version =~ /:/ and $version !~ /^\d*:/) { | 
| 366 | 1 |  |  |  |  | 4 | $version =~ /^([^:]*):/; | 
| 367 | 1 |  |  |  |  | 3 | my $msg = sprintf(_g("epoch part of the version number " . | 
| 368 |  |  |  |  |  |  | "is not a number: '%s'"), $1); | 
| 369 | 1 | 50 |  |  |  | 6 | return (0, $msg) if wantarray; | 
| 370 | 1 |  |  |  |  | 5 | return 0; | 
| 371 |  |  |  |  |  |  | } | 
| 372 | 3440 | 50 |  |  |  | 5872 | return (1, "") if wantarray; | 
| 373 | 3440 |  |  |  |  | 9034 | return 1; | 
| 374 |  |  |  |  |  |  | } | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | sub _g { | 
| 377 | 3 |  |  | 3 |  | 10 | return @_; | 
| 378 |  |  |  |  |  |  | } | 
| 379 |  |  |  |  |  |  | sub warning { | 
| 380 |  |  |  |  |  |  | carp(@_); | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | =back | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | =head1 AUTHOR | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | Don Armstrong , Colin Watson | 
| 388 |  |  |  |  |  |  | and Raphaël Hertzog , based on | 
| 389 |  |  |  |  |  |  | the implementation in C by Ian Jackson and others. | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | =cut | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | 1; |