Add support for two-dot versions.
authorAlexandre Duret-Lutz <adl@gnu.org>
Wed, 20 Mar 2002 22:27:11 +0000 (22:27 +0000)
committerAlexandre Duret-Lutz <adl@gnu.org>
Wed, 20 Mar 2002 22:27:11 +0000 (22:27 +0000)
* tests/version5.test: New file.
* tests/Makefile.am (TESTS): Add it.
* automake.in (version_split, version_compare): New functions.
(version_check): Rewrite using version_split and version_compare.
(process_option_list): Adjust regex.

ChangeLog
automake.in
tests/Makefile.am
tests/version5.test [new file with mode: 0755]

index f4ea9d7..060971e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2002-03-20  Alexandre Duret-Lutz  <duret_g@epita.fr>
+
+       Add support for two-dot versions.
+
+       * tests/version5.test: New file.
+       * tests/Makefile.am (TESTS): Add it.
+       * automake.in (version_split, version_compare): New functions.
+       (version_check): Rewrite using version_split and version_compare.
+       (process_option_list): Adjust regex.
+
 2002-03-18  Richard Boulton <richard@tartarus.org>
 
        Fix for PR automake/306:
index c705d3d..604941d 100755 (executable)
@@ -1375,65 +1375,90 @@ sub generate_makefile
 
 ################################################################
 
-# A helper which handles the logic of requiring a version number in
-# AUTOMAKE_OPTIONS.  Return 1 on error, 0 on success.
-sub version_check ($$$$)
+# A version is a string that looks like
+#   MAJOR.MINOR[.MICRO][ALPHA][-FORK]
+# where
+#   MAJOR, MINOR, and MICRO are digits, ALPHA is a character, and
+# FORK any alphanumeric word.
+# Usually, ALPHA is used to label alpha releases or intermediate snapshots,
+# FORK is used for CVS branches or patched releases, and MICRO is used
+# for bug fixes releases on the MAJOR.MINOR branch.
+#
+# For the purpose of ordering, 1.4 is the same as 1.4.0, but 1.4g is
+# the same as 1.4.99g.  The FORK identifier is ignored in the
+# ordering, except when it looks like -pMINOR[ALPHA]: some versions
+# were labelled like 1.4-p3a, this is the same as an alpha release
+# labelled 1.4.3a.  Yes it's horrible, but Automake did not support
+# two-dot versions in the past.
+
+# version_split (VERSION)
+# -----------------------
+# Split a version string into the corresponding (MAJOR, MINOR, MICRO,
+# ALPHA, FORK) tuple.  For instance "1.4g" would be split into
+# (1, 4, 99, 'g', '').
+# Return () on error.
+sub version_split ($)
 {
-    my ($rmajor, $rminor, $ralpha, $rfork) = ($1, $2, $3, $4);
-
-    prog_error ("version is incorrect: $VERSION")
-       if $VERSION !~ /(\d+)\.(\d+)([a-z]?)-?([A-Za-z0-9]+)?/;
-
-    my ($tmajor, $tminor, $talpha, $tfork) = ($1, $2, $3, $4);
+    my ($ver) = @_;
 
-    $rfork ||= '';
-    $tfork ||= '';
+    # Special case for versions like 1.4-p2a.
+    if ($ver =~ /^(\d+)\.(\d+)(?:-p(\d+)([a-z]+)?)$/)
+    {
+       return ($1, $2, $3, $4 || '', '');
+    }
+    # Common case.
+    elsif ($ver =~ /^(\d+)\.(\d+)(?:\.(\d+))?([a-z])?(?:-([A-Za-z0-9]+))?$/)
+    {
+       return ($1, $2, $3 || (defined $4 ? 99 : 0), $4 || '', $5 || '');
+    }
+    return ();
+}
 
