[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: