← 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