Subject: Re: bug#72157: Current master (commit 4e6eff3597649782def55fc1dfeeec92cec4b15e) is unusable

From: Karl Berry <[email-masked]>
Date: Tue, 10 Sep 2024 16:46:06 -0600

Hi Dario - thanks for the report. I've made the changes below to try to
support the new four-part numeric version numbers, like 1.17.0.91 (which
is now the current dev version). 

All the tests pass for me, so I hope it's also usable. I won't be
surprised if something is still messed up somewhere, but hoping for the
best, so will provisionally close this.  --thanks, karl.

-----------------------------------------------------------------------------
automake: recognize all-numeric MAJ.MIN.MICROa.ALPHA versions better.

* HACKING: more doc on version numbers.
* configure.ac (AC_INIT): 1.17.0.91, since we want (I guess)
to retain odd numbers for development and even numbers for pretests.
* m4/amversion.m4 (AM_AUTOMAKE_VERSION): 1.17.0.91 (auto-update).
(AM_SET_CURRENT_AUTOMAKE_VERSION): likewise.
* lib/Automake/Options.pm (_process_option_list): recognize
four-part numeric versions as Automake options.
* lib/Automake/Version.pm (split): recognize four-part numeric
versions.
* t/pm/Version.pl (@tests, @bad_versions): update test
to check (not reject) four-part numeric versions.

diff --git a/HACKING b/HACKING
index f8d2fb043..cd28dbe82 100644
--- a/HACKING
+++ b/HACKING
@@ -529,16 +529,23 @@
 * Check NEWS; in particular, ensure that all the relevant differences
   with the last release are included.

-* Update the AC_INIT version number in configure.ac.  Leading up to a release,
-  say 1.17, pretests should be numbered from 1.16.90. Even numbers
-  (1.16.90, 1.16.92, ...) should be the pretest releases; odd numbers
-  (1.16.91, 1.16.93, ...) should be only the development versions.
-  Leading up to a release 1.17.1, we would have 1.17.0.90, etc.
-  Before 1.17 (July 2024), we used suffixed letters for pretests,
-  as is traditional, but deficient sorting algorithms did not like that.
+* Update the AC_INIT version number in configure.ac.  Leading up to a
+  minor release (x.y), say 1.17, pretests should be numbered from
+  1.16.90. Even numbers (1.16.90, 1.16.92, ...) should be pretest
+  releases; odd numbers (1.16.91, 1.16.93, ...) should be only
+  development versions.  Leading up to a micro release (x.y.z), say
+  1.17.1, we would have 1.17.0.91 for the initial post-release
+  development version, 1.17.0.92 for the first pretest, etc.
+  
+  Before 1.17 (July 2024), we used suffixed letters for pretests, as is
+  traditional, but deficient sorting algorithms did not like that. The
+  code in lib/Automake/Version.pm, along with the regexp in
+  lib/Automake/Options.pm, has to be updated to understand any change in
+  version number schemes. The test t/pm/Version[.pl] comprehensively
+  checks valid and invalid version strings.

 * If making a minor or major release (1.x), also update APIVERSION
-  in configure.ac.
+  in configure.ac. But not micro.

 * Create an announcement message with "make announcement".  Edit the
   generated 'announcement' file appropriately, in particularly filling
@@ -602,9 +609,10 @@
        make web-manual

     The ready-to-be-uploaded manuals (in several formats) will be left
-    in the 'doc/web-manuals' directory.
+    in the 'doc/web-manual' directory.

-  - Commit the updated manuals to web CVS:
+  - Commit the updated manuals to web CVS. This requires the "cvsu"
+    utility from the "cvsutils" package.
       make web-manual-update

     If your local username is different from your username at Savannah,
diff --git a/configure.ac b/configure.ac
index 54cd709d1..e4c7a126c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,7 +16,7 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.

 AC_PREREQ([2.69])
-AC_INIT([GNU Automake], [1.17.0.90], [[email-masked]])
+AC_INIT([GNU Automake], [1.17.0.91], [[email-masked]])

 AC_CONFIG_SRCDIR([bin/automake.in])
 AC_CONFIG_AUX_DIR([lib])
diff --git a/lib/Automake/Options.pm b/lib/Automake/Options.pm
index 98d3fd9e5..2dc7899f8 100644
--- a/lib/Automake/Options.pm
+++ b/lib/Automake/Options.pm
@@ -378,7 +378,8 @@ sub _process_option_list (\%@)
               $ret = 0;
             }
         }