-    my $rminorminor = 0;
-    my $tminorminor = 0;
+# version_compare (\@LVERSION, \@RVERSION)
+# ----------------------------------------
+# Return 1 if LVERSION > RVERSION,
+#       -1 if LVERSION < RVERSION,
+#        0 if LVERSION = RVERSION.
+sub version_compare (\@\@)
+{
+    my @l = @{$_[0]};
+    my @r = @{$_[1]};
 
-    # Some versions were labelled like `1.4-p3a'.  This is the same as
-    # an alpha release labelled `1.4.3a'.  However, a version like
-    # `1.4g' is the same as `1.4.99g'.  Yes, this sucks.  Moral:
-    # always listen to the users.
-    if ($rfork =~ /p([0-9]+)([a-z]?)/)
+    for my $i (0, 1, 2)
     {
-       $rminorminor = $1;
-       # `1.4a-p3b' never existed.  But we'll accept it anyway.
-       $ralpha = $ralpha || $2 || '';
-       $rfork = '';
+       return 1  if ($l[$i] > $r[$i]);
+       return -1 if ($l[$i] < $r[$i]);
     }
-    if ($tfork =~ /p([0-9]+)([a-z]?)/)
+    for my $i (3, 4)
     {
-       $tminorminor = $1;
-       # `1.4a-p3b' never existed.  But we'll accept it anyway.
-       $talpha = $talpha || $2 || '';
-       $tfork = '';
+       return 1  if ($l[$i] gt $r[$i]);
+       return -1 if ($l[$i] lt $r[$i]);
     }
+    return 0;
+}
+
+# Handles the logic of requiring a version number in AUTOMAKE_OPTIONS.
+# Return 0 if the required version is satisfied, 1 otherwise.
+sub version_check ($)
+{
+    my ($required) = @_;
+    my @version = version_split $VERSION;
+    my @required = version_split $required;
+
+    prog_error ("version is incorrect: $VERSION")
+       if $#version == -1;
 
-    $rminorminor = 99 if $ralpha ne '' && $rminorminor == 0;
-    $tminorminor = 99 if $talpha ne '' && $tminorminor == 0;
+    # This should not happen, because process_option_list and split_version
+    # use similar regexes.
+    prog_error ("required version is incorrect: $required")
+       if $#required == -1;
 
-    # 2.0 is better than 1.0.
-    # 1.2 is better than 1.1.
-    # 1.2a is better than 1.2.
     # If we require 3.4n-foo then we require something
     # >= 3.4n, with the `foo' fork identifier.
-    # The $r* variables are what the user specified.
-    # The $t* variables denote automake itself.
-    if ($rmajor > $tmajor
-       || ($rmajor == $tmajor && $rminor > $tminor)
-       || ($rminor == $tminor && $rminor == $tminor
-           && $rminorminor > $tminorminor)
-       || ($rminor == $tminor && $rminor == $tminor
-           && $rminorminor == $tminorminor
-           && $ralpha gt $talpha)
-       || ($rfork ne '' && $rfork ne $tfork))
-    {
-       return 1;
-    }
+    return 1
+       if ($required[4] ne '' && $required[4] ne $version[4]);
 
-    return 0;
+    return 0 >= version_compare @version, @required;
 }
 
 # $BOOL
@@ -1477,10 +1502,10 @@ sub process_option_list
        {
            $use_dependencies = 0;
        }
-       elsif (/(\d+)\.(\d+)([a-z]?)(-[A-Za-z0-9]+)?/)
+       elsif (/^\d+\.\d+(?:\.\d+)?[a-z]?(?:-[A-Za-z0-9]+)?$/)
        {
            # Got a version number.
-           if (version_check ($1, $2, $3, $4))
+           if (version_check $&)
            {
                if ($config)
                {
index 80cc7a7..b295919 100644 (file)
@@ -349,6 +349,7 @@ version.test \
 version2.test \
 version3.test \
 version4.test \
+version5.test \
 vpath.test \
 vtexi.test \
 vtexi2.test \
diff --git a/tests/version5.test b/tests/version5.test
new file mode 100755 (executable)
index 0000000..e6331c5
--- /dev/null
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+# Exercise &version_compare.
+
+. $srcdir/defs || exit 1
+
+set -e
+
+# FIXME: probably ought to let users override this like we do in `defs'.
+amfile=../../automake
+
+sed 1q $amfile >>automake_tmp
+cat << 'END' >> automake_tmp
+
+my $failed = 0;
+
+sub test_version_compare
+{
+  my ($left, $right, $result) = @_;
+  my @leftver = Automake::version_split ($left);
+  my @rightver = Automake::version_split ($right);
+  if ($#leftver == -1)
+  {
+     print "can't grok \"$left\"\n";
+     $failed = 1;
+     return;
+  }
+  if ($#rightver == -1)
+  {
+     print "can't grok \"$right\"\n";
+     $failed = 1;
+     return;
+  }
+  my $res = Automake::version_compare (\@leftver, \@rightver);
+  if ($res != $result)
+  {
+     print "version_compare (\"$left\", \"$right\") = $res! (not $result?)\n";
+     $failed = 1;
+  }
+}
+
+my @tests = (
+# basics
+  ['1.0', '2.0', -1],
+  ['2.0', '1.0', 1],
+  ['1.2', '1.2', 0],
+  ['1.1', '1.2', -1],
+  ['1.2', '1.1', 1],
+# alphas
+  ['1.4', '1.4g', -1],
+  ['1.4g', '1.5', -1],
+  ['1.4g', '1.4', 1],
+  ['1.5', '1.4g', 1],
+  ['1.4a', '1.4g', -1],
+  ['1.5a', '1.3g', 1],
+  ['1.6a', '1.6a', 0],
+# micros
+  ['1.5.1', '1.5', 1],
+  ['1.5.0', '1.5', 0],
+  ['1.5.4', '1.6.1', -1],
+# micros and alphas
+  ['1.5a', '1.5.1', 1],
+  ['1.5a', '1.5.1a', 1],
+  ['1.5a', '1.5.1f', 1],
+  ['1.5', '1.5.1a', -1],
+  ['1.5.1a', '1.5.1f', -1],
+# special exceptions
+  ['1.6-p5a', '1.6.5a', 0],
+  ['1.6', '1.6-p5a', -1],
+  ['1.6-p4b', '1.6-p5a', -1],
+  ['1.6-p4b', '1.6-foo', 1],
+  ['1.6-p4b', '1.6a-foo', -1]
+);
+
+test_version_compare (@{$_}) foreach @tests;
+
+exit $failed;
+END
+
+cat $amfile >>automake_tmp
+
+$PERL ./automake_tmp