Files
orca/src/main/git/command-runner/github-cli-host-fallback.ts
T
NeilandNeil 822087c8ec refactor(git): split runner.ts into focused command-runner modules (#16395)
* 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>
2026-08-25 02:34:11 -07:00

94 lines
2.6 KiB
TypeScript

import type { ResolvedCommand } from './wsl-command-resolution'
function hasExplicitRepoArg(args: string[]): boolean {
for (let i = 0; i < args.length; i++) {
if (
(args[i] === '--repo' || args[i] === '-R') &&
typeof args[i + 1] === 'string' &&
args[i + 1].trim()
) {
return true
}
if (args[i].startsWith('--repo=') || args[i].startsWith('-R=')) {
return args[i].slice(args[i].indexOf('=') + 1).trim().length > 0
}
if (args[i].startsWith('-R') && args[i].length > 2) {
return args[i].slice(2).trim().length > 0
}
}
return false
}
function argsUseGhApiPlaceholders(args: string[]): boolean {
return args.some(
(arg) => arg.includes('{owner}') || arg.includes('{repo}') || arg.includes('{branch}')
)
}
function hasExplicitRepoViewTarget(args: string[]): boolean {
const target = args[2]
return (
args[0] === 'repo' &&
args[1] === 'view' &&
typeof target === 'string' &&
!target.startsWith('-') &&
target.includes('/')
)
}
function canRunGitHubCliWithoutRepoCwd(args: string[]): boolean {
if (hasExplicitRepoArg(args)) {
return true
}
if (args[0] === 'api') {
return !argsUseGhApiPlaceholders(args)
}
return args[0] === 'auth' || hasExplicitRepoViewTarget(args)
}
function isMissingCommandInWsl(stderr: string, command: string): boolean {
const s = stderr.toLowerCase()
const c = command.toLowerCase()
return s.includes(`${c}: command not found`) || s.includes(`${c}: not found`)
}
export function canFallBackToHostGitHubCli(
command: 'gh',
args: string[],
resolved: ResolvedCommand,
stderr: string
): boolean {
return (
process.platform === 'win32' &&
resolved.wsl !== null &&
isMissingCommandInWsl(stderr, command) &&
canRunGitHubCliWithoutRepoCwd(args)
)
}
export function resolveHostGitHubCli(command: 'gh', args: string[]): ResolvedCommand {
return {
binary: command,
args,
// Why: host gh can't use a WSL UNC cwd; we only fall back for commands with explicit repo/API context, so none is needed.
cwd: undefined,
wsl: null,
wslMode: null
}
}
export function isHostCommandMissing(err: unknown, command: 'gh' | 'glab'): boolean {
if (!err || typeof err !== 'object') {
return false
}
const e = err as { code?: unknown; message?: unknown; syscall?: unknown; path?: unknown }
if (e.code === 'ENOENT') {
return true
}
const message = typeof e.message === 'string' ? e.message.toLowerCase() : ''
return (
message.includes('enoent') &&
(message.includes(command) || e.path === command || e.syscall === 'spawn')
)
}