mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 16:03:17 +00:00
fix(git): run WSL git reads without a shell (#15257)
* fix(git): run WSL git reads without a shell WSL-routed git ran through the distro user's interactive login shell for one reason: to inherit their PATH. That shell also runs the distro's rc/motd and writes it to the stdout callers parse, which is why #10917 reports a shell banner breaking GitHub source detection. A shell-free route already existed (`--exec /usr/bin/env PATH=... git`, added for status reads in #13207) but it was opt-in, and only gitStatusReadOptionsForWorktree opted in. Every other read -- remote get-url, config --get, log, show, rev-parse -- took the login shell on every call, so the reported parse never benefited. Classify reads at the resolver instead of at each caller. A read needs nothing the login shell provides, so it takes the direct route without the caller asking. Writes and network operations stay on the login shell: they can depend on credential helpers and ssh-agent that the user's profile sets up. Subcommands that both read and write (config, remote, branch, submodule) require an explicit read flag before they qualify, so `config --get` goes direct while `config user.email x` does not. `git show` blob reads stop forcing the login shell and go direct too. The fence stays on that path: the login shell is still the fallback when the environment probe is cold or rejected, and a banner there would become file content. Behavior note: the first WSL read per distro now also warms the environment probe in the background, so a cold read spawns one extra wsl.exe. Subsequent reads start no shell at all. * fix(git): keep queried WSL remote reads on login shell * style: format WSL runner test * fix(git): match WSL read markers positionally The conditional read markers were matched anywhere after the subcommand, so a positional argument that happened to share a marker's name routed a write shell-free: `worktree remove list` read as a listing, and `submodule foreach status` as a status query -- the latter can run arbitrary commands, including network ones. Split the two kinds of marker apart. `config`/`branch` are flag-marked and still match anywhere; `remote`/`worktree`/`submodule` are action-marked and must match the first non-flag argument. The queried `remote show` rule and the `symbolic-ref` arity rule are unchanged. Neither case is reachable today -- Orca issues no `submodule foreach`, and the worktree paths are its own CLI, not git argv -- but the loose match was the shape of the defect, not those two instances. * test(git): pin read routing behind global options Writes hidden behind -c/-C/--git-dir must not reach the shell-free route, and an unparsed global form must fall back to the login shell rather than guess at the subcommand. Both directions fail safe. --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
This commit is contained in:
@@ -296,7 +296,10 @@ describe('runner execFile timeout handling', () => {
|
||||
return child
|
||||
})
|
||||
|
||||
await gitExecFileAsync(['worktree', 'list', '--porcelain', '-z'], { cwd: '/home5/Brian' })
|
||||
await gitExecFileAsync(['worktree', 'list', '--porcelain', '-z'], {
|
||||
cwd: '/home5/Brian',
|
||||
env: { ...process.env, GIT_ASKPASS: undefined, SSH_ASKPASS: undefined }
|
||||
})
|
||||
|
||||
expect(capturedEnv?.GIT_TERMINAL_PROMPT).toBe('0')
|
||||
expect(capturedEnv?.GIT_ASKPASS).toBe('')
|
||||
@@ -507,7 +510,10 @@ describe('runner execFile timeout handling', () => {
|
||||
expect.objectContaining({ cwd: undefined }),
|
||||
expect.any(Function)
|
||||
)
|
||||
const shellCommand = execFileMock.mock.calls[0]?.[1]?.[5] as string
|
||||
// A read also warms the direct-git environment probe in the background, so
|
||||
// pick the git call rather than assuming it is the first spawn.
|
||||
const gitCall = execFileMock.mock.calls.find((call) => String(call[1]?.[5]).includes("'git'"))
|
||||
const shellCommand = gitCall?.[1]?.[5] as string
|
||||
expect(shellCommand).toContain('getent passwd')
|
||||
expect(shellCommand).toContain('exec "$_orca_wsl_shell" -ilc')
|
||||
expect(shellCommand).toContain('/mnt/c/repo')
|
||||
|
||||
Reference in New Issue
Block a user