mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 10:08:13 +00:00
* 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>
101 lines
3.4 KiB
TypeScript
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')
|
|
})
|
|
})
|