From 758f53b5e1bb8761f1b39088afc7a29c3b9d9b93 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell Date: Sun, 26 Jul 2026 23:22:39 +0100 Subject: [PATCH 1/2] fix(git/fetch): report a fetch/skip summary instead of raw errors A repo the script can't fetch (e.g. no publickey access) already gets skipped via `continue`, but the raw git/ssh failure text printed to the terminal made it look like the whole run had crashed rather than just moving on. Quiet that output and instead read the repo list from a temp file (a plain pipe would have run the loop in a subshell, losing any counters) so the run can report a final summary: how many repos were fetched, how many were skipped, and why. --- git/fetch | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/git/fetch b/git/fetch index 169f5715..24d07971 100755 --- a/git/fetch +++ b/git/fetch @@ -42,7 +42,16 @@ for arg in "$@"; do esac done -find "$(pwd)"/* -name '*.git' -print | sed "s|/.git$||" | sort -u | grep -v .cache | while IFS= read -r line +REPO_LIST=$(mktemp) +trap 'rm -f "$REPO_LIST"' EXIT + +find "$(pwd)"/* -name '*.git' -print | sed "s|/.git$||" | sort -u | grep -v .cache > "$REPO_LIST" + +FETCHED_COUNT=0 +SKIPPED_COUNT=0 +SKIPPED_REPOS="" + +while IFS= read -r line do CURRENT_DIR=$line @@ -53,11 +62,15 @@ do else git -C "$CURRENT_DIR" config --local --unset core.hookspath 2>/dev/null || true fi - git -C "$CURRENT_DIR" remote get-url origin 2>&1 || { warn "Could not determine origin for ${CURRENT_DIR}"; continue; } - git -C "$CURRENT_DIR" fetch --prune --prune-tags 2>&1 || { warn "Could not fetch ${CURRENT_DIR}"; continue; } - git -C "$CURRENT_DIR" remote update origin --prune 2>&1 || { warn "Could not update remote refs for ${CURRENT_DIR}"; continue; } + git -C "$CURRENT_DIR" remote get-url origin > /dev/null 2>&1 || { warn "Could not determine origin for ${CURRENT_DIR}"; SKIPPED_COUNT=$((SKIPPED_COUNT + 1)); SKIPPED_REPOS="${SKIPPED_REPOS}${CURRENT_DIR} (could not determine origin) +"; continue; } + git -C "$CURRENT_DIR" fetch --prune --prune-tags > /dev/null 2>&1 || { warn "Could not fetch ${CURRENT_DIR}"; SKIPPED_COUNT=$((SKIPPED_COUNT + 1)); SKIPPED_REPOS="${SKIPPED_REPOS}${CURRENT_DIR} (could not fetch) +"; continue; } + git -C "$CURRENT_DIR" remote update origin --prune > /dev/null 2>&1 || { warn "Could not update remote refs for ${CURRENT_DIR}"; SKIPPED_COUNT=$((SKIPPED_COUNT + 1)); SKIPPED_REPOS="${SKIPPED_REPOS}${CURRENT_DIR} (could not update remote refs) +"; continue; } - REPO_STATUS=$(git -C "$CURRENT_DIR" status --porcelain 2>&1) || { warn "Could not read status for ${CURRENT_DIR}"; continue; } + REPO_STATUS=$(git -C "$CURRENT_DIR" status --porcelain 2>&1) || { warn "Could not read status for ${CURRENT_DIR}"; SKIPPED_COUNT=$((SKIPPED_COUNT + 1)); SKIPPED_REPOS="${SKIPPED_REPOS}${CURRENT_DIR} (could not read status) +"; continue; } if [ -z "$REPO_STATUS" ] then @@ -75,7 +88,8 @@ do if [ "$SWITCH_TO_MAIN" = "1" ] then - CURRENT_BRANCH=$(git -C "$CURRENT_DIR" rev-parse --abbrev-ref HEAD 2>&1) || { warn "Could not determine current branch for ${CURRENT_DIR}"; continue; } + CURRENT_BRANCH=$(git -C "$CURRENT_DIR" rev-parse --abbrev-ref HEAD 2>&1) || { warn "Could not determine current branch for ${CURRENT_DIR}"; SKIPPED_COUNT=$((SKIPPED_COUNT + 1)); SKIPPED_REPOS="${SKIPPED_REPOS}${CURRENT_DIR} (could not determine current branch) +"; continue; } DEFAULT_BRANCH=$(git -C "$CURRENT_DIR" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||') if [ -z "$DEFAULT_BRANCH" ] @@ -106,5 +120,13 @@ do fi fi + FETCHED_COUNT=$((FETCHED_COUNT + 1)) success "Done with ${CURRENT_DIR}" -done +done < "$REPO_LIST" + +info "${FETCHED_COUNT} repo(s) fetched, ${SKIPPED_COUNT} repo(s) skipped" +if [ "$SKIPPED_COUNT" -gt 0 ] +then + warn "Skipped repositories:" + printf '%s' "$SKIPPED_REPOS" >&2 +fi From 32acc2ee8c456a886244d2ddd57f8faaa41bc7f3 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell Date: Sun, 26 Jul 2026 23:24:46 +0100 Subject: [PATCH 2/2] docs(changelog): add entry for git/fetch skip summary fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 239e9d9e..3eac3b63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ Please ADD ALL Changes to the UNRELEASED SECTION and not a specific release - development/buildtest now runs unit tests first, always excluding benchmark test projects, then runs any benchmark projects found individually without the --long-running/--parallel-algorithm flags, since some benchmark projects' test host rejects them as invalid arguments (exit code 5, zero tests ran) instead of running - development/buildtest: fixed the --no-benchmarks/--no-integration flag typos and the broken TEST_INTEGRATION filter assignment so --no-integration actually excludes integration tests - development/buildtest: disable shell pathname expansion (set -f) around the dotnet test invocation using the unquoted TEST_INTEGRATION filter, so a *.Integration.Tests(.*) file in the solution directory can no longer glob-expand and corrupt the --no-integration filter arguments +- git/fetch no longer prints raw git/ssh errors when a repo can't be reached, and reports a fetched/skipped summary at the end ### Changed - Replace raw echo with standard output helpers (die/info/success) in github/cancel-workflows - Replace raw echo with standard output helpers (die/info/success) in git/update-repos-personal