mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 22:48:57 +02:00
fix(session-update): un-wedge auto-upgrade — autostash over local patches, log the pull's real reason
On a normal install the tracked files ARE locally patched (skill-prefix name rewrites, gbrain-refresh blocks), so the bare `git pull --ff-only` refused on every run and auto-upgrade froze forever — observed as 308 consecutive PULL_FAILED entries with the reason discarded by 2>/dev/null. Pull now runs --autostash (local patches ride over the update and pop back), stderr is captured into the log so a genuine failure names its cause, an autostash pop conflict recovers to a clean tree and re-renders the patches (gstack-patch-names + gbrain-refresh, both idempotent), and a successful pull re-renders them as a self-heal. Behavioral tests cover the wedge shape and the reason logging. Fixes #2566. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4f891303f2
commit
031bb3689e
@@ -82,8 +82,15 @@ fi
|
||||
OLD_HEAD=$(git -C "$GSTACK_DIR" rev-parse HEAD 2>/dev/null)
|
||||
UPDATE_URL=$(git -C "$GSTACK_DIR" remote get-url origin 2>/dev/null || echo "")
|
||||
UPDATE_HOST="${UPDATE_URL#*://}"; UPDATE_HOST="${UPDATE_HOST#*@}"; UPDATE_HOST="${UPDATE_HOST%%[/:]*}"
|
||||
# --autostash: locally-patched TRACKED files are the NORM on installs, not
|
||||
# the exception — skill-prefix mode rewrites frontmatter names and
|
||||
# `gstack-config gbrain-refresh` renders brain blocks into SKILL.md. A bare
|
||||
# --ff-only refuses over those edits, so auto-upgrade wedged permanently
|
||||
# (observed: 308 consecutive PULL_FAILED with the reason discarded, #2566).
|
||||
# Capture stderr: the log must carry WHY a pull failed, never just the code.
|
||||
PULL_ERR_FILE=$(mktemp "${TMPDIR:-/tmp}/gstack-session-pull-XXXXXX" 2>/dev/null || echo "")
|
||||
GSTACK_HOME="$STATE_DIR" _receipted_git open session-update "${UPDATE_HOST:-unknown}" gstack-self-update-pull "auto_upgrade=true" \
|
||||
bash -c 'git -C "$1" pull --ff-only -q 2>/dev/null' _ "$GSTACK_DIR"
|
||||
bash -c 'git -C "$1" pull --ff-only --autostash -q 2>"${2:-/dev/null}"' _ "$GSTACK_DIR" "$PULL_ERR_FILE"
|
||||
PULL_EXIT=$?
|
||||
NEW_HEAD=$(git -C "$GSTACK_DIR" rev-parse HEAD 2>/dev/null)
|
||||
|
||||
@@ -91,9 +98,30 @@ fi
|
||||
date +%s > "$THROTTLE_FILE" 2>/dev/null
|
||||
|
||||
if [ "$PULL_EXIT" -ne 0 ]; then
|
||||
log_entry "PULL_FAILED exit=$PULL_EXIT"
|
||||
PULL_REASON=$(head -c 300 "$PULL_ERR_FILE" 2>/dev/null | tr '\n' ' ' | tr -s ' ')
|
||||
log_entry "PULL_FAILED exit=$PULL_EXIT reason=${PULL_REASON:-unknown}"
|
||||
# Autostash pop conflict leaves the stash behind and the tree half-merged.
|
||||
# The local patches are REGENERABLE (prefix renames, gbrain blocks), so
|
||||
# recover to a clean upstream tree and re-render them below rather than
|
||||
# leaving conflict markers in a live install.
|
||||
if grep -qi "autostash" "$PULL_ERR_FILE" 2>/dev/null; then
|
||||
git -C "$GSTACK_DIR" checkout -q -- . 2>/dev/null
|
||||
git -C "$GSTACK_DIR" stash drop -q 2>/dev/null
|
||||
log_entry "AUTOSTASH_CONFLICT_RECOVERED tree_reset=1"
|
||||
_PREFIX_CFG=$("$GSTACK_DIR/bin/gstack-config" get skill_prefix 2>/dev/null || echo false)
|
||||
"$GSTACK_DIR/bin/gstack-patch-names" "$GSTACK_DIR" "$_PREFIX_CFG" >/dev/null 2>&1 || true
|
||||
"$GSTACK_DIR/bin/gstack-config" gbrain-refresh >/dev/null 2>&1 || true
|
||||
fi
|
||||
rm -f "$PULL_ERR_FILE" 2>/dev/null
|
||||
exit 0
|
||||
fi
|
||||
rm -f "$PULL_ERR_FILE" 2>/dev/null
|
||||
# Re-render local patches over the fresh tree (both tools are idempotent
|
||||
# no-ops when the feature is unconfigured); the autostash pop usually
|
||||
# preserves them, but a clean re-render costs nothing and self-heals.
|
||||
_PREFIX_CFG=$("$GSTACK_DIR/bin/gstack-config" get skill_prefix 2>/dev/null || echo false)
|
||||
"$GSTACK_DIR/bin/gstack-patch-names" "$GSTACK_DIR" "$_PREFIX_CFG" >/dev/null 2>&1 || true
|
||||
"$GSTACK_DIR/bin/gstack-config" gbrain-refresh >/dev/null 2>&1 || true
|
||||
|
||||
# ── If HEAD moved, run setup -q ──
|
||||
if [ "$OLD_HEAD" != "$NEW_HEAD" ]; then
|
||||
|
||||
Reference in New Issue
Block a user