diff --git a/build-env/sync-from-windows.sh b/build-env/sync-from-windows.sh new file mode 100755 index 00000000..d47ed36d --- /dev/null +++ b/build-env/sync-from-windows.sh @@ -0,0 +1,171 @@ +#!/usr/bin/env bash +# sync-from-windows.sh +# Pulls build and deploy OUTPUTS back from the Windows build/test machine +# mounted at /vwe/firestorm. This is the inverse of sync-to-windows.sh, which +# pushes sources out. +# +# Only GENERATED artefacts come back. Source, content and assets are never +# pulled, so local edits made since the last push cannot be clobbered by a +# stale copy sitting on the build machine. +# +# Usage: +# ./sync-from-windows.sh # pull everything generated +# ./sync-from-windows.sh --dry-run # preview only, no files written +# ./sync-from-windows.sh --delete # also delete local files that are gone +# # on Windows (off by default: a pull with +# # --delete can destroy mirrored history) +# +# This repo is a full disaster-recovery mirror -- build outputs are tracked on +# purpose (.gitignore is deliberately almost empty), so pulling them back and +# committing them is the intended workflow, not noise. + +SRC=/vwe/firestorm +DST=~/Repositories/firestorm + +# Deliberately NOT -a: the CIFS mount reports every file as 755 while git +# tracks these as 100644. Preserving permissions would flip the exec bit on +# every file pulled and show up as a mode change on thousands of paths. +# -rlt keeps recursion, symlinks and mtimes; --chmod forces sane local modes. +RSYNC_OPTS="-rltv --chmod=F664,D775 --modify-window=2" + +for arg in "$@"; do + case "$arg" in + --dry-run) RSYNC_OPTS="$RSYNC_OPTS --dry-run" + echo "[DRY RUN] No files will be written." ;; + --delete) RSYNC_OPTS="$RSYNC_OPTS --delete" + echo "[DELETE] Local files absent on Windows will be removed." ;; + *) echo "Unknown option: $arg"; exit 2 ;; + esac +done + +set -e + +if [[ ! -d "$SRC" ]]; then + echo "ERROR: $SRC is not mounted. Mount the build machine first." >&2 + exit 1 +fi + +# Warn before overwriting work that is not yet committed. Untracked files are +# ignored: they are new local work, not a modified copy of something the build +# machine is about to send back. +UNCOMMITTED=$(cd "$DST" && git status --porcelain -- \ + Gameleap/code Gameleap/mw4/Resource MW4 build-env 2>/dev/null \ + | grep -cv '^??' || true) +if [[ "$UNCOMMITTED" -gt 0 ]]; then + echo + echo "WARNING: $UNCOMMITTED uncommitted change(s) already exist in the pull targets." + echo " Pulling will overwrite them. Ctrl-C now if that is not what you want." + echo +fi + +echo +echo "=== [1/6] Linked build output dirs (MW4.exe, MW4Ed2.exe, libs, dlls, pdbs) ===" +for d in rel.bin dbg.bin pro.bin arm.bin ice.bin; do + if [[ -d "$SRC/Gameleap/code/$d" ]]; then + echo "--- $d" + rsync $RSYNC_OPTS "$SRC/Gameleap/code/$d/" "$DST/Gameleap/code/$d/" + fi +done + +echo +echo "=== [2/6] Per-project intermediates (obj, pch, idb, pdb, res) ===" +# VC6 writes these into a Release/Profile/Armor/Debug folder beside each .dsp. +# They are scattered across the tree, so the list is discovered rather than +# hardcoded. 2700+ .obj files are tracked here -- see the mirror note above. +INTERMEDIATES=$(cd "$SRC" && find Gameleap/code -type d \ + \( -name Release -o -name Profile -o -name Armor -o -name Debug -o -name icecap \) \ + -printf '%p/\n' 2>/dev/null | sort) +if [[ -n "$INTERMEDIATES" ]]; then + echo "$INTERMEDIATES" | rsync $RSYNC_OPTS --files-from=- "$SRC/" "$DST/" + echo "--- $(echo "$INTERMEDIATES" | wc -l) intermediate dirs" +else + echo "--- none found" +fi + +echo +echo "=== [3/6] Packed resources (*.mw4 + *.dep) ===" +# .tga/.nfo/.txt in here are SOURCE and travel outbound only, so they are excluded. +rsync $RSYNC_OPTS \ + --include='*/' \ + --include='*.mw4' \ + --include='*.dep' \ + --exclude='*' \ + --prune-empty-dirs \ + "$SRC/Gameleap/mw4/Resource/" "$DST/Gameleap/mw4/Resource/" + +echo +echo "=== [4/6] Deployed game (MW4/) - output of deploy-mw4.ps1 ===" +# Two classes of exclusion here: +# - per-machine and gitignored: player-made variants, and the GameOS run-time +# reports which are rewritten on every launch. +# - dgVoodoo2: an installed-per-machine, OS-dependent prerequisite for Win10/11 +# pods. It must NEVER enter the repo -- shipping it would push a Win10-only +# dependency onto the XP pods and break them. Removed deliberately in +# 0ceba9c7; do not "fix" that by letting a pull put it back. +rsync $RSYNC_OPTS \ + --exclude='Resource/Variants/' \ + --exclude='gos-displays.txt' \ + --exclude='gos-fps.txt' \ + --exclude='[Dd][Gg][Vv]oodoo.conf' \ + --exclude='[Dd][Gg][Vv]oodooCpl.exe' \ + --exclude='[Dd][Dd]raw.dll' \ + --exclude='[Dd]3[Dd]8.dll' \ + --exclude='[Dd]3[Dd]9.dll' \ + --exclude='[Dd]3[Dd][Ii]mm.dll' \ + "$SRC/MW4/" "$DST/MW4/" + +echo +echo "=== [5/6] Binaries deployed into the data tree (Gameleap/mw4 root) ===" +# deploy-editor.ps1 installs the editor here; the game binaries are mirrored +# alongside it. Only known build products are listed, so nothing else in this +# directory can be overwritten by a stale copy. +PRODUCTS="MW4.exe MW4pro.exe MW4Ed2.exe MW4Ed2.pdb Launcher.exe autoconfig.exe \ +mw4print.exe MissionLang.dll ScriptStrings.dll ctcls.dll Language.dll" +PRESENT="" +for f in $PRODUCTS; do + [[ -f "$SRC/Gameleap/mw4/$f" ]] && PRESENT="$PRESENT$f"$'\n' +done +if [[ -n "$PRESENT" ]]; then + # --delete is meaningless for an explicit file list, so it is dropped here. + printf '%s' "$PRESENT" | rsync ${RSYNC_OPTS/--delete/} --files-from=- \ + "$SRC/Gameleap/mw4/" "$DST/Gameleap/mw4/" +else + echo "--- no deployed binaries found" +fi + +echo +echo "=== [6/6] Build logs (build-env/*.log, *.plg, *.map) ===" +rsync $RSYNC_OPTS \ + --include='*.log' --include='*.plg' --include='*.map' \ + --exclude='*/' --exclude='*' \ + "$SRC/build-env/" "$DST/build-env/" + +echo +echo "=== Pull complete ===" +echo "Pulled: Gameleap/code/{rel,dbg,pro,arm,ice}.bin/" +echo " Gameleap/code/**/{Release,Profile,Armor,Debug}/" +echo " Gameleap/mw4/Resource/*.mw4 *.dep" +echo " MW4/ (deployed game)" +echo " Gameleap/mw4/ deployed binaries" +echo " build-env/ build logs" +echo +echo "NOT pulled (source travels outbound only):" +echo " Gameleap/code source, Gameleap/mw4/Content, hsh, Assets, Stats" +echo " Resource/*.tga *.nfo *.txt, build-env scripts, BTFrstrm" +echo "NOT pulled (per-machine):" +echo " MW4/Resource/Variants/, MW4/gos-displays.txt, MW4/gos-fps.txt" +echo " MW4/ dgVoodoo2 (DDraw/D3D8/D3D9/D3DImm.dll, dgVoodoo.conf/Cpl.exe)" +echo " -- a Win10/11-only prerequisite that must never reach the XP pods" + +echo +echo "=== Changed in the working tree ===" +cd "$DST" +CHANGED=$(git status --porcelain | wc -l) +if [[ "$CHANGED" -eq 0 ]]; then + echo " nothing changed - the repo already matched the build machine" +else + git status --short | head -40 + [[ "$CHANGED" -gt 40 ]] && echo " ... and $((CHANGED - 40)) more" + echo + echo " $CHANGED path(s) changed. Review, then commit." +fi