Hi Simon,

After fixing the --help output, I'm changing the 'bootstrap' logic
to follow this documentation. Two patches:
* 0001 simplifies the logic by removing fallback code for git versions < 1.6.4.
  Version 1.6.4 was released in 2009, that is, 15 years ago. When encountering
  such an old version, now an error message is output.
* 0002 implements prepare_GNULIB_SRCDIR as documented. The real change is that
  instead of having a single occurrence of
    git checkout "$GNULIB_REVISION"
  at the end, we have one in each possible case. Which allows to tailor
  when to invoke it.

> Bug #1: it seems GNULIB_REVISION in bootstrap.conf has no effect, and
> this code is the reason (quoting bootstrap-funclib.sh):
> 
>   # XXX Should this be done if $use_git is false?
>   if test -d "$GNULIB_SRCDIR"/.git && test -n "$GNULIB_REVISION" \
>      && ! git_modules_config submodule.gnulib.url >/dev/null; then
>     (cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || cleanup_gnulib
>   fi
> 
> The reason is that the tarball has .gitmodules looking like this:
> 
> [submodule "gnulib"]
>       path = gnulib
>       url = https://git.savannah.gnu.org/git/gnulib.git
> 
> Which trigger the '! git_modules_config submodules.gnulib.url'.

This is fixed as part of 0002.

Bruno
>From ac8c4111ce570e140c819f231493fa573d3b0904 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 14 Apr 2024 00:08:50 +0200
Subject: [PATCH 1/2] bootstrap: Simplify git submodule initialization.

* top/bootstrap-funclib.sh (prepare_GNULIB_SRCDIR): Err out if git is
older than version 1.6.4. Remove fallback code for older versions.
* build-aux/bootstrap: Regenerated.
---
 ChangeLog                |  7 +++++++
 build-aux/bootstrap      | 27 ++++++++-------------------
 top/bootstrap-funclib.sh | 27 ++++++++-------------------
 3 files changed, 23 insertions(+), 38 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c9349f22ac..a6878807ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-04-13  Bruno Haible  <br...@clisp.org>
+
+	bootstrap: Simplify git submodule initialization.
+	* top/bootstrap-funclib.sh (prepare_GNULIB_SRCDIR): Err out if git is
+	older than version 1.6.4. Remove fallback code for older versions.
+	* build-aux/bootstrap: Regenerated.
+
 2024-04-13  Collin Funk  <collin.fu...@gmail.com>
 
 	Improve 'git diff' of Python files.
diff --git a/build-aux/bootstrap b/build-aux/bootstrap
index ef9161d75e..70e567b2ad 100755
--- a/build-aux/bootstrap
+++ b/build-aux/bootstrap
@@ -500,6 +500,12 @@ prepare_GNULIB_SRCDIR ()
       || die "Error: --gnulib-srcdir or \$GNULIB_SRCDIR is specified," \
              "but does not contain gnulib-tool"
   elif $use_git; then
+    if git submodule -h | grep -- --reference > /dev/null; then
+      :
+    else
+      die "git version is too old, git >= 1.6.4 is required"
+    fi
+
     gnulib_path=$(git_modules_config submodule.gnulib.path)
     test -z "$gnulib_path" && gnulib_path=gnulib
 
@@ -510,25 +516,8 @@ prepare_GNULIB_SRCDIR ()
        && git_modules_config submodule.gnulib.url >/dev/null; then
       # Use GNULIB_REFDIR as a reference.
       echo "$0: getting gnulib files..."
-      if git submodule -h|grep -- --reference > /dev/null; then
-        # Prefer the one-liner available in git 1.6.4 or newer.
-        git submodule update --init --reference "$GNULIB_REFDIR" \
-          "$gnulib_path" || exit $?
-      else
-        # This fallback allows at least git 1.5.5.
-        if test -f "$gnulib_path"/gnulib-tool; then
-          # Since file already exists, assume submodule init already complete.
-          git submodule update -- "$gnulib_path" || exit $?
-        else
-          # Older git can't clone into an empty directory.
-          rmdir "$gnulib_path" 2>/dev/null
-          git clone --reference "$GNULIB_REFDIR" \
-            "$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
-            && git submodule init -- "$gnulib_path" \
-            && git submodule update -- "$gnulib_path" \
-            || exit $?
-        fi
-      fi
+      git submodule update --init --reference "$GNULIB_REFDIR" \
+        "$gnulib_path" || exit $?
     else
       # GNULIB_REFDIR is not set or not usable. Ignore it.
       if git_modules_config submodule.gnulib.url >/dev/null; then
diff --git a/top/bootstrap-funclib.sh b/top/bootstrap-funclib.sh
index 64896ff4e5..e0d3ab900d 100644
--- a/top/bootstrap-funclib.sh
+++ b/top/bootstrap-funclib.sh
@@ -463,6 +463,12 @@ prepare_GNULIB_SRCDIR ()
       || die "Error: --gnulib-srcdir or \$GNULIB_SRCDIR is specified," \
              "but does not contain gnulib-tool"
   elif $use_git; then
+    if git submodule -h | grep -- --reference > /dev/null; then
+      :
+    else
+      die "git version is too old, git >= 1.6.4 is required"
+    fi
+
     gnulib_path=$(git_modules_config submodule.gnulib.path)
     test -z "$gnulib_path" && gnulib_path=gnulib
 
@@ -473,25 +479,8 @@ prepare_GNULIB_SRCDIR ()
        && git_modules_config submodule.gnulib.url >/dev/null; then
       # Use GNULIB_REFDIR as a reference.
       echo "$0: getting gnulib files..."
-      if git submodule -h|grep -- --reference > /dev/null; then
-        # Prefer the one-liner available in git 1.6.4 or newer.
-        git submodule update --init --reference "$GNULIB_REFDIR" \
-          "$gnulib_path" || exit $?
-      else
-        # This fallback allows at least git 1.5.5.
-        if test -f "$gnulib_path"/gnulib-tool; then
-          # Since file already exists, assume submodule init already complete.
-          git submodule update -- "$gnulib_path" || exit $?
-        else
-          # Older git can't clone into an empty directory.
-          rmdir "$gnulib_path" 2>/dev/null
-          git clone --reference "$GNULIB_REFDIR" \
-            "$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
-            && git submodule init -- "$gnulib_path" \
-            && git submodule update -- "$gnulib_path" \
-            || exit $?
-        fi
-      fi
+      git submodule update --init --reference "$GNULIB_REFDIR" \
+        "$gnulib_path" || exit $?
     else
       # GNULIB_REFDIR is not set or not usable. Ignore it.
       if git_modules_config submodule.gnulib.url >/dev/null; then
-- 
2.34.1

>From d84255c1285785c3d53aad17c05b83291846be06 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 14 Apr 2024 01:38:42 +0200
Subject: [PATCH 2/2] bootstrap: Implement phase 1 as documented in the --help
 output.

Reported by Simon Josefsson as bug #1 in
<https://lists.gnu.org/archive/html/bug-gnulib/2024-04/msg00152.html>.

* top/bootstrap: Correct indentation.
* top/bootstrap-funclib.sh (prepare_GNULIB_SRCDIR): Implement as
documented:
If GNULIB_SRCDIR and GNULIB_REVISION are set and there is a 'gnulib'
submodule, checkout the revision GNULIB_REVISION.
If GNULIB_SRCDIR and GNULIB_REVISION are set and --no-git is specified,
don't checkout the revision GNULIB_REVISION.
---
 ChangeLog                | 13 ++++++
 build-aux/bootstrap      | 90 ++++++++++++++++++++++------------------
 top/bootstrap            |  8 ++--
 top/bootstrap-funclib.sh | 82 +++++++++++++++++++-----------------
 4 files changed, 111 insertions(+), 82 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a6878807ba..f57cb59b81 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2024-04-13  Bruno Haible  <br...@clisp.org>
+
+	bootstrap: Implement phase 1 as documented in the --help output.
+	Reported by Simon Josefsson as bug #1 in
+	<https://lists.gnu.org/archive/html/bug-gnulib/2024-04/msg00152.html>.
+	* top/bootstrap: Correct indentation.
+	* top/bootstrap-funclib.sh (prepare_GNULIB_SRCDIR): Implement as
+	documented:
+	If GNULIB_SRCDIR and GNULIB_REVISION are set and there is a 'gnulib'
+	submodule, checkout the revision GNULIB_REVISION.
+	If GNULIB_SRCDIR and GNULIB_REVISION are set and --no-git is specified,
+	don't checkout the revision GNULIB_REVISION.
+
 2024-04-13  Bruno Haible  <br...@clisp.org>
 
 	bootstrap: Simplify git submodule initialization.
diff --git a/build-aux/bootstrap b/build-aux/bootstrap
index 70e567b2ad..20913180a6 100755
--- a/build-aux/bootstrap
+++ b/build-aux/bootstrap
@@ -478,10 +478,9 @@ find_tool ()
 # --------------------- Preparing GNULIB_SRCDIR for use. ---------------------
 # This is part of autopull.sh, but bootstrap needs it too, for self-upgrading.
 
+# cleanup_gnulib fails, removing the directory $gnulib_path first.
 cleanup_gnulib() {
   status=$?
-  # XXX It's a bad idea to erase the submodule directory if it contains local
-  #     modifications.
   rm -fr "$gnulib_path"
   exit $status
 }
@@ -499,37 +498,44 @@ prepare_GNULIB_SRCDIR ()
     test -f "$GNULIB_SRCDIR/gnulib-tool" \
       || die "Error: --gnulib-srcdir or \$GNULIB_SRCDIR is specified," \
              "but does not contain gnulib-tool"
-  elif $use_git; then
+    if test -n "$GNULIB_REVISION" && $use_git; then
+      (cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || exit $?
+    fi
+  else
+    if ! $use_git; then
+      die "Error: --no-git is specified," \
+          "but neither --gnulib-srcdir nor \$GNULIB_SRCDIR is specified"
+    fi
     if git submodule -h | grep -- --reference > /dev/null; then
       :
     else
       die "git version is too old, git >= 1.6.4 is required"
     fi
-
     gnulib_path=$(git_modules_config submodule.gnulib.path)
-    test -z "$gnulib_path" && gnulib_path=gnulib
-
-    # Get gnulib files.  Populate $gnulib_path, possibly updating a
-    # submodule, for use in the rest of the script.
-
-    if test -n "$GNULIB_REFDIR" && test -d "$GNULIB_REFDIR"/.git \
-       && git_modules_config submodule.gnulib.url >/dev/null; then
-      # Use GNULIB_REFDIR as a reference.
-      echo "$0: getting gnulib files..."
-      git submodule update --init --reference "$GNULIB_REFDIR" \
-        "$gnulib_path" || exit $?
-    else
-      # GNULIB_REFDIR is not set or not usable. Ignore it.
-      if git_modules_config submodule.gnulib.url >/dev/null; then
+    if test -n "$gnulib_path"; then
+      # A submodule 'gnulib' is configured.
+      # Get gnulib files.  Populate $gnulib_path, updating the submodule.
+      if test -n "$GNULIB_REFDIR" && test -d "$GNULIB_REFDIR"/.git; then
+        # Use GNULIB_REFDIR as a reference.
         echo "$0: getting gnulib files..."
-        git submodule init -- "$gnulib_path" || exit $?
-        git submodule update -- "$gnulib_path" || exit $?
-
-      elif [ ! -d "$gnulib_path" ]; then
+        git submodule update --init --reference "$GNULIB_REFDIR" "$gnulib_path" \
+          || exit $?
+      else
+        # GNULIB_REFDIR is not set or not usable. Ignore it.
+        if git_modules_config submodule.gnulib.url >/dev/null; then
+          echo "$0: getting gnulib files..."
+          git submodule init -- "$gnulib_path" || exit $?
+          git submodule update -- "$gnulib_path" || exit $?
+        else
+          die "Error: submodule 'gnulib' has no configured url"
+        fi
+      fi
+    else
+      gnulib_path='gnulib'
+      if test ! -d "$gnulib_path"; then
+        # The subdirectory 'gnulib' does not yet exist. Clone into it.
         echo "$0: getting gnulib files..."
-
         trap cleanup_gnulib HUP INT PIPE TERM
-
         shallow=
         if test -z "$GNULIB_REVISION"; then
           if git clone -h 2>&1 | grep -- --depth > /dev/null; then
@@ -551,30 +557,32 @@ prepare_GNULIB_SRCDIR ()
           # is without fetching all commits. So fall back to fetching all
           # commits.
           git -C "$gnulib_path" init
-          git -C "$gnulib_path" remote add origin \
-              ${GNULIB_URL:-$default_gnulib_url}
+          git -C "$gnulib_path" remote add origin ${GNULIB_URL:-$default_gnulib_url}
           git -C "$gnulib_path" fetch $shallow origin "$GNULIB_REVISION" \
             || git -C "$gnulib_path" fetch origin \
             || cleanup_gnulib
           git -C "$gnulib_path" reset --hard FETCH_HEAD
+          (cd "$gnulib_path" && git checkout "$GNULIB_REVISION") || cleanup_gnulib
         fi
-
         trap - HUP INT PIPE TERM
+      else
+        # The subdirectory 'gnulib' already exists.
+        if test -n "$GNULIB_REVISION"; then
+          if test -d "$gnulib_path/.git"; then
+            (cd "$gnulib_path" && git checkout "$GNULIB_REVISION") || exit 1
+          else
+            die "Error: GNULIB_REVISION is specified in bootstrap.conf," \
+                "but '$gnulib_path' contains no git history"
+          fi
+        fi
       fi
     fi
-    GNULIB_SRCDIR=$gnulib_path
-    # Verify that the submodule contains a gnulib checkout.
+    # Verify that $gnulib_path contains a gnulib checkout.
     test -f "$gnulib_path/gnulib-tool" \
-      || die "Error: $gnulib_path is supposed to contain a gnulib checkout," \
+      || die "Error: '$gnulib_path' is supposed to contain a gnulib checkout," \
              "but does not contain gnulib-tool"
+    GNULIB_SRCDIR=$gnulib_path
   fi
-
-  # XXX Should this be done if $use_git is false?
-  if test -d "$GNULIB_SRCDIR"/.git && test -n "$GNULIB_REVISION" \
-     && ! git_modules_config submodule.gnulib.url >/dev/null; then
-    (cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || cleanup_gnulib
-  fi
-
   # $GNULIB_SRCDIR now points to the version of gnulib to use, and
   # we no longer need to use git or $gnulib_path below here.
 }
@@ -1523,10 +1531,10 @@ if $pull && { $use_git || test -z "$SKIP_PO"; }; then
 fi
 
 if $gen; then
- autogen \
-    `if $copy; then echo ' --copy'; fi` \
-    `if test -z "$checkout_only_file"; then echo ' --force'; fi` \
-  || die "could not generate auxiliary files"
+  autogen \
+      `if $copy; then echo ' --copy'; fi` \
+      `if test -z "$checkout_only_file"; then echo ' --force'; fi` \
+    || die "could not generate auxiliary files"
 fi
 
 # ----------------------------------------------------------------------------
diff --git a/top/bootstrap b/top/bootstrap
index b640bae83d..4beae0e912 100755
--- a/top/bootstrap
+++ b/top/bootstrap
@@ -228,10 +228,10 @@ if $pull && { $use_git || test -z "$SKIP_PO"; }; then
 fi
 
 if $gen; then
- autogen \
-    `if $copy; then echo ' --copy'; fi` \
-    `if test -z "$checkout_only_file"; then echo ' --force'; fi` \
-  || die "could not generate auxiliary files"
+  autogen \
+      `if $copy; then echo ' --copy'; fi` \
+      `if test -z "$checkout_only_file"; then echo ' --force'; fi` \
+    || die "could not generate auxiliary files"
 fi
 
 # ----------------------------------------------------------------------------
diff --git a/top/bootstrap-funclib.sh b/top/bootstrap-funclib.sh
index e0d3ab900d..7511d62d9b 100644
--- a/top/bootstrap-funclib.sh
+++ b/top/bootstrap-funclib.sh
@@ -441,10 +441,9 @@ find_tool ()
 # --------------------- Preparing GNULIB_SRCDIR for use. ---------------------
 # This is part of autopull.sh, but bootstrap needs it too, for self-upgrading.
 
+# cleanup_gnulib fails, removing the directory $gnulib_path first.
 cleanup_gnulib() {
   status=$?
-  # XXX It's a bad idea to erase the submodule directory if it contains local
-  #     modifications.
   rm -fr "$gnulib_path"
   exit $status
 }
@@ -462,37 +461,44 @@ prepare_GNULIB_SRCDIR ()
     test -f "$GNULIB_SRCDIR/gnulib-tool" \
       || die "Error: --gnulib-srcdir or \$GNULIB_SRCDIR is specified," \
              "but does not contain gnulib-tool"
-  elif $use_git; then
+    if test -n "$GNULIB_REVISION" && $use_git; then
+      (cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || exit $?
+    fi
+  else
+    if ! $use_git; then
+      die "Error: --no-git is specified," \
+          "but neither --gnulib-srcdir nor \$GNULIB_SRCDIR is specified"
+    fi
     if git submodule -h | grep -- --reference > /dev/null; then
       :
     else
       die "git version is too old, git >= 1.6.4 is required"
     fi
-
     gnulib_path=$(git_modules_config submodule.gnulib.path)
-    test -z "$gnulib_path" && gnulib_path=gnulib
-
-    # Get gnulib files.  Populate $gnulib_path, possibly updating a
-    # submodule, for use in the rest of the script.
-
-    if test -n "$GNULIB_REFDIR" && test -d "$GNULIB_REFDIR"/.git \
-       && git_modules_config submodule.gnulib.url >/dev/null; then
-      # Use GNULIB_REFDIR as a reference.
-      echo "$0: getting gnulib files..."
-      git submodule update --init --reference "$GNULIB_REFDIR" \
-        "$gnulib_path" || exit $?
-    else
-      # GNULIB_REFDIR is not set or not usable. Ignore it.
-      if git_modules_config submodule.gnulib.url >/dev/null; then
+    if test -n "$gnulib_path"; then
+      # A submodule 'gnulib' is configured.
+      # Get gnulib files.  Populate $gnulib_path, updating the submodule.
+      if test -n "$GNULIB_REFDIR" && test -d "$GNULIB_REFDIR"/.git; then
+        # Use GNULIB_REFDIR as a reference.
         echo "$0: getting gnulib files..."
-        git submodule init -- "$gnulib_path" || exit $?
-        git submodule update -- "$gnulib_path" || exit $?
-
-      elif [ ! -d "$gnulib_path" ]; then
+        git submodule update --init --reference "$GNULIB_REFDIR" "$gnulib_path" \
+          || exit $?
+      else
+        # GNULIB_REFDIR is not set or not usable. Ignore it.
+        if git_modules_config submodule.gnulib.url >/dev/null; then
+          echo "$0: getting gnulib files..."
+          git submodule init -- "$gnulib_path" || exit $?
+          git submodule update -- "$gnulib_path" || exit $?
+        else
+          die "Error: submodule 'gnulib' has no configured url"
+        fi
+      fi
+    else
+      gnulib_path='gnulib'
+      if test ! -d "$gnulib_path"; then
+        # The subdirectory 'gnulib' does not yet exist. Clone into it.
         echo "$0: getting gnulib files..."
-
         trap cleanup_gnulib HUP INT PIPE TERM
-
         shallow=
         if test -z "$GNULIB_REVISION"; then
           if git clone -h 2>&1 | grep -- --depth > /dev/null; then
@@ -514,30 +520,32 @@ prepare_GNULIB_SRCDIR ()
           # is without fetching all commits. So fall back to fetching all
           # commits.
           git -C "$gnulib_path" init
-          git -C "$gnulib_path" remote add origin \
-              ${GNULIB_URL:-$default_gnulib_url}
+          git -C "$gnulib_path" remote add origin ${GNULIB_URL:-$default_gnulib_url}
           git -C "$gnulib_path" fetch $shallow origin "$GNULIB_REVISION" \
             || git -C "$gnulib_path" fetch origin \
             || cleanup_gnulib
           git -C "$gnulib_path" reset --hard FETCH_HEAD
+          (cd "$gnulib_path" && git checkout "$GNULIB_REVISION") || cleanup_gnulib
         fi
-
         trap - HUP INT PIPE TERM
+      else
+        # The subdirectory 'gnulib' already exists.
+        if test -n "$GNULIB_REVISION"; then
+          if test -d "$gnulib_path/.git"; then
+            (cd "$gnulib_path" && git checkout "$GNULIB_REVISION") || exit 1
+          else
+            die "Error: GNULIB_REVISION is specified in bootstrap.conf," \
+                "but '$gnulib_path' contains no git history"
+          fi
+        fi
       fi
     fi
-    GNULIB_SRCDIR=$gnulib_path
-    # Verify that the submodule contains a gnulib checkout.
+    # Verify that $gnulib_path contains a gnulib checkout.
     test -f "$gnulib_path/gnulib-tool" \
-      || die "Error: $gnulib_path is supposed to contain a gnulib checkout," \
+      || die "Error: '$gnulib_path' is supposed to contain a gnulib checkout," \
              "but does not contain gnulib-tool"
+    GNULIB_SRCDIR=$gnulib_path
   fi
-
-  # XXX Should this be done if $use_git is false?
-  if test -d "$GNULIB_SRCDIR"/.git && test -n "$GNULIB_REVISION" \
-     && ! git_modules_config submodule.gnulib.url >/dev/null; then
-    (cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || cleanup_gnulib
-  fi
-
   # $GNULIB_SRCDIR now points to the version of gnulib to use, and
   # we no longer need to use git or $gnulib_path below here.
 }
-- 
2.34.1

Reply via email to