From 98dbe44fa71e3e30d8df7111c3b96389ace53616 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Sun, 11 Jan 2026 22:08:13 -0800 Subject: [PATCH 01/12] Add `git-clone-or-pull` script --- README.md | 5 +++++ git-clone-or-pull | 50 +++++++++++++++++++++++++++++++++++++++++++++++ git-clone-related | 7 ++++--- 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100755 git-clone-or-pull diff --git a/README.md b/README.md index 644db7c..9edbab5 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,11 @@ A script for use as a git mergetool; runs Emacs ediff as the mergetool. Lists all the authors of commits in a git repository. [Documentation](git-authors) at top of file. +### git-clone-or-pull + +Either clones a repository, or pulls it if it is already cloned. +[Documentation](git-clone-or-pull) at top of file. + ### git-clone-related Clones a repository related to the one where this script is called, trying diff --git a/git-clone-or-pull b/git-clone-or-pull new file mode 100755 index 0000000..6dda824 --- /dev/null +++ b/git-clone-or-pull @@ -0,0 +1,50 @@ +#!/bin/sh + +# git-clone-or-pull: clone a GitHub repository, or pull it if already cloned. +# +# Usage: git-clone-or-pull ORG REPO [DESTINATION_PARENT] [GIT_CLONE_ARGS] +# ORG is the GitHub organization +# REPO_NAME is the repository name (without the organization) +# DESTINATION_PARENT is the directory that contains the clone directory. +# GIT_CLONE_ARGS is extra arguments to git clone. It defaults to +# "-q --single-branch --depth 1" (without the quotes). +# It is not used if the destination already exists. + +if [ "$#" -lt 2 ]; then + echo "Usage: $0 ORG REPO [DESTINATION_PARENT] [GIT_CLONE_ARGS...]" >&2 + exit 1 +fi + +ORG=$1 +shift +REPO_NAME=$2 +shift +if [ "$#" -ne 0 ] && ! beginswith "-" "$1"; then + DESTINATION_PARENT=$1 + shift + if [ ! -d "${DESTINATION_PARENT}" ]; then + mkdir -p "${DESTINATION_PARENT}" + exit 1 + fi +else + DESTINATION_PARENT=. +fi +if [ "$#" -eq 0 ]; then + set -- -q --single-branch --depth 1 +fi + +REPO_URL="https://github.com/${ORG}/${REPO_NAME}.git" +DESTINATION="${DESTINATION_PARENT}/${REPO_NAME}" + +# Try twice in case of network lossage. 60 seconds is not enough to clone a branch of the JDK. +if test -d "${DESTINATION}"; then + (cd "${DESTINATION}" && (timeout 180 git pull -q || (sleep 1m && (timeout 180 git pull || true)))) +else + mkdir -p "${DESTINATION_PARENT} + if ! timeout 180 git clone -q --depth=1 "${REPO_URL}" "${DESTINATION}"; then + sleep 1m + timeout 180 git clone --depth=1 "${REPO_URL}" "${DESTINATION} + fi +fi + +echo "$0: ${REPO_NAME} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" diff --git a/git-clone-related b/git-clone-related index 7c06bbb..1cef876 100755 --- a/git-clone-related +++ b/git-clone-related @@ -57,7 +57,7 @@ if [ "$1" = "--upstream-branch" ]; then fi if [ "$#" -lt 2 ]; then - echo "Usage: $0 UPSTREAM_ORG REPO [DESTINATION] [GIT_CLONE_ARGS...]" >&2 + echo "Usage: $0 UPSTREAM_ORG REPO_NAME [DESTINATION] [GIT_CLONE_ARGS...]" >&2 exit 1 fi @@ -155,7 +155,7 @@ else REPO_BRANCH=$("${SCRIPT_DIR}"/git-find-branch "${REPO_URL}" "${CI_BRANCH_NAME}" ${FALLBACK_BRANCH:+"$FALLBACK_BRANCH"}) fi echo "About to run: git clone -q -b ${REPO_BRANCH} $* ${REPO_URL} ${DESTINATION}" - # Try twice in case of network lossage. 60 seconds is not enough for a branch of the JDK. + # Try twice in case of network lossage. 60 seconds is not enough to clone a branch of the JDK. timeout 180 git clone -q -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}" \ || { echo "Retrying 'git clone ... ${REPO_URL} ${DESTINATION}' after timeout" \ && rm -rf "${DESTINATION}" \ @@ -166,4 +166,5 @@ else exit 2 }; }; } fi -echo "git-clone-related: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" + +echo "$0: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" From 8af23d4cafd8a6be3d1dded8bef02e02031b26d6 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 12 Jan 2026 05:35:51 -0800 Subject: [PATCH 02/12] Add debugging diagnostics --- .../test-git-clone-related.sh | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/git-clone-related-test/test-git-clone-related.sh b/tests/git-clone-related-test/test-git-clone-related.sh index a80558b..4581133 100755 --- a/tests/git-clone-related-test/test-git-clone-related.sh +++ b/tests/git-clone-related-test/test-git-clone-related.sh @@ -15,6 +15,9 @@ ARGS=$3 GOAL_REPO=$4 GOAL_BRANCH=$5 +DEBUG= +DEBUG=--debug + set -o errexit -o nounset # set -o pipefail # Display commands and their arguments as they are executed. @@ -24,8 +27,8 @@ set -o errexit -o nounset USER=${USER:-git-clone-related} PLUME_SCRIPTS=$(cd ../../ && pwd -P) startdir=$(mktemp -d 2> /dev/null || mktemp -d -t 'startdir') -goaldir=$(mktemp -d 2> /dev/null || mktemp -d -t 'goaldir') -rm -rf "$startdir" "$goaldir" +resultdir=$(mktemp -d 2> /dev/null || mktemp -d -t 'resultdir') +rm -rf "$startdir" "$resultdir" git clone --branch "$START_BRANCH" "$START_REPO" "$startdir" -q --single-branch --depth 1 # This test might itself be running under CI, so unset the variables that @@ -35,21 +38,25 @@ unset BUILD_SOURCEBRANCH unset TRAVIS unset CIRCLE_COMPARE_URL unset GITHUB_HEAD_REF -# shellcheck disable=SC2086 # $ARGS should not be quoted -(cd "$startdir" && "${PLUME_SCRIPTS}"/git-clone-related $ARGS "$goaldir") -clonedrepo=$(git -C "$goaldir" config --get remote.origin.url) + +# shellcheck disable=SC2086 # $DEBUG and $ARGS should not be quoted +(cd "$startdir" && "${PLUME_SCRIPTS}"/git-clone-related $DEBUG $ARGS "$resultdir") + +clonedrepo=$(git -C "$resultdir" config --get remote.origin.url) # git 2.22 and later has `git branch --show-current`; CircleCI doesn't have that version yet. -clonedbranch=$(git -C "$goaldir" rev-parse --abbrev-ref HEAD) +clonedbranch=$(git -C "$resultdir" rev-parse --abbrev-ref HEAD) -rm -rf "$startdir" "$goaldir" +if [ -z "$DEBUG" ]; then + rm -rf "$startdir" "$resultdir" +fi if [ "$clonedrepo" != "$GOAL_REPO" ]; then - echo "test-git-clone-related.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\"" - echo "expected repo $GOAL_REPO, got: $clonedrepo" + echo "error: test-git-clone-related.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\"" + echo "error: expected repo $GOAL_REPO, got: $clonedrepo" exit 2 fi if [ "$clonedbranch" != "$GOAL_BRANCH" ]; then - echo "test-git-clone-related.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\"" - echo "expected branch $GOAL_BRANCH, got: $clonedbranch" + echo "error: test-git-clone-related.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\"" + echo "error: expected branch $GOAL_BRANCH, got: $clonedbranch" exit 2 fi From 62b1080cf267a9eb96c3e1768f1a5e9c027ef1f0 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 12 Jan 2026 11:13:11 -0800 Subject: [PATCH 03/12] Don't show path to script --- git-clone-related | 2 +- git-find-fork | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/git-clone-related b/git-clone-related index 7c06bbb..680eff4 100755 --- a/git-clone-related +++ b/git-clone-related @@ -57,7 +57,7 @@ if [ "$1" = "--upstream-branch" ]; then fi if [ "$#" -lt 2 ]; then - echo "Usage: $0 UPSTREAM_ORG REPO [DESTINATION] [GIT_CLONE_ARGS...]" >&2 + echo "Usage: $(basename -- "$0") UPSTREAM_ORG REPO [DESTINATION] [GIT_CLONE_ARGS...]" >&2 exit 1 fi diff --git a/git-find-fork b/git-find-fork index e7f0cc5..09d5e3a 100755 --- a/git-find-fork +++ b/git-find-fork @@ -10,9 +10,9 @@ # Often, you can use the `git-clone-related` script instead of this one. if [ "$#" -ne 3 ]; then - script=$(basename -- "$0") - >&2 echo "Error: $script requires 3 arguments, got $#" - >&2 echo "Usage: $script ORG UPSTREAM_ORG REPONAME" + SCRIPT_NAME=$(basename -- "$0") + >&2 echo "Error: ${SCRIPT_NAME} requires 3 arguments, got $#" + >&2 echo "Usage: ${SCRIPT_NAME} ORG UPSTREAM_ORG REPONAME" exit 1 fi From a308bf6c6c1ee07bc4ba4b2e705b9ecaad5d5e70 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 12 Jan 2026 15:24:46 -0800 Subject: [PATCH 04/12] Use variable for script name --- git-clone-or-pull | 10 ++++++---- git-clone-related | 6 ++++-- git-find-fork | 6 +++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index 6dda824..47c6036 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -10,8 +10,10 @@ # "-q --single-branch --depth 1" (without the quotes). # It is not used if the destination already exists. +SCRIPT_NAME="$(basename "$0")" + if [ "$#" -lt 2 ]; then - echo "Usage: $0 ORG REPO [DESTINATION_PARENT] [GIT_CLONE_ARGS...]" >&2 + echo "Usage: ${SCRIPT_NAME} ORG REPO [DESTINATION_PARENT] [GIT_CLONE_ARGS...]" >&2 exit 1 fi @@ -40,11 +42,11 @@ DESTINATION="${DESTINATION_PARENT}/${REPO_NAME}" if test -d "${DESTINATION}"; then (cd "${DESTINATION}" && (timeout 180 git pull -q || (sleep 1m && (timeout 180 git pull || true)))) else - mkdir -p "${DESTINATION_PARENT} + mkdir -p "${DESTINATION_PARENT}" if ! timeout 180 git clone -q --depth=1 "${REPO_URL}" "${DESTINATION}"; then sleep 1m - timeout 180 git clone --depth=1 "${REPO_URL}" "${DESTINATION} + timeout 180 git clone --depth=1 "${REPO_URL}" "${DESTINATION}" fi fi -echo "$0: ${REPO_NAME} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" +echo "${SCRIPT_NAME}: ${REPO_NAME} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" diff --git a/git-clone-related b/git-clone-related index 1cef876..90929fb 100755 --- a/git-clone-related +++ b/git-clone-related @@ -56,8 +56,10 @@ if [ "$1" = "--upstream-branch" ]; then shift fi +SCRIPT_NAME="$(basename "$0")" + if [ "$#" -lt 2 ]; then - echo "Usage: $0 UPSTREAM_ORG REPO_NAME [DESTINATION] [GIT_CLONE_ARGS...]" >&2 + echo "Usage: ${SCRIPT_NAME} UPSTREAM_ORG REPO_NAME [DESTINATION] [GIT_CLONE_ARGS...]" >&2 exit 1 fi @@ -167,4 +169,4 @@ else }; }; } fi -echo "$0: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" +echo "${SCRIPT_NAME}: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" diff --git a/git-find-fork b/git-find-fork index e7f0cc5..09d5e3a 100755 --- a/git-find-fork +++ b/git-find-fork @@ -10,9 +10,9 @@ # Often, you can use the `git-clone-related` script instead of this one. if [ "$#" -ne 3 ]; then - script=$(basename -- "$0") - >&2 echo "Error: $script requires 3 arguments, got $#" - >&2 echo "Usage: $script ORG UPSTREAM_ORG REPONAME" + SCRIPT_NAME=$(basename -- "$0") + >&2 echo "Error: ${SCRIPT_NAME} requires 3 arguments, got $#" + >&2 echo "Usage: ${SCRIPT_NAME} ORG UPSTREAM_ORG REPONAME" exit 1 fi From 2f449e176a9a6d1024f24f8c31c7eea2108df591 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 12 Jan 2026 17:45:07 -0800 Subject: [PATCH 05/12] Use in more places --- git-clone-related | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/git-clone-related b/git-clone-related index ba8bb2e..8186c1b 100755 --- a/git-clone-related +++ b/git-clone-related @@ -56,8 +56,10 @@ if [ "$1" = "--upstream-branch" ]; then shift fi +SCRIPT_NAME=$(basename -- "$0") + if [ "$#" -lt 2 ]; then - echo "Usage: $(basename -- "$0") UPSTREAM_ORG REPO_NAME [DESTINATION] [GIT_CLONE_ARGS...]" >&2 + echo "Usage: ${SCRIPT_NAME} UPSTREAM_ORG REPO_NAME [DESTINATION] [GIT_CLONE_ARGS...]" >&2 exit 1 fi @@ -167,4 +169,4 @@ else }; }; } fi -echo "$0: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" +echo "${SCRIPT_NAME}: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" From 04d70c8656c4515b4788a1480c4e865b340f8ca4 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Mon, 12 Jan 2026 20:42:22 -0800 Subject: [PATCH 06/12] Fixes from CodeRabbit --- git-clone-or-pull | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index 47c6036..1a6747e 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -2,7 +2,7 @@ # git-clone-or-pull: clone a GitHub repository, or pull it if already cloned. # -# Usage: git-clone-or-pull ORG REPO [DESTINATION_PARENT] [GIT_CLONE_ARGS] +# Usage: git-clone-or-pull ORG REPO_NAME [DESTINATION_PARENT] [GIT_CLONE_ARGS] # ORG is the GitHub organization # REPO_NAME is the repository name (without the organization) # DESTINATION_PARENT is the directory that contains the clone directory. @@ -13,25 +13,29 @@ SCRIPT_NAME="$(basename "$0")" if [ "$#" -lt 2 ]; then - echo "Usage: ${SCRIPT_NAME} ORG REPO [DESTINATION_PARENT] [GIT_CLONE_ARGS...]" >&2 + echo "Usage: ${SCRIPT_NAME} ORG REPO_NAME [DESTINATION_PARENT] [GIT_CLONE_ARGS...]" >&2 exit 1 fi ORG=$1 shift -REPO_NAME=$2 +REPO_NAME=$1 shift -if [ "$#" -ne 0 ] && ! beginswith "-" "$1"; then - DESTINATION_PARENT=$1 - shift - if [ ! -d "${DESTINATION_PARENT}" ]; then - mkdir -p "${DESTINATION_PARENT}" - exit 1 - fi -else - DESTINATION_PARENT=. +DESTINATION_PARENT=. +if [ "$#" -ne 0 ]; then + case $1 in + "-"*) ;; # $1 starts with "-" and is probably a command-line argument. + *) + DESTINATION_PARENT=$1 + shift + if [ ! -d "${DESTINATION_PARENT}" ]; then + mkdir -p "${DESTINATION_PARENT}" + fi + ;; + esac fi if [ "$#" -eq 0 ]; then + # Default command-line arguments. set -- -q --single-branch --depth 1 fi @@ -43,9 +47,9 @@ if test -d "${DESTINATION}"; then (cd "${DESTINATION}" && (timeout 180 git pull -q || (sleep 1m && (timeout 180 git pull || true)))) else mkdir -p "${DESTINATION_PARENT}" - if ! timeout 180 git clone -q --depth=1 "${REPO_URL}" "${DESTINATION}"; then + if ! timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}"; then sleep 1m - timeout 180 git clone --depth=1 "${REPO_URL}" "${DESTINATION}" + timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}" fi fi From d2b37f35e2a4693cb43a51d4f59e8bc09acb770a Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 13 Jan 2026 08:10:56 -0800 Subject: [PATCH 07/12] Better test and cleanup --- git-clone-or-pull | 8 +++++--- git-clone-related | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index 1a6747e..94becf7 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -5,7 +5,8 @@ # Usage: git-clone-or-pull ORG REPO_NAME [DESTINATION_PARENT] [GIT_CLONE_ARGS] # ORG is the GitHub organization # REPO_NAME is the repository name (without the organization) -# DESTINATION_PARENT is the directory that contains the clone directory. +# DESTINATION_PARENT is the directory that contains the clone directory. It +# defaults to the current directory. # GIT_CLONE_ARGS is extra arguments to git clone. It defaults to # "-q --single-branch --depth 1" (without the quotes). # It is not used if the destination already exists. @@ -40,7 +41,7 @@ if [ "$#" -eq 0 ]; then fi REPO_URL="https://github.com/${ORG}/${REPO_NAME}.git" -DESTINATION="${DESTINATION_PARENT}/${REPO_NAME}" +DESTINATION="${DESTINATION_PARENT:?}/${REPO_NAME}" # Try twice in case of network lossage. 60 seconds is not enough to clone a branch of the JDK. if test -d "${DESTINATION}"; then @@ -48,7 +49,8 @@ if test -d "${DESTINATION}"; then else mkdir -p "${DESTINATION_PARENT}" if ! timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}"; then - sleep 1m + rm -rf "${DESTINATION:?}/${REPO_NAME}" + sleep 180 timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}" fi fi diff --git a/git-clone-related b/git-clone-related index d653032..27f5e22 100755 --- a/git-clone-related +++ b/git-clone-related @@ -165,15 +165,16 @@ else fi echo "${SCRIPT_NAME}: About to run: git clone -q -b ${REPO_BRANCH} $* ${REPO_URL} ${DESTINATION}" # Try twice in case of network lossage. 60 seconds is not enough to clone a branch of the JDK. - timeout 180 git clone -q -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}" \ - || { echo "Retrying 'git clone ... ${REPO_URL} ${DESTINATION}' after timeout" \ - && rm -rf "${DESTINATION}" \ - && sleep 180 \ - && { timeout 180 git clone -q -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}" \ - || { - echo "${SCRIPT_NAME}: failed: git clone -q -b ${REPO_BRANCH}" "$@" "${REPO_URL} ${DESTINATION}" - exit 2 - }; }; } + if ! timeout 180 git clone -q -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}"; then + echo "Retrying 'git clone ... ${REPO_URL} ${DESTINATION}' after timeout" + rm -rf "${DESTINATION}" + sleep 180 + if ! timeout 180 git clone -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}"; then + echo "${SCRIPT_NAME}: failed: git clone -q -b ${REPO_BRANCH}" "$@" "${REPO_URL} ${DESTINATION}" + exit 2 + fi + fi + fi echo "${SCRIPT_NAME}: ${DESTINATION} is at $(cd "${DESTINATION}" && git rev-parse HEAD)" From 55e5b8539d993aca559e675db84af35449589975 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 13 Jan 2026 08:28:27 -0800 Subject: [PATCH 08/12] Fixes --- git-clone-or-pull | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index 94becf7..cdbe477 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -49,9 +49,12 @@ if test -d "${DESTINATION}"; then else mkdir -p "${DESTINATION_PARENT}" if ! timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}"; then - rm -rf "${DESTINATION:?}/${REPO_NAME}" + rm -rf "${DESTINATION}" sleep 180 - timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}" + if ! timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}"; then + echo "Failed to clone ${REPO_URL}" + exit 1 + fi fi fi From 3c5cad51ddb3b2a6dfb86c4b0d8fc9abd1aec561 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 13 Jan 2026 08:38:24 -0800 Subject: [PATCH 09/12] Fixes from CodeRabbit --- git-clone-or-pull | 1 - git-clone-related | 4 ++-- tests/git-clone-related-test/test-git-clone-related.sh | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index cdbe477..9be9809 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -47,7 +47,6 @@ DESTINATION="${DESTINATION_PARENT:?}/${REPO_NAME}" if test -d "${DESTINATION}"; then (cd "${DESTINATION}" && (timeout 180 git pull -q || (sleep 1m && (timeout 180 git pull || true)))) else - mkdir -p "${DESTINATION_PARENT}" if ! timeout 180 git clone "$@" "${REPO_URL}" "${DESTINATION}"; then rm -rf "${DESTINATION}" sleep 180 diff --git a/git-clone-related b/git-clone-related index df00307..5b24970 100755 --- a/git-clone-related +++ b/git-clone-related @@ -176,11 +176,11 @@ else echo "${SCRIPT_NAME}: About to run: git clone -q -b ${REPO_BRANCH} $* ${REPO_URL} ${DESTINATION}" # Try twice in case of network lossage. 60 seconds is not enough to clone a branch of the JDK. if ! timeout 180 git clone -q -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}"; then - echo "Retrying 'git clone ... ${REPO_URL} ${DESTINATION}' after timeout" + echo "Retrying 'git clone ... ${REPO_URL} ${DESTINATION}'" rm -rf "${DESTINATION}" sleep 180 if ! timeout 180 git clone -b "${REPO_BRANCH}" "$@" "${REPO_URL}" "${DESTINATION}"; then - echo "${SCRIPT_NAME}: failed: git clone -q -b ${REPO_BRANCH}" "$@" "${REPO_URL} ${DESTINATION}" + echo "${SCRIPT_NAME}: failed: git clone -b ${REPO_BRANCH}" "$@" "${REPO_URL} ${DESTINATION}" exit 2 fi fi diff --git a/tests/git-clone-related-test/test-git-clone-related.sh b/tests/git-clone-related-test/test-git-clone-related.sh index 58d75e3..219f867 100755 --- a/tests/git-clone-related-test/test-git-clone-related.sh +++ b/tests/git-clone-related-test/test-git-clone-related.sh @@ -41,7 +41,7 @@ unset TRAVIS unset CIRCLE_COMPARE_URL unset GITHUB_HEAD_REF -echo "$0: About to run: (cd $startdir && ${GIT_SCRIPTS}/git-clone-related $ARGS $resultdir)" +echo "$0: About to run: (cd $startdir && ${GIT_SCRIPTS}/git-clone-related $DEBUG $ARGS $resultdir)" # shellcheck disable=SC2086 # $DEBUG and $ARGS should not be quoted (cd "$startdir" && "${GIT_SCRIPTS}"/git-clone-related $DEBUG $ARGS "$resultdir") echo "$0: Done: (cd $startdir && ${GIT_SCRIPTS}/git-clone-related $ARGS $resultdir)" From e0eb2efdc3a53bf569d582c88bfcb46b53ac6cf6 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 13 Jan 2026 08:43:10 -0800 Subject: [PATCH 10/12] More consistent output --- tests/git-clone-related-test/test-git-clone-related.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/git-clone-related-test/test-git-clone-related.sh b/tests/git-clone-related-test/test-git-clone-related.sh index 219f867..39f4405 100755 --- a/tests/git-clone-related-test/test-git-clone-related.sh +++ b/tests/git-clone-related-test/test-git-clone-related.sh @@ -44,7 +44,7 @@ unset GITHUB_HEAD_REF echo "$0: About to run: (cd $startdir && ${GIT_SCRIPTS}/git-clone-related $DEBUG $ARGS $resultdir)" # shellcheck disable=SC2086 # $DEBUG and $ARGS should not be quoted (cd "$startdir" && "${GIT_SCRIPTS}"/git-clone-related $DEBUG $ARGS "$resultdir") -echo "$0: Done: (cd $startdir && ${GIT_SCRIPTS}/git-clone-related $ARGS $resultdir)" +echo "$0: Done: (cd $startdir && ${GIT_SCRIPTS}/git-clone-related $DEBUG $ARGS $resultdir)" clonedrepo=$(git -C "$resultdir" config --get remote.origin.url) # git 2.22 and later has `git branch --show-current`; CircleCI doesn't have that version yet. From 3c8efb85290af5776a3a54446d86123d421a7900 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 13 Jan 2026 08:46:09 -0800 Subject: [PATCH 11/12] Use `beginswith` for clarity --- git-clone-or-pull | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index 9be9809..7643fef 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -18,22 +18,22 @@ if [ "$#" -lt 2 ]; then exit 1 fi +beginswith() { case $2 in "$1"*) true ;; *) false ;; esac } + ORG=$1 shift REPO_NAME=$1 shift DESTINATION_PARENT=. if [ "$#" -ne 0 ]; then - case $1 in - "-"*) ;; # $1 starts with "-" and is probably a command-line argument. - *) - DESTINATION_PARENT=$1 - shift - if [ ! -d "${DESTINATION_PARENT}" ]; then - mkdir -p "${DESTINATION_PARENT}" - fi - ;; - esac + if ! beginswith "-" "$1"; then + # Does not start with "-" and therefore isn't a command-line argument. + DESTINATION_PARENT=$1 + shift + if [ ! -d "${DESTINATION_PARENT}" ]; then + mkdir -p "${DESTINATION_PARENT}" + fi + fi fi if [ "$#" -eq 0 ]; then # Default command-line arguments. From 0c3cd37663fe33dd97ceca3a6cbd4accdaac9ff8 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 13 Jan 2026 08:54:37 -0800 Subject: [PATCH 12/12] Improve usage message --- git-clone-or-pull | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-clone-or-pull b/git-clone-or-pull index 7643fef..8d6c2c7 100755 --- a/git-clone-or-pull +++ b/git-clone-or-pull @@ -2,7 +2,7 @@ # git-clone-or-pull: clone a GitHub repository, or pull it if already cloned. # -# Usage: git-clone-or-pull ORG REPO_NAME [DESTINATION_PARENT] [GIT_CLONE_ARGS] +# Usage: git-clone-or-pull ORG REPO_NAME [DESTINATION_PARENT] [GIT_CLONE_ARGS...] # ORG is the GitHub organization # REPO_NAME is the repository name (without the organization) # DESTINATION_PARENT is the directory that contains the clone directory. It