mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* refactor(git): split runner.ts into focused command-runner modules * chore(ratchets): repoint child_process and wsl.exe allowlists at the split modules --------- Co-authored-by: Neil <n@example.com>
69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
import { isWindowsBatchScript, resolveWindowsCommand } from '../../win32-utils'
|
|
import { resolveCommand, type ResolvedCommand } from './wsl-command-resolution'
|
|
import { execFileCapture } from './exec-file-capture'
|
|
import { spawnCommandCapture, type CommandExecOptions } from './spawn-command-capture'
|
|
|
|
function isMissingCommandError(error: unknown): boolean {
|
|
return Boolean(
|
|
error && typeof error === 'object' && (error as { code?: unknown }).code === 'ENOENT'
|
|
)
|
|
}
|
|
|
|
function hasPathSeparator(command: string): boolean {
|
|
return command.includes('/') || command.includes('\\')
|
|
}
|
|
|
|
function shouldRetryWindowsCommandShim(error: unknown, resolved: ResolvedCommand): boolean {
|
|
return (
|
|
process.platform === 'win32' &&
|
|
resolved.wsl === null &&
|
|
isMissingCommandError(error) &&
|
|
!hasPathSeparator(resolved.binary) &&
|
|
!/\.[A-Za-z0-9]+$/.test(resolved.binary)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Async command execution with the same WSL cwd translation as repo-scoped git.
|
|
* Keep this for fixed binary+argv call sites; never pass shell fragments.
|
|
*/
|
|
export async function commandExecFileAsync(
|
|
command: string,
|
|
args: string[],
|
|
options: CommandExecOptions = {}
|
|
): Promise<{ stdout: string; stderr: string }> {
|
|
const { wslDistro, ...execOptions } = options
|
|
const resolved = resolveCommand(command, args, options.cwd, wslDistro)
|
|
const binary =
|
|
resolved.wsl === null ? resolveWindowsCommand(resolved.binary, options.env) : resolved.binary
|
|
if (isWindowsBatchScript(binary)) {
|
|
return spawnCommandCapture(binary, resolved.args, {
|
|
...execOptions,
|
|
cwd: resolved.cwd
|
|
})
|
|
}
|
|
try {
|
|
const { stdout, stderr } = await execFileCapture(binary, resolved.args, {
|
|
cwd: resolved.cwd,
|
|
encoding: execOptions.encoding ?? 'utf-8',
|
|
maxBuffer: execOptions.maxBuffer,
|
|
timeout: execOptions.timeout,
|
|
env: execOptions.env,
|
|
signal: execOptions.signal
|
|
})
|
|
return { stdout: stdout as string, stderr: stderr as string }
|
|
} catch (error) {
|
|
if (shouldRetryWindowsCommandShim(error, resolved)) {
|
|
return spawnCommandCapture(
|
|
resolveWindowsCommand(`${resolved.binary}.cmd`, options.env),
|
|
resolved.args,
|
|
{
|
|
...execOptions,
|
|
cwd: resolved.cwd
|
|
}
|
|
)
|
|
}
|
|
throw error
|
|
}
|
|
}
|