mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 14:06:50 +01:00
Git Bash hands native Bun C:/ paths while gstack-hook-check looked them up as /c/, so every TypeScript hook was refused and team-mode auto-update held every release since 1.91.31. The checker maps Bun's paths back to the shell spelling, the auto-updater lets the incoming release's own checker decide (installed checker only as a fallback, hook-check-unavailable when neither verifies), and docs/troubleshooting.md gives stuck installs one recovery command. /gstack-upgrade and /spec guards use the --show-prefix root check, gstack-wtree treats drive-letter --git-path answers as absolute, and setup refuses to replace a runtime root that is or contains its own checkout, Kiro's in-place root included (#3084), with --status suggesting the move. New sourced helper bin/gstack-path-spelling.sh and TS twin lib/path-spelling.ts. Co-authored-by: yuriysan <63948747+yuriysan@users.noreply.github.com> Co-authored-by: y$un_ <3579304+szsunyuan@users.noreply.github.com> Co-authored-by: Frederik Reventlow <267160539+dmfrede@users.noreply.github.com> Co-authored-by: skleinbe-ny <226563731+skleinbe-ny@users.noreply.github.com> Co-authored-by: bkermen <184220642+bkermen@users.noreply.github.com> Co-authored-by: Drew Jankowski <3200063+andrewkjankowski@users.noreply.github.com>
40 lines
1.8 KiB
TypeScript
40 lines
1.8 KiB
TypeScript
/**
|
|
* One spelling for paths on Windows shells. Git Bash (MSYS) spells a drive
|
|
* path /c/x, native programs (git.exe, bun.exe) answer C:/x or C:\x, and MSYS
|
|
* converts /c/x arguments to C:/x before a native program starts. Comparing two
|
|
* spellings as strings is the bug class behind #3088, #3100 and #3101.
|
|
* Bash twin: bin/gstack-path-spelling.sh.
|
|
*/
|
|
import * as fs from 'node:fs';
|
|
|
|
/** Git Bash's drive spelling (/c/x) of a native path on Windows; unchanged elsewhere. */
|
|
export function shellPath(value: string, platform: string = process.platform): string {
|
|
if (platform !== 'win32') return value;
|
|
return value.replace(/\\/g, '/').replace(/^([A-Za-z]):(?=\/|$)/, (_, drive: string) => `/${drive.toLowerCase()}`);
|
|
}
|
|
|
|
/** The native spelling (C:/x) of a Git Bash drive path on Windows; unchanged elsewhere. */
|
|
export function nativePath(value: string, platform: string = process.platform): string {
|
|
if (platform !== 'win32') return value;
|
|
const slashed = value.replace(/\\/g, '/');
|
|
const drive = /^\/([A-Za-z])(?=\/|$)/.exec(slashed);
|
|
if (!drive) return slashed;
|
|
return `${drive[1]!.toUpperCase()}:${slashed.slice(2) || '/'}`;
|
|
}
|
|
|
|
/** True when a and b name the same file: filesystem identity when both exist, else equal spellings. */
|
|
export function samePath(a: string, b: string, platform: string = process.platform): boolean {
|
|
const left = nativePath(a, platform);
|
|
const right = nativePath(b, platform);
|
|
try {
|
|
const sa = fs.statSync(left, { bigint: true });
|
|
const sb = fs.statSync(right, { bigint: true });
|
|
return sa.dev === sb.dev && sa.ino === sb.ino;
|
|
} catch {
|
|
const trim = (v: string) => (v.length > 1 ? v.replace(/\/+$/, '') : v);
|
|
return platform === 'win32'
|
|
? trim(left).toLowerCase() === trim(right).toLowerCase()
|
|
: trim(left) === trim(right);
|
|
}
|
|
}
|