mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 06:24:41 +01:00
doctor --check: name the held-install recovery on Windows, not bin/gstack-upgrade
bin/gstack-upgrade compares a pwd -P path (/c/...) with git's toplevel (C:/...) and refuses on every Git Bash install, so on Windows the revision row's upgrade fix (REVISION_BELOW_MINIMUM, the Capy-wrapper variant and REVISION_UNMET) names the held-install recovery forms from docs/troubleshooting.md#auto-update-held-install-recovery instead: the Git Bash form and the Windows PowerShell 5.1 form, each labelled by shell with the install path quoted for that shell. Other platforms keep bin/gstack-upgrade. A test pins both printed forms to the documented ones. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
75e425b1d5
commit
37bac07f87
3 files changed
+68
-7
No files matched your search
+2
-1
@@ -88,8 +88,9 @@ row() {
|
||||
esac
|
||||
}
|
||||
|
||||
# sq TEXT — TEXT single-quoted for bash.
|
||||
# sq TEXT — TEXT single-quoted for bash; psq TEXT — single-quoted for PowerShell.
|
||||
sq() { printf "'%s'" "$(printf '%s' "$1" | sed "s/'/'\\\\''/g")"; }
|
||||
psq() { printf "'%s'" "$(printf '%s' "$1" | sed "s/'/''/g")"; }
|
||||
|
||||
# clamp CHARSET MAX — stdin's first line reduced to CHARSET, at most MAX chars.
|
||||
clamp() { head -1 | tr -cd "$1" | cut -c1-"$2"; }
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# gstack-doctor-check.sh — `gstack-doctor --check`: the one-line install verdict.
|
||||
#
|
||||
# Sourced by bin/gstack-doctor after its prelude (ROOT, ROOT_REAL, BIN, SRC,
|
||||
# DOCS, STATE_ROOT, EXE, clamp, the launch probe, the codex status helpers)
|
||||
# and never executed on its own. Prints `required: <ids>`, one
|
||||
# DOCS, STATE_ROOT, EXE, WINDOWS, clamp, sq, psq, the launch probe, the codex
|
||||
# status helpers) and never executed on its own. Prints `required: <ids>`, one
|
||||
# `PASS | FAIL | SKIP <id>` row per component in bin/gstack-doctor-components.sh
|
||||
# (generated from lib/doctor-components.ts; the same ids feed --for, --require
|
||||
# and --json), then exactly one trailer: `gstack: ok <revision> for=<what>` on
|
||||
@@ -16,7 +16,8 @@
|
||||
# Inputs (set by bin/gstack-doctor): CHECK_FOR (skill), CHECK_REQUIRE (csv),
|
||||
# CHECK_JSON (0|1), CHECK_PROJECT (path or ""), CHECK_REVISION (ref or ""),
|
||||
# CHECK_MIN_REVISION (the supported minimum the Capy wrapper read from the
|
||||
# remote's capy/support.env, `unknown` when its fetch failed, or ""), LIVE.
|
||||
# remote's capy/support.env, `unknown` when its fetch failed, or ""), LIVE,
|
||||
# WINDOWS (1 on Windows; GSTACK_DOCTOR_PLATFORM overrides the detection).
|
||||
# GSTACK_CAPY_WRAPPER_PATH (optional) names the wrapper a below-minimum fix runs.
|
||||
|
||||
. "$BIN/gstack-doctor-components.sh" || { echo "gstack-doctor: $BIN/gstack-doctor-components.sh is missing; reinstall with cd $SRC && ./setup" >&2; exit 1; }
|
||||
@@ -378,6 +379,21 @@ _dc_version_below() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# _dc_upgrade_cmd — the command that moves this install to the latest release.
|
||||
# On Windows bin/gstack-upgrade refuses every Git Bash install (it compares a
|
||||
# pwd -P /c/... path with git's C:/... toplevel), so the held-install recovery
|
||||
# forms from docs/troubleshooting.md#auto-update-held-install-recovery are
|
||||
# named instead, one per shell, with the install path quoted for each.
|
||||
_dc_upgrade_cmd() {
|
||||
local win
|
||||
if [ "$WINDOWS" -ne 1 ]; then printf '%s' "$SRC/bin/gstack-upgrade"; return; fi
|
||||
win=$(cygpath -w "$SRC" 2>/dev/null) || win="$SRC"
|
||||
printf '%s' "run the held-install recovery (bin/gstack-upgrade refuses on Git Bash installs): in Git Bash: cd $(sq "$SRC")"
|
||||
printf '%s' ' && git fetch origin main && d=$(mktemp -d) && git show FETCH_HEAD:bin/gstack-ff-update > "$d/gstack-ff-update" && bash "$d/gstack-ff-update" . FETCH_HEAD; s=$?; rm -rf "$d"; [ "$s" = 0 ] && ./setup'
|
||||
printf '%s' " — or in Windows PowerShell 5.1: Set-Location -LiteralPath $(psq "$win")"
|
||||
printf '%s' " -ErrorAction Stop; \$gb = Join-Path (git --exec-path) '..\\..\\..\\bin\\bash.exe'; & \$gb -c 'set -f; IFS=; git fetch origin main && d=\$(mktemp -d) && git show FETCH_HEAD:bin/gstack-ff-update > \$d/gstack-ff-update && bash \$d/gstack-ff-update . FETCH_HEAD; s=\$?; rm -rf -- \$d; exit \$s'; if (\$LASTEXITCODE -eq 0) { .\\setup.ps1 }"
|
||||
}
|
||||
|
||||
# _dc_check_min_revision INSTALLED HEAD — sets the PASS-row suffix _dc_min_note,
|
||||
# or prints the REVISION_BELOW_MINIMUM FAIL row for --min-revision and returns 1.
|
||||
# Returns 1 after printing a FAIL row.
|
||||
@@ -390,7 +406,9 @@ _dc_check_min_revision() {
|
||||
esac
|
||||
if _dc_version_below "$installed" "$CHECK_MIN_REVISION"; then
|
||||
if [ -n "${GSTACK_CAPY_WRAPPER_PATH:-}" ]; then
|
||||
fix="bash $GSTACK_CAPY_WRAPPER_PATH${CHECK_FOR:+ --for $CHECK_FOR} (fast-forwards), or $SRC/bin/gstack-upgrade"
|
||||
fix="bash $GSTACK_CAPY_WRAPPER_PATH${CHECK_FOR:+ --for $CHECK_FOR} (fast-forwards), or $(_dc_upgrade_cmd)"
|
||||
elif [ "$WINDOWS" -eq 1 ]; then
|
||||
fix="$(_dc_upgrade_cmd)"
|
||||
else
|
||||
fix="$SRC/bin/gstack-upgrade (fast-forwards to the remote default branch, then reinstalls)"
|
||||
fi
|
||||
@@ -419,7 +437,9 @@ _dc_check_revision() {
|
||||
_dc_row PASS revision "$installed ($head) is --revision $want$_dc_min_note"
|
||||
return
|
||||
fi
|
||||
_dc_row FAIL revision "installed ${installed:-unknown}${head:+ at $head} (requested $want)" "cd $SRC && git fetch origin && git checkout $want && ./setup, or run $SRC/bin/gstack-upgrade to move to the latest release (interactive: /gstack-upgrade)" REVISION_UNMET
|
||||
local latest="run $SRC/bin/gstack-upgrade to move to the latest release (interactive: /gstack-upgrade)"
|
||||
[ "$WINDOWS" -eq 1 ] && latest="to move to the latest release, $(_dc_upgrade_cmd)"
|
||||
_dc_row FAIL revision "installed ${installed:-unknown}${head:+ at $head} (requested $want)" "cd $SRC && git fetch origin && git checkout $want && ./setup, or $latest" REVISION_UNMET
|
||||
}
|
||||
|
||||
# _dc_wrapper_rev FILE — the GSTACK_CAPY_WRAPPER revision a Capy skill copy
|
||||
|
||||
@@ -760,7 +760,8 @@ describe('gstack-doctor --check: launch Bun, supported minimum, planning-only pi
|
||||
expect(below.rows.revision.status).toBe('FAIL');
|
||||
expect(below.rows.revision.rest).toContain(`installed ${VERSION}`);
|
||||
expect(below.rows.revision.rest).toContain('below the supported minimum 99.0.0.0');
|
||||
expect(below.rows.revision.rest).toContain(`${bashPath(f.root)}/bin/gstack-upgrade`);
|
||||
// On Windows the fix names the held-install recovery instead (bin/gstack-upgrade refuses Git Bash installs).
|
||||
expect(below.rows.revision.rest).toContain(process.platform === 'win32' ? 'in Git Bash: ' : `${bashPath(f.root)}/bin/gstack-upgrade`);
|
||||
expect(below.rows.revision.rest).toContain('(REVISION_BELOW_MINIMUM; ');
|
||||
expect(below.trailer).toBe('gstack: fail revision');
|
||||
const wrapped = check(f, ['--min-revision', '99.0.0.0'], { GSTACK_CAPY_WRAPPER_PATH: '/drive/skills/gstack/scripts/install.sh' });
|
||||
@@ -1033,4 +1034,43 @@ describe('gstack-doctor: rescue refs, CLAUDE.md skill lists, Windows bash, Windo
|
||||
expect(refused.status).toBe(1);
|
||||
expect(doctor(f, [], { GSTACK_DOCTOR_PLATFORM: 'posix' }).out).not.toContain('windows bash');
|
||||
});
|
||||
|
||||
/** A held-install recovery form from docs/troubleshooting.md (the line after its form marker's fence). */
|
||||
const form = (name: string) => {
|
||||
const doc = fs.readFileSync(path.join(REPO, 'docs/troubleshooting.md'), 'utf8');
|
||||
return doc.slice(doc.indexOf(`<!-- form:${name} -->`)).match(/```[a-z]+\n([^\n]+)\n```/)![1];
|
||||
};
|
||||
const check = (f: Fixture, args: string[], extra: Record<string, string> = {}) => {
|
||||
const r = doctor(f, ['--check', ...args], extra);
|
||||
return { ...r, revision: r.out.split('\n').find(l => /^(PASS|FAIL) revision\b/.test(l)) ?? '' };
|
||||
};
|
||||
|
||||
test('--check on Windows: the upgrade fix names both held-install recovery forms, each labelled by shell with the install path quoted, never bin/gstack-upgrade; elsewhere it keeps bin/gstack-upgrade', () => {
|
||||
const f = makeFixture();
|
||||
const root = bashPath(f.root);
|
||||
const win = spawnSync('bash', ['-c', 'cygpath -w "$1" 2>/dev/null || printf %s "$1"', '_', root], { encoding: 'utf8', timeout: 10_000 }).stdout.trim();
|
||||
const gitBash = form('recovery-gitbash').replace('cd ~/.claude/skills/gstack', `cd '${root}'`);
|
||||
const powershell = form('recovery-powershell').replace('"$HOME\\.claude\\skills\\gstack"', `'${win}'`);
|
||||
expect(gitBash).toContain(`cd '${root}' && `);
|
||||
expect(powershell).toContain(`Set-Location -LiteralPath '${win}' `);
|
||||
const windows = { GSTACK_DOCTOR_PLATFORM: 'windows' };
|
||||
for (const [args, extra] of [
|
||||
[['--min-revision', '99.0.0.0'], windows],
|
||||
[['--min-revision', '99.0.0.0'], { ...windows, GSTACK_CAPY_WRAPPER_PATH: '/drive/skills/gstack/scripts/install.sh' }],
|
||||
[['--revision', 'v0.0.0.1'], windows],
|
||||
] as Array<[string[], Record<string, string>]>) {
|
||||
const r = check(f, args, extra);
|
||||
expect(r.revision, r.out).toStartWith('FAIL revision');
|
||||
expect(r.revision).toContain(`in Git Bash: ${gitBash}`);
|
||||
expect(r.revision).toContain(`in Windows PowerShell 5.1: ${powershell}`);
|
||||
expect(r.revision).not.toContain(`${root}/bin/gstack-upgrade`);
|
||||
}
|
||||
expect(spawnSync('bash', ['-n', '-c', gitBash], { encoding: 'utf8', timeout: 10_000 }).status).toBe(0);
|
||||
const json = JSON.parse(doctor(f, ['--check', '--json', '--min-revision', '99.0.0.0'], windows).out);
|
||||
expect(json.rows.find((x: { id: string }) => x.id === 'revision').fix).toContain(`in Windows PowerShell 5.1: ${powershell}`);
|
||||
const posix = check(f, ['--min-revision', '99.0.0.0'], { GSTACK_DOCTOR_PLATFORM: 'posix' });
|
||||
expect(posix.revision).toContain(`fix: ${root}/bin/gstack-upgrade (fast-forwards to the remote default branch, then reinstalls)`);
|
||||
expect(posix.revision).not.toContain('in Git Bash:');
|
||||
expect(check(f, ['--revision', 'v0.0.0.1'], { GSTACK_DOCTOR_PLATFORM: 'posix' }).revision).toContain(`or run ${root}/bin/gstack-upgrade to move to the latest release`);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user