Files
orca/src/main/git/git-network-safety-real-git.test.ts
T
NeilandClaude 6328a104bd refactor(ssh): split ssh-connection-utils into concretely named modules (#30488)
* refactor(ssh): split ssh-connection-utils into concretely named modules

- classifiers -> ssh-reconnect-error-classification.ts
- retry/timeout constants and sleep -> connection/ssh-connection-timing.ts
- buildConnectConfig -> connection/ssh-connect-config.ts
- credential callbacks -> connection/ssh-connection-callbacks.ts
- exec options and abort error -> connection/ssh-exec-options.ts
- wrapRemoteCommandForPosixShell -> ssh-posix-command-wrapper.ts
- shellEscape and shared/wsl-login-shell-command quotePosixShell (identical) -> shared/shell-argument-quoting.ts quotePosixShell

No re-exports are left behind.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: point the WSL git benchmark and the WSL lane route at shell-argument-quoting

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-18 20:48:05 -07:00

101 lines
3.4 KiB
TypeScript

import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { runProcess } from '@orca/process-host'
import { quotePosixShell } from '../../shared/shell-argument-quoting'
import { gitExecFileAsync, gitSpawnAfterWindowsEnvironmentReady } from './runner'
let root = ''
let repo = ''
let script = ''
let marker = ''
let env: NodeJS.ProcessEnv = {}
async function git(args: string[]): Promise<string> {
const result = await runProcess({ program: 'git', args, cwd: repo, env })
if (result.code !== 0) {
throw new Error(result.stderr)
}
return result.stdout
}
function sshCommand(identity: string): string {
return [process.execPath, script, marker, identity].map(quotePosixShell).join(' ')
}
beforeEach(async () => {
root = await mkdtemp(join(tmpdir(), 'orca-git-network-safety-'))
repo = join(root, 'repo')
script = join(root, 'ssh wrapper.cjs')
marker = join(root, 'ssh calls.jsonl')
await mkdir(repo)
const globalConfig = join(root, 'global.gitconfig')
await writeFile(globalConfig, '')
env = {
...process.env,
GIT_CONFIG_GLOBAL: globalConfig,
GIT_CONFIG_NOSYSTEM: '1',
GIT_SSH: undefined,
GIT_SSH_COMMAND: undefined,
GIT_SSH_VARIANT: undefined
}
await writeFile(
script,
"const fs = require('node:fs'); fs.appendFileSync(process.argv[2], JSON.stringify({ args: process.argv.slice(3), prompt: process.env.GIT_TERMINAL_PROMPT, askpass: process.env.SSH_ASKPASS }) + '\\n'); process.exit(1);\n"
)
await git(['init', '-q'])
await git(['remote', 'add', 'origin', 'ssh://example.invalid/repository'])
vi.stubEnv('GIT_CONFIG_GLOBAL', globalConfig)
vi.stubEnv('GIT_CONFIG_NOSYSTEM', '1')
vi.stubEnv('GIT_SSH', undefined)
vi.stubEnv('GIT_SSH_COMMAND', undefined)
vi.stubEnv('GIT_SSH_VARIANT', undefined)
})
afterEach(async () => {
vi.unstubAllEnvs()
await rm(root, { recursive: true, force: true })
})
async function expectIdentity(identity: string): Promise<void> {
const calls = (await readFile(marker, 'utf8'))
.trim()
.split('\n')
.map((line) => JSON.parse(line))
expect(calls.length).toBeGreaterThan(0)
for (const call of calls) {
expect(call.args[0]).toBe(identity)
expect(call.prompt).toBe('0')
expect(call.askpass).toBe('')
}
}
describe('network SSH configuration with real Git', () => {
it('preserves command-line SSH configuration ahead of repository configuration', async () => {
await git(['config', 'core.sshCommand', sshCommand('repository')])
await expect(
gitExecFileAsync(
['-c', `core.sshCommand=${sshCommand('command-line')}`, 'ls-remote', 'origin'],
{ cwd: repo, env }
)
).rejects.toThrow()
await expectIdentity('command-line')
})
it('honors configured global SSH wrappers for streaming clones from a folder', async () => {
await git(['config', '--global', 'core.sshCommand', sshCommand('clone identity')])
const child = await gitSpawnAfterWindowsEnvironmentReady(
['clone', 'ssh://example.invalid/repository', 'clone'],
{ cwd: root, env, stdio: 'pipe' }
)
child.stdout?.resume()
child.stderr?.resume()
await new Promise<void>((resolve, reject) => {
child.once('error', reject)
child.once('close', () => resolve())
})
await expectIdentity('clone identity')
})
})