Files
firestorm/build-env/sync-from-windows.sh
T
a57be4bd12 Add sync-from-windows.sh to pull build outputs back from the build machine
sync-to-windows.sh pushes sources out; there was no inverse, so every build
had to be retrieved by hand. This pulls back only GENERATED artefacts:
the linked output dirs (rel/dbg/pro/arm/ice.bin), the per-project VC6
intermediates, packed Resource/*.mw4 + *.dep, the MW4/ deploy, the binaries
deployed into Gameleap/mw4, and the build logs. Source, content and assets
are never pulled, so a stale copy on the build machine cannot clobber local
edits made since the last push.

Two things it has to get right, both found by running it:

It does not use rsync -a. The CIFS mount reports every file as 755 while git
tracks these as 100644, so preserving permissions would flip the exec bit on
every file pulled -- a spurious mode change on ~2000 paths. It uses
-rlt --chmod=F664,D775 instead. Verified: 1994 files pulled, 0 mode changes.

It excludes dgVoodoo2 from the MW4/ deploy (DDraw/D3D8/D3D9/D3DImm.dll,
dgVoodoo.conf, dgVoodooCpl.exe). That is a Win10/11-only prerequisite which
must never enter the repo because it breaks the XP pods; it was removed
deliberately in 0ceba9c7. A naive pull dragged all six straight back in.
This was being stripped by hand before every push back.

--delete is opt-in rather than default: a pull with --delete can destroy
mirrored history if the build machine is missing something. Excluded files
are protected from deletion, so Resource/*.tga and *.nfo cannot be removed
by it. There is also a --dry-run, and a warning if the pull targets already
hold uncommitted work.

Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-08-09 17:54:38 -05:00

172 lines
6.8 KiB
Bash
Executable File

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