← back to Games Agentabrams
sync.sh
91 lines
#!/bin/bash
# Reconcile standalone source builds -> this topic hub (games/<id>/).
# Mapping lives in sources.tsv: "<hub-id>\t<abs-source-project-path>".
# Usage: ./sync.sh [--commit|--check]
# (no flag) copy source builds into games/<id>/ and regenerate games-data.js
# --commit same, then git-commit the hub if anything changed
# --check NON-MUTATING drift detector: exit 3 if any deployed copy or the
# games-data.js mirror is out of sync with source (for canaries/CI)
set -euo pipefail
HUB="$(cd "$(dirname "$0")" && pwd)"
MAP="$HUB/sources.tsv"
[ -f "$MAP" ] || { echo "no sources.tsv"; exit 0; }
if [ "${1:-}" = "--check" ]; then
drift=0
while IFS=$'\t' read -r id src; do
[ -z "${id:-}" ] && continue
case "$id" in \#*) continue;; esac
src="${src/#\~/$HOME}"
dest="$HUB/games/$id"
[ -d "$src" ] || { echo "! source missing for $id: $src"; drift=1; continue; }
if ! cmp -s "$src/index.html" "$dest/index.html" 2>/dev/null; then
echo "DRIFT: games/$id/index.html differs from $src/index.html"; drift=1
fi
# also verify the .aa manifests the mutating sync copies (line 20)
for aa in "$src"/*.aa; do
[ -e "$aa" ] || continue
if ! cmp -s "$aa" "$dest/$(basename "$aa")" 2>/dev/null; then
echo "DRIFT: games/$id/$(basename "$aa") differs from $aa"; drift=1
fi
done
done < "$MAP"
# games-data.js must equal a fresh regen of games.json (lockstep mirror)
if [ -f "$HUB/games.json" ]; then
tmp="$(mktemp)"
python3 - "$HUB" "$tmp" <<'PY'
import json, os, sys
hub, out = sys.argv[1], sys.argv[2]
d = json.load(open(os.path.join(hub, 'games.json')))
with open(out, 'w') as f:
f.write('/* AUTO-GENERATED from games.json by sync.sh — do not edit by hand.\n')
f.write(' file:// fallback: <script src> works from a local file, fetch() does not. */\n')
f.write('window.__GAMES_DATA__ = ')
json.dump(d, f, ensure_ascii=False, indent=2)
f.write(';\n')
PY
if ! cmp -s "$tmp" "$HUB/games-data.js"; then
echo "DRIFT: games-data.js is stale vs games.json (run ./sync.sh)"; drift=1
fi
rm -f "$tmp"
fi
[ "$drift" = 0 ] && { echo "check: all in sync"; exit 0; } || { echo "check: DRIFT detected"; exit 3; }
fi
changed=0
while IFS=$'\t' read -r id src; do
[ -z "${id:-}" ] && continue
case "$id" in \#*) continue;; esac
src="${src/#\~/$HOME}"
dest="$HUB/games/$id"
if [ ! -d "$src" ]; then echo "! source missing for $id: $src"; continue; fi
mkdir -p "$dest"
if ! cmp -s "$src/index.html" "$dest/index.html" 2>/dev/null; then
cp "$src/index.html" "$dest/index.html"; echo "synced index.html -> games/$id/"; changed=1
fi
for aa in "$src"/*.aa; do [ -e "$aa" ] || continue; cp "$aa" "$dest/"; done
done < "$MAP"
[ "$changed" = 1 ] && echo "sync: updates applied" || echo "sync: all in sync"
# Regenerate the file:// fallback mirror of games.json (a <script src> loads
# from a local file; fetch() is blocked over file://). Keeps games-data.js in
# lockstep with games.json so double-clicking index.html shows every game.
if [ -f "$HUB/games.json" ]; then
python3 - "$HUB" <<'PY'
import json, os, sys
hub = sys.argv[1]
d = json.load(open(os.path.join(hub, 'games.json')))
with open(os.path.join(hub, 'games-data.js'), 'w') as f:
f.write('/* AUTO-GENERATED from games.json by sync.sh — do not edit by hand.\n')
f.write(' file:// fallback: <script src> works from a local file, fetch() does not. */\n')
f.write('window.__GAMES_DATA__ = ')
json.dump(d, f, ensure_ascii=False, indent=2)
f.write(';\n')
PY
echo "regenerated games-data.js ($(grep -c '"id"' "$HUB/games.json") games)"
fi
if [ "${1:-}" = "--commit" ] && [ -n "$(git -C "$HUB" status --porcelain)" ]; then
git -C "$HUB" add -A
git -C "$HUB" -c user.email="steve@designerwallcoverings.com" -c user.name="Steve" commit -q -m "sync builds from source" && echo "committed hub"
fi