-      elsif (/^\d+\.\d+(?:\.\d+)?[a-z]?(?:-[A-Za-z0-9]+)?$/)
+      elsif (/^\d+\.\d+(?:\.\d+)?(?:\.\d+)?[a-z]?(?:-[A-Za-z0-9]+)?$/)
+            # MAJOR.MINOR (all digits) are required, all else optional.
         {
           # Got a version number.
           if (Automake::Version::check ($VERSION, $&))
diff --git a/lib/Automake/Version.pm b/lib/Automake/Version.pm
index daba71ffe..7da0560c9 100644
--- a/lib/Automake/Version.pm
+++ b/lib/Automake/Version.pm
@@ -39,12 +39,12 @@ as they are used in Automake.

 A version is a string that looks like
 C<MAJOR.MINOR[.MICRO][ALPHA][-FORK]> where C<MAJOR>, C<MINOR>, and
-C<MICRO> are digits, C<ALPHA> is a character, and C<FORK> any
-alphanumeric word.
+C<MICRO> are digits, C<ALPHA> is either a character or another C<.NUM>,
+and C<FORK> any alphanumeric word.

 Usually, C<ALPHA> is used to label alpha releases or intermediate
 snapshots, C<FORK> is used for git branches or patched releases, and
-C<MICRO> is used for bug fixes releases on the C<MAJOR.MINOR> branch.
+C<MICRO> is used for bug fix releases on the C<MAJOR.MINOR> branch.

 For the purpose of ordering, C<1.4> is the same as C<1.4.0>, but
 C<1.4g> is the same as C<1.4.99g>.  The C<FORK> identifier is ignored
@@ -53,6 +53,18 @@ versions were labeled like C<1.4-p3a>, this is the same as an alpha
 release labeled C<1.4.3a>.  Yes, it's horrible, but Automake did not
 support two-dot versions in the past.

+In 2024, Automake switched from using letter suffixes like C<1.4g> for
+pretests to the C<.90> form (used by nearly all other GNU packages),
+e.g., C<1.16.90> was a pretest leading up to C<1.17>. Thus we also have
+to support four-part version numbers, since test releases leading up to
+C<1.17.1> have to be C<1.17.0.92>, etc., to follow the pattern. In this
+case, all four version parts have to be present and all-numeric; the
+C<-FORK> is still optional (but entirely ignored).
+
+Aggravatingly, version number syntax is also recognized in
+lib/Automake/Options.pm, since bare version numbers are also valid
+Automake options, as tested in C<version6[.sh]>.
+
 =head2 FUNCTIONS

 =over 4
@@ -61,7 +73,8 @@ support two-dot versions in the past.

 Split the string C<$version> into the corresponding C<(MAJOR, MINOR,
 MICRO, ALPHA, FORK)> tuple.  For instance C<'1.4g'> would be split
-into C<(1, 4, 99, 'g', '')>.  Return C<()> on error.
+into C<(1, 4, 99, 'g', '')> and C<'1.17.0.91'> into C<1, 17, 0, 91, ''>.
+Return C<()> on error.

 =cut

@@ -69,16 +82,22 @@ sub split ($)
 {
   my ($ver) = @_;

-  # Special case for versions like 1.4-p2a.
+  # Recognize MAJOR.MINOR, plus special case for versions like 1.4-p2a.
   if ($ver =~ /^(\d+)\.(\d+)(?:-p(\d+)([a-z]+)?)$/)
   {
     return ($1, $2, $3, $4 || '', '');
   }
-  # Common case.
+  # Recognize MAJOR.MINOR and MAJOR.MINOR.MICRO, as well as
+  # the pre-2024 case with possible letters in the alpha part.
   elsif ($ver =~ /^(\d+)\.(\d+)(?:\.(\d+))?([a-z])?(?:-([A-Za-z0-9]+))?$/)
   {
     return ($1, $2, $3 || (defined $4 ? 99 : 0), $4 || '', $5 || '');
   }
+  # 2024ff. case with all numbers: MAJOR.MINOR.MICRO.ALPHA[-FORK].
+  elsif ($ver =~ /^(\d+)\.(\d+).(\d+)\.(\d+)(?:-([A-Za-z0-9]+))?$/)
+  {
+    return ($1, $2, $3, $4, $5 || '');
+  }
   return ();
 }

diff --git a/m4/amversion.m4 b/m4/amversion.m4
index eaf900ea7..5a5ec0868 100644
--- a/m4/amversion.m4
+++ b/m4/amversion.m4
@@ -15,7 +15,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
 [am__api_version='1.17'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.17.0.90], [],
+m4_if([$1], [1.17.0.91], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])

@@ -31,7 +31,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.17.0.90])dnl
+[AM_AUTOMAKE_VERSION([1.17.0.91])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
diff --git a/t/pm/Version.pl b/t/pm/Version.pl
index b33d74b94..1312eb258 100644
--- a/t/pm/Version.pl
+++ b/t/pm/Version.pl
@@ -92,6 +92,11 @@ my @tests = (
   ['1.5.1a', '1.5.1f', -1],
   ['1.5.1f', '1.5.1a', 1],
   ['1.5.1f', '1.5.1f', 0],
+# with four-part numeric versions, starting 2024
+  ['1.17.0.91', '1.17.0.91', 0],
+  ['1.17.0.91', '1.17.0.92', -1],
+  ['1.17.0.91', '1.17.1', -1],
+  ['1.17.0.91', '1.17', 1],
 # special exceptions
   ['1.6-p5a', '1.6.5a', 0],
   ['1.6', '1.6-p5a', -1],
@@ -103,7 +108,7 @@ my @tests = (
 );

 my @bad_versions = (
-  '', 'a', '1', '1a', '1.2.3.4', '-1.2'
+  '', 'a', '1', '1a', '-1.2'
 );

 test_version_compare (@{$_}) foreach @tests;

compile finished at Tue Sep 10 15:44:43 2024