fix(sync): init submodules on fresh clones; drop orphaned solverbot gitlink

Phase 1a used `git submodule foreach`, which only visits initialized
submodules — a fresh machine silently skipped population while the script
still reported success. It now explicitly inits + populates each submodule
declared in .gitmodules (inheriting credentials from the parent origin URL
so non-interactive init authenticates; .gitmodules stays credential-free),
then advances each to its remote branch tip. Reporting reflects the real
configured count.

Also removes the orphaned `projects/solverbot` gitlink (mode 160000),
committed without a .gitmodules entry, which made `git submodule status`
throw `fatal: no submodule mapping`. solverbot's own Gitea repo is untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-25 09:12:08 -07:00
parent 3eff33839b
commit 413df93189
2 changed files with 40 additions and 3 deletions

View File

@@ -93,13 +93,51 @@ fi
echo -e "${GREEN}[OK]${NC} Syncing as: $USER_DISPLAY (machine: $MACHINE)"
# Phase 1a: Update submodules to latest remote
# `git submodule foreach` only visits *initialized* submodules, so a fresh clone
# would silently skip population and the old "[OK] updated" message lied. We now
# explicitly init+populate each submodule declared in .gitmodules, then advance
# it to its remote branch tip. Iterating .gitmodules (not the index) sidesteps
# any orphaned gitlink that lacks a .gitmodules mapping. Credentials are inherited
# from the parent origin URL so non-interactive init works without a credential
# helper; .gitmodules itself stays credential-free.
echo ""
echo "=== Phase 1a: Submodule update ==="
if [ -f ".gitmodules" ]; then
if [ -f ".gitmodules" ] && git config --file .gitmodules --get-regexp '^submodule\..*\.path$' >/dev/null 2>&1; then
# Temporarily disable errexit — submodule ops emit non-fatal warnings that
# would otherwise kill the script under set -e.
set +e
# If origin embeds credentials (https://user:pass@host/...), reuse its
# scheme+userinfo+host for submodule clones.
PARENT_URL="$(git config --get remote.origin.url)"
CRED_HOST=""
case "$PARENT_URL" in
https://*@*) CRED_HOST="$(printf '%s' "$PARENT_URL" | sed -E 's#^(https://[^/]+)/.*#\1#')" ;;
esac
SUB_COUNT=0
while read -r pkey ppath; do
[ -z "$ppath" ] && continue
name="$(printf '%s' "$pkey" | sed -E 's#^submodule\.(.*)\.path$#\1#')"
SUB_COUNT=$((SUB_COUNT + 1))
# Register in .git/config (no-op if already initialized).
git submodule init -- "$ppath" >/dev/null 2>&1
# Override the local clone URL with credentials when available.
if [ -n "$CRED_HOST" ]; then
gm_url="$(git config --file .gitmodules --get "submodule.${name}.url")"
case "$gm_url" in
https://*)
sub_path="$(printf '%s' "$gm_url" | sed -E 's#^https://[^/]+(/.*)#\1#')"
git config "submodule.${name}.url" "${CRED_HOST}${sub_path}"
;;
esac
fi
# Populate if missing (fresh clone) at the pinned commit.
git submodule update --init -- "$ppath" >/dev/null 2>&1
done < <(git config --file .gitmodules --get-regexp '^submodule\..*\.path$')
# Advance each initialized submodule to its remote branch tip.
git submodule foreach --quiet '
git fetch origin --quiet 2>/dev/null
git checkout main --quiet 2>/dev/null || git checkout master --quiet 2>/dev/null
@@ -107,7 +145,7 @@ if [ -f ".gitmodules" ]; then
git merge --ff-only origin/master --quiet 2>/dev/null
' 2>/dev/null
set -e
echo -e "${GREEN}[OK]${NC} Submodules updated to latest remote (on branch)."
echo -e "${GREEN}[OK]${NC} Submodules init+advanced (${SUB_COUNT} configured)."
else
echo -e "${GREEN}[OK]${NC} No submodules."
fi