forked from FlyingEwok/MinecraftSplitscreenSteamdeck
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdeploy.sh
More file actions
executable file
·219 lines (203 loc) · 10.1 KB
/
Copy pathdeploy.sh
File metadata and controls
executable file
·219 lines (203 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/bin/bash
# =============================================================================
# deploy.sh — sync the checkout's runtime tree to the deployed location
# =============================================================================
#
# `git pull` is NOT a deploy: the launcher runs from ~/.local/share/PolyMC/,
# not from this checkout, and testing a stale deployed tree has produced false
# test results twice (issue #54). The installer is the only other deploy path
# and is far too heavy for iterate-test loops. This script closes that gap:
#
# ./deploy.sh deploy: copy the entry script + runtime modules from
# this checkout into the deployed tree, printing
# exactly what changed
# ./deploy.sh --check freshness check: diff the deployed tree against the
# checkout; exit 0 if fresh, 1 on ANY drift (missing
# or differing file). Run before every test phase —
# tests/hardware/run_all.sh does this automatically.
# ./deploy.sh --target D use D instead of ~/.local/share/PolyMC (both modes)
#
# What counts as "the runtime tree" is defined once for everyone (#49):
# the entry script is minecraftSplitscreen.sh and the module list is
# modules/runtime_modules.list — the same manifest the launcher, the installer
# entry, and launcher_setup.sh read. The manifest deploys with the tree.
#
# Version stamping: the installer replaces the launcher's __MCSS_VERSION__ /
# __MCSS_COMMIT__ / __MCSS_BUILD_DATE__ placeholders at deploy time. This
# script does the same (marking dirty checkouts as <commit>+dirty), and the
# --check diff normalizes those three lines on both sides so a stamp from an
# older deploy of IDENTICAL code is not reported as drift.
#
# Version history (one line per version; details live in git; max 6 lines):
# v1.4 2026-07-29 #89: stamp format via modules/version_stamp.sh (one encoding)
# v1.3 2026-07-19 #89: documented as a deliberate duplicate reader (#38
# PR2 adds controller_proxy.sh to the manifest)
# v1.2 2026-07-10 #45 PR3/#49: runtime_modules.list is the one manifest
# v1.1 2026-07-07 Refresh launcher stamp on module-only redeploys too
# v1.0 2026-07-07 Initial deploy/--check tool (issue #54)
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
TARGET_DIR="${MCSS_TARGET_DIR:-$HOME/.local/share/PolyMC}"
CHECK_ONLY=false
while [[ $# -gt 0 ]]; do
case "$1" in
--check) CHECK_ONLY=true; shift ;;
--target) TARGET_DIR="${2:?--target requires a directory}"; shift 2 ;;
-h|--help)
sed -n '2,31p' "${BASH_SOURCE[0]:-$0}" | sed 's/^# \{0,1\}//'
exit 0 ;;
*) echo "deploy.sh: unknown argument: $1 (try --help)" >&2; exit 2 ;;
esac
done
LAUNCHER_SRC="$SCRIPT_DIR/minecraftSplitscreen.sh"
LAUNCHER_DST="$TARGET_DIR/minecraftSplitscreen.sh"
MODULES_SRC_DIR="$SCRIPT_DIR/modules"
MODULES_DST_DIR="$TARGET_DIR/modules"
MANIFEST_SOURCE="$MODULES_SRC_DIR/runtime_modules.list"
# #89: the ONLY module this script sources, and a deliberate narrow exception to
# its otherwise standalone stance. It carries the launcher's stamp FORMAT, which
# the installer writes and this script's --check has to un-write; duplicating it
# is precisely the drift #89 was filed about. Hard error rather than a silent
# fallback: a checkout missing this file is broken, and quietly skipping stamps
# would make --check report phantom drift forever.
_STAMP_LIB="$MODULES_SRC_DIR/version_stamp.sh"
if [[ ! -f "$_STAMP_LIB" ]]; then
echo "deploy.sh: FATAL: $_STAMP_LIB missing — incomplete checkout" >&2
exit 1
fi
# shellcheck source=modules/version_stamp.sh
source "$_STAMP_LIB"
# --- Runtime module manifest (#49: the ONE manifest, shared with the launcher,
# the installer entry, and launcher_setup.sh — no more parsing a bash array
# out of launcher_setup with sed) ---
# runtime_module_list: List the runtime module filenames from the manifest,
# skipping blank/comment lines.
# #89: this duplicates install-minecraft-splitscreen.sh's canonical
# read_runtime_manifest (identical parse rule) rather than sharing it — this
# is a standalone dev tool with no installer/module sourcing of its own
# (it does not source ANY modules, by design: it only copies files), so
# there is no in-process function to reach. Any change to the parse rule
# must be mirrored in both places.
# Outputs: stdout — one module filename per line (data only)
runtime_module_list() {
grep -vE '^[[:space:]]*(#|$)' "$MANIFEST_SOURCE" 2>/dev/null
}
mapfile -t RUNTIME_MODS < <(runtime_module_list)
if [[ ${#RUNTIME_MODS[@]} -eq 0 ]]; then
echo "deploy.sh: could not read the runtime module manifest: $MANIFEST_SOURCE" >&2
echo " (missing or empty — refusing to deploy an empty tree)" >&2
exit 2
fi
# --- Stamp normalization for the launcher diff ---
# normalize_stamps: Rewrite the three stamp assignments to their placeholder
# form so a deployed (stamped) launcher and the checkout (placeholder)
# launcher compare equal when the rest of the file is identical. Applied to
# BOTH sides for symmetry.
# Inputs: $1 — path to the file to normalize
# Outputs: stdout — the file's contents with stamps replaced by placeholders
normalize_stamps() { mcss_stamp_normalize "$1"; }
# files_differ: Check whether DST is missing or differs from SRC.
# Inputs:
# $1 — src path, $2 — dst path
# $3 — "normalize" to compare via normalize_stamps instead of raw bytes
# Outputs: return — 0 if DST is missing or differs from SRC, 1 if identical
files_differ() {
local src="$1" dst="$2" normalize="${3:-}"
[[ -f "$dst" ]] || return 0
if [[ "$normalize" == normalize ]]; then
! cmp -s <(normalize_stamps "$src") <(normalize_stamps "$dst")
else
! cmp -s "$src" "$dst"
fi
}
# --- Build the work list: "src|dst|label|normalize" ---
WORK=("$LAUNCHER_SRC|$LAUNCHER_DST|minecraftSplitscreen.sh|normalize")
# The manifest itself deploys too — the launcher reads it at startup.
WORK+=("$MANIFEST_SOURCE|$MODULES_DST_DIR/runtime_modules.list|modules/runtime_modules.list|")
for mod in "${RUNTIME_MODS[@]}"; do
WORK+=("$MODULES_SRC_DIR/$mod|$MODULES_DST_DIR/$mod|modules/$mod|")
done
# =============================================================================
# --check mode: report drift, exit nonzero if the deployed tree is stale
# =============================================================================
if [[ "$CHECK_ONLY" == true ]]; then
drift=0
for entry in "${WORK[@]}"; do
IFS='|' read -r src dst label normalize <<<"$entry"
if [[ ! -f "$src" ]]; then
echo " ✗ $label — missing from CHECKOUT ($src)"; drift=$((drift + 1))
elif [[ ! -f "$dst" ]]; then
echo " ✗ $label — not deployed ($dst missing)"; drift=$((drift + 1))
elif files_differ "$src" "$dst" "$normalize"; then
echo " ✗ $label — deployed copy differs from checkout"; drift=$((drift + 1))
fi
done
if [[ $drift -gt 0 ]]; then
echo ""
echo "STALE: $drift file(s) drifted — deployed tree ($TARGET_DIR) does not match this checkout."
echo "Run: $SCRIPT_DIR/deploy.sh (git pull is not a deploy)"
exit 1
fi
echo "✓ Deployed tree is fresh: $TARGET_DIR matches the checkout (${#WORK[@]} files)."
exit 0
fi
# =============================================================================
# deploy mode: copy what changed, print it
# =============================================================================
if [[ ! -d "$TARGET_DIR" ]]; then
echo "deploy.sh: target $TARGET_DIR does not exist — run the installer once first" >&2
echo " (deploy.sh only refreshes an existing install; it does not create one)" >&2
exit 2
fi
mkdir -p "$MODULES_DST_DIR"
changed=0 unchanged=0 launcher_differs=false
for entry in "${WORK[@]}"; do
IFS='|' read -r src dst label normalize <<<"$entry"
if [[ ! -f "$src" ]]; then
echo "deploy.sh: $label missing from checkout ($src)" >&2
exit 2
fi
# The launcher is deployed AFTER this loop (its stamp must reflect the
# whole tree, so it is refreshed whenever ANY file changes) — here it only
# contributes to the changed/unchanged accounting.
if [[ "$src" == "$LAUNCHER_SRC" ]]; then
if files_differ "$src" "$dst" "$normalize"; then
launcher_differs=true
fi
continue
fi
if files_differ "$src" "$dst" "$normalize"; then
status="updated"; [[ -f "$dst" ]] || status="NEW"
cp "$src" "$dst"
chmod +x "$dst"
echo " → $label ($status)"
changed=$((changed + 1))
else
unchanged=$((unchanged + 1))
fi
done
# Deploy + stamp the launcher whenever anything in the tree changed — not just
# when the launcher itself did. The stamp describes the deployed TREE; found
# on-Deck: a module-only redeploy left the launcher carrying the previous
# deploy's commit/date while this script claimed the new stamp. Re-copying from
# the checkout restores the placeholders so the sed always takes effect.
# Stamped exactly like the installer (launcher_setup.sh), plus a +dirty marker
# so a test log can never claim a clean commit it didn't run.
if [[ "$launcher_differs" == true || $changed -gt 0 || ! -f "$LAUNCHER_DST" ]]; then
status="updated"; [[ -f "$LAUNCHER_DST" ]] || status="NEW"
[[ "$launcher_differs" == true || ! -f "$LAUNCHER_DST" ]] || status="re-stamped"
cp "$LAUNCHER_SRC" "$LAUNCHER_DST"
chmod +x "$LAUNCHER_DST"
changed=$((changed + 1))
# #89: same format + resolution as the installer, via modules/version_stamp.sh.
# mark_dirty is ours alone — a dev checkout is routinely uncommitted.
IFS=$'\t' read -r _ver _commit _date \
< <(mcss_stamp_resolve "$SCRIPT_DIR" mark_dirty)
mcss_stamp_apply "$LAUNCHER_DST" "$_ver" "$_commit" "$_date" || true
echo " → minecraftSplitscreen.sh ($status; stamped version=${_ver} commit=${_commit})"
else
unchanged=$((unchanged + 1))
fi
echo ""
echo "Deployed to $TARGET_DIR: $changed changed, $unchanged already current."