#!/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