version-ordering.txt
The file below will be in the next dpkg version, installed in
/usr/doc/dpkg:
--8<--
(This has been edited to conform to the intent in dpkg 1.0.16.
When recent versions of dpkg compare versions they break the Version
into an upstream version and debian revision first, by splitting the
Version at the last hyphen. The revisions are only considered if the
upstream versions compare equal.)
To: debian-devel@pixar.com
Subject: Re: dpkg 0.93.8 released
[...]
Well, here is what I came up with after a bit of thought and testing.
I propose the following algorithm for comparing version numbers:
forever {
remove initial non-digit substring from string a
remove initial non-digit substring from string b
compare initial non-digit substrings lexically,
counting letters as coming before punctuation
if (they differ) return the answer
remove initial digit substring from string a
remove initial digit substring from string b
compare initial digit substrings numerically
if (they differ) return the answer
if (both strings are now empty)
the version numbers are the same, stop
if (one string is now empty)
it is the `lesser', return the answer
}
This will have the desired results:
2.1 < 2.7 < 2.7a < 2.7a-2 < 2.15
An implementation in Perl is attached below.
Ian.
#!/usr/bin/perl --
if (@ARGV) {
print &compare(@ARGV),"\n";
} else {
while(<>) { chop; chop($x=<>); print &compare($_,$x),"\n"; }
}
sub compare {
local ($a,$b) = @_;
do {
$a =~ s/^\D*//; $ad= $&; $ad =~ s/\W/ /g;
$b =~ s/^\D*//; $bd= $&; $bd =~ s/\W/ /g;
print "\t[$ad|$a] [$bd|$b]\n";
$cm = $ad cmp $bd; return $cm if $cm;
$a =~ s/^\d*//; $ad= $&;
$b =~ s/^\d*//; $bd= $&;
print "\t<$ad|$a> <$bd|$b>\n";
$cm = $ad <=> $bd; return $cm if $cm;
} while (length($a) && length($b));
print "\t{$a} {$b}\n";
return length($a) cmp length($b);
}
Reply to: