mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-10 02:30:39 +01:00
fix(windows): migrations resolve their directory with either path separator; state-root parity compares under the HOME Git Bash actually sees
This commit is contained in:
1 parent
fa81927f3f
commit
d361f9a8b8
11 files changed
+39
-20
No files matched your search
@@ -11,7 +11,8 @@
|
||||
# Affected: users who ran /office-hours before this version
|
||||
set -euo pipefail
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
PROFILE_FILE="$GSTACK_HOME/builder-profile.jsonl"
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
# Affected: every user on v0.19.x and below who upgrades to v1.x
|
||||
set -euo pipefail
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
PROMPTED_FLAG="$GSTACK_HOME/.writing-style-prompted"
|
||||
PENDING_FLAG="$GSTACK_HOME/.writing-style-prompt-pending"
|
||||
|
||||
@@ -38,7 +38,8 @@ if [ "$SYNC_MODE" = "off" ] || [ -z "$SYNC_MODE" ]; then
|
||||
fi
|
||||
|
||||
# Skip if no brain-sync git repo exists.
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select
|
||||
if [ ! -d "$_gstack_sr_root/.git" ]; then
|
||||
exit 0
|
||||
|
||||
@@ -44,7 +44,8 @@ fi
|
||||
# ---------------------------------------------------------------------------
|
||||
# Configuration
|
||||
# ---------------------------------------------------------------------------
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
SKILLS_DIR="${HOME}/.claude/skills"
|
||||
BIN_DIR="${SKILLS_DIR}/gstack/bin"
|
||||
|
||||
@@ -38,7 +38,8 @@ if [ -z "${HOME:-}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
MIGRATIONS_DIR="$GSTACK_HOME/.migrations"
|
||||
DONE_TOUCH="$MIGRATIONS_DIR/v1.37.0.0.done"
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
# still run. `set -u` is fine.
|
||||
set -u
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
ALLOWLIST="${GSTACK_HOME}/.brain-allowlist"
|
||||
PRIVACY="${GSTACK_HOME}/.brain-privacy-map.json"
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
set -u
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
ALLOWLIST="${GSTACK_HOME}/.brain-allowlist"
|
||||
PRIVACY="${GSTACK_HOME}/.brain-privacy-map.json"
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
set -u
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
MIGRATION_DIR="${GSTACK_HOME}/.migrations"
|
||||
DONE="${MIGRATION_DIR}/v1.58.0.0.done"
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
|
||||
set -u
|
||||
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GSTACK_HOME="$_gstack_sr_root"
|
||||
MIGRATION_DIR="${GSTACK_HOME}/.migrations"
|
||||
DONE="${MIGRATION_DIR}/v1.65.0.0.done"
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
set -u
|
||||
|
||||
INSTALL_DIR="${GSTACK_INSTALL_DIR:-$HOME/.claude/skills/gstack}"
|
||||
. "${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${BASH_SOURCE[0]%/*}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
_gstack_migration_dir="${BASH_SOURCE[0]//\\//}"; _gstack_migration_dir="${_gstack_migration_dir%/*}"
|
||||
. "${_gstack_migration_dir}/../../bin/gstack-state-root.sh" 2>/dev/null || { echo "$0: cannot resolve the gstack state root: ${_gstack_migration_dir}/../../bin/gstack-state-root.sh is missing. fix: reinstall with ./setup or /gstack-upgrade (docs/state-root.md)" >&2; exit 1; }
|
||||
gstack_state_root_select; GH="$_gstack_sr_root"
|
||||
|
||||
mkdir -p "$GH" 2>/dev/null || exit 0
|
||||
|
||||
@@ -17,19 +17,28 @@ const BASH = Bun.which('bash') ?? '/bin/bash';
|
||||
|
||||
type Row = { name: string; env: Record<string, string>; win?: boolean };
|
||||
|
||||
function bashEval(row: Row, body: string): string {
|
||||
// On a Windows host the MSYS runtime fills HOME before Git Bash starts, so a
|
||||
// row that leaves HOME unset or empty reaches the bash twin with the runtime's
|
||||
// HOME. Those rows compare both twins under the HOME the child actually saw;
|
||||
// the unset-HOME branches themselves are covered on POSIX hosts.
|
||||
const HOST_FILLS_HOME = process.platform === 'win32';
|
||||
|
||||
function bashEval(row: Row, body: string): { out: string; home: string } {
|
||||
const ostype = row.win ? 'msys' : 'linux-gnu';
|
||||
const r = spawnSync(BASH, ['-c', `OSTYPE=${ostype}; . "${TWIN}" && ${body}`], {
|
||||
const r = spawnSync(BASH, ['-c', `OSTYPE=${ostype}; printf '%s\\0' "\${HOME-}"; . "${TWIN}" && ${body}`], {
|
||||
env: { USERPROFILE: '', ...row.env, PATH: '' },
|
||||
encoding: 'utf-8',
|
||||
timeout: 10_000,
|
||||
});
|
||||
if (r.status !== 0) throw new Error(`bash twin failed for ${row.name}: ${r.stderr}`);
|
||||
return r.stdout;
|
||||
const split = r.stdout.indexOf('\0');
|
||||
return { home: r.stdout.slice(0, split), out: r.stdout.slice(split + 1) };
|
||||
}
|
||||
|
||||
function tsEnv(row: Row): Record<string, string> {
|
||||
return { USERPROFILE: '', ...row.env };
|
||||
function tsEnv(row: Row, childHome: string): Record<string, string> {
|
||||
const env: Record<string, string> = { USERPROFILE: '', ...row.env };
|
||||
if (HOST_FILLS_HOME && !row.env.HOME) env.HOME = childHome;
|
||||
return env;
|
||||
}
|
||||
|
||||
const A = '/state/a', B = '/state/b', C = '/state/c';
|
||||
@@ -63,8 +72,8 @@ const rootRows: Row[] = [
|
||||
describe('state root parity (bash twin vs lib/state-root.ts)', () => {
|
||||
for (const row of rootRows) {
|
||||
test(row.name, () => {
|
||||
const bash = bashEval(row, 'gstack_state_root; printf x').replace(/x$/, '');
|
||||
expect(bash).toBe(resolveStateRoot(tsEnv(row), row.win ? 'win32' : 'linux'));
|
||||
const bash = bashEval(row, 'gstack_state_root; printf x');
|
||||
expect(bash.out.replace(/x$/, '')).toBe(resolveStateRoot(tsEnv(row, bash.home), row.win ? 'win32' : 'linux'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -126,9 +135,9 @@ describe('config key parity (gstack_read_config_key vs readConfigKey)', () => {
|
||||
];
|
||||
for (const row of envs) {
|
||||
for (const key of keys) {
|
||||
const bash = bashEval(row, `gstack_read_config_key ${key}; printf x`).replace(/x$/, '');
|
||||
const ts = readConfigKey(key, tsEnv(row), row.win ? 'win32' : 'linux') ?? '';
|
||||
expect(`${row.name}/${key}=${bash}`).toBe(`${row.name}/${key}=${ts}`);
|
||||
const bash = bashEval(row, `gstack_read_config_key ${key}; printf x`);
|
||||
const ts = readConfigKey(key, tsEnv(row, bash.home), row.win ? 'win32' : 'linux') ?? '';
|
||||
expect(`${row.name}/${key}=${bash.out.replace(/x$/, '')}`).toBe(`${row.name}/${key}=${ts}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user