/** * Pure shape classifier for a bash-command token on a win32 host, where Pi core * executes commands through Git Bash and POSIX-shaped absolute tokens carry * MSYS mount semantics rather than `node:path.win32` semantics. * * Consumed only by {@link PathNormalizer.forBashToken}; kept as a standalone * module so the shape knowledge is unit-testable in isolation (no filesystem, * no platform read). */ import { isSafeSystemPath } from "#src/safe-system-paths"; /** * The MSYS interpretation of a win32 bash token: * * - `device` — a safe MSYS runtime device (`/dev/null`, `/dev/std{in,out,err}`); * never a filesystem path. * - `drive-mount` — an MSYS drive mount (`/c/…`, `/d/…`); `windowsPath` is its * deterministic Windows equivalent (`C:\…`). * - `posix-absolute` — any other absolute POSIX path (`/tmp/foo`, `/usr/bin`); * its Windows target is install-dependent and not deterministically knowable, * so it is treated literally. * - `plain` — everything else (relative tokens, `~/…`, native Windows drive * paths); handled by ordinary win32 resolution. */ export type BashTokenShape = | { kind: "device" } | { kind: "drive-mount"; windowsPath: string } | { kind: "posix-absolute" } | { kind: "plain" }; /** * A single-letter first path segment identifies an MSYS drive mount: `/c`, * `/c/`, or `/c/rest`. A multi-letter first segment (`/dev`, `/tmp`) is not a * mount. The device set is checked before this pattern, so `/dev/*` never * reaches it. */ const MSYS_DRIVE_MOUNT_PATTERN = /^\/([a-zA-Z])(\/.*)?$/; export function classifyWin32BashToken(token: string): BashTokenShape { if (isSafeSystemPath(token)) return { kind: "device" }; const driveMatch = MSYS_DRIVE_MOUNT_PATTERN.exec(token); if (driveMatch) { return { kind: "drive-mount", windowsPath: toWindowsDrivePath(driveMatch[1], driveMatch[2]), }; } if (token.startsWith("/")) return { kind: "posix-absolute" }; return { kind: "plain" }; } /** * Build the Windows equivalent of an MSYS drive mount: uppercase drive letter, * `:\`, and the remainder with `/` separators rewritten to `\`. A bare or * trailing-slash mount (`/c`, `/c/`) maps to the drive root (`C:\`). */ function toWindowsDrivePath(letter: string, rest: string | undefined): string { const drive = `${letter.toUpperCase()}:`; const tail = (rest ?? "").replace(/^\//, "").replaceAll("/", "\\"); return tail ? `${drive}\\${tail}` : `${drive}\\`; }