mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-18 19:02:18 +02:00
fix(hooks): shared spawn-bin helper — all three AskUserQuestion hooks were inert on Windows
The plan-tune hooks resolved bin scripts via new URL(import.meta.url).pathname (which doubles the drive letter on Windows: /C:/C:/...) and spawnSync'd extensionless bash scripts directly (unrunnable without a shell association) — so question logging, preferences, and the error fallback all silently no-op'd on Windows, and /plan-tune collected no data. A single spawn-bin.ts helper now owns bin resolution (fileURLToPath) and win32 bash routing for every hook, with static tripwires so a future hook can't reintroduce the raw pattern. This is the one Windows-spawn idiom for hook code. Fixes #2356. Contributed by @rafassousa (PR #2504; supersedes PR #2399 by @chuchu2781). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
99e2718943
commit
d7ce124092
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Windows-safe resolution + spawn for gstack's bash bins. Two Windows-only
|
||||
* bugs made every hook subprocess a silent no-op; both are fixed here so all
|
||||
* call sites are covered at once.
|
||||
*
|
||||
* 1. `new URL(import.meta.url).pathname` yields `/C:/Users/...`; path.resolve
|
||||
* then rebases it onto the drive root as `C:\C:\Users\...`. fileURLToPath
|
||||
* is the correct conversion. (ENOENT before the bin ever ran.)
|
||||
* 2. `bin/gstack-*` are extensionless bash scripts. Windows has no shebang
|
||||
* support, so they must be handed to bash explicitly.
|
||||
*/
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { spawnSync, type SpawnSyncOptions } from 'child_process';
|
||||
|
||||
// Forward slashes on purpose: Bun's spawnSync on Windows returns ENOENT for a
|
||||
// backslash exe path containing spaces.
|
||||
const GIT_BASH = 'C:/Program Files/Git/bin/bash.exe';
|
||||
|
||||
/** bash Windows itself can execute — env override, Git Bash, then PATH. */
|
||||
function bashExe(): string {
|
||||
return process.env.GSTACK_BASH || (fs.existsSync(GIT_BASH) ? GIT_BASH : 'bash');
|
||||
}
|
||||
|
||||
/** gstack install root. This file lives at hosts/claude/hooks/. */
|
||||
export function repoRoot(): string {
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
return path.resolve(here, '..', '..', '..');
|
||||
}
|
||||
|
||||
/** Absolute path to a `bin/` script. */
|
||||
export function binPath(name: string): string {
|
||||
return path.join(repoRoot(), 'bin', name);
|
||||
}
|
||||
|
||||
/** Resolve `name` under bin/ and run it, via bash on Windows. */
|
||||
export function runBin(name: string, args: string[], opts: SpawnSyncOptions) {
|
||||
const bin = binPath(name);
|
||||
return process.platform === 'win32'
|
||||
? spawnSync(bashExe(), [bin, ...args], opts)
|
||||
: spawnSync(bin, args, opts);
|
||||
}
|
||||
Reference in New Issue
Block a user