From c9e662d80266fbcbd273f7988c33841bfc86323d Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 1 Sep 2026 16:07:45 +0000 Subject: [PATCH] fix(upgrade): abort when a stale .bak already exists at the install path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A leftover $INSTALL_DIR.bak from a crashed upgrade would make the mv nest the live install inside it, and the failure-restore arm would 'restore' the stale backup — possibly deleting the only good copy. The upgrade now refuses to start and tells the user to inspect/salvage the backup. Co-Authored-By: Claude Fable 5 --- gstack-upgrade/SKILL.md | 5 +++++ gstack-upgrade/SKILL.md.tmpl | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/gstack-upgrade/SKILL.md b/gstack-upgrade/SKILL.md index 9055789a8..79ec181ee 100644 --- a/gstack-upgrade/SKILL.md +++ b/gstack-upgrade/SKILL.md @@ -170,6 +170,11 @@ If `$STASH_OUTPUT` contains "Saved working directory", warn the user: "Note: loc **For vendored installs** (vendored, vendored-global): ```bash PARENT=$(dirname "$INSTALL_DIR") +# A stale .bak from a previously crashed upgrade would make the mv below NEST +# the live install inside it and the failure-restore arm would "restore" the +# stale backup. It may also be the only good copy from that crashed run — +# abort and let the human inspect, never delete it silently. +[ -e "$INSTALL_DIR.bak" ] && { echo "ERROR: stale backup exists at $INSTALL_DIR.bak (from a previous failed upgrade?) — inspect it, salvage/remove it, then re-run." >&2; exit 1; } TMP_DIR=$(mktemp -d) || { echo "ERROR: mktemp failed — aborting upgrade (install untouched)." >&2; exit 1; } git clone --depth 1 https://github.com/garrytan/gstack.git "$TMP_DIR/gstack" || { echo "ERROR: clone failed — aborting upgrade (install untouched)." >&2; rm -rf "$TMP_DIR"; exit 1; } mv "$INSTALL_DIR" "$INSTALL_DIR.bak" diff --git a/gstack-upgrade/SKILL.md.tmpl b/gstack-upgrade/SKILL.md.tmpl index eb112fdea..158f3e052 100644 --- a/gstack-upgrade/SKILL.md.tmpl +++ b/gstack-upgrade/SKILL.md.tmpl @@ -167,6 +167,11 @@ If `$STASH_OUTPUT` contains "Saved working directory", warn the user: "Note: loc **For vendored installs** (vendored, vendored-global): ```bash PARENT=$(dirname "$INSTALL_DIR") +# A stale .bak from a previously crashed upgrade would make the mv below NEST +# the live install inside it and the failure-restore arm would "restore" the +# stale backup. It may also be the only good copy from that crashed run — +# abort and let the human inspect, never delete it silently. +[ -e "$INSTALL_DIR.bak" ] && { echo "ERROR: stale backup exists at $INSTALL_DIR.bak (from a previous failed upgrade?) — inspect it, salvage/remove it, then re-run." >&2; exit 1; } TMP_DIR=$(mktemp -d) || { echo "ERROR: mktemp failed — aborting upgrade (install untouched)." >&2; exit 1; } git clone --depth 1 https://github.com/garrytan/gstack.git "$TMP_DIR/gstack" || { echo "ERROR: clone failed — aborting upgrade (install untouched)." >&2; rm -rf "$TMP_DIR"; exit 1; } mv "$INSTALL_DIR" "$INSTALL_DIR.bak"