mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +00:00
`RuntimeGitTarget` carried `connectionId?: string` and no host id, so `undefined` spelled three different answers at once — "runtime: host", "unresolved", and "genuinely local". Its sole resolver read `store.getRepo(worktree.repoId)?.connectionId` and never looked at `worktree.hostId`, which outranks every repo row, so one arbitrarily chosen row decided the execution host for 36 downstream dispatches. The target now carries `executionHostId: ExecutionHostId` (never null, never optional), resolved through the shared rule that landed with #17909/#17919 and dispatched through the host-keyed routes from #18296. Dispatch sites call `requireRuntimeGitProvider`, where `null` means exactly one thing: the host is `local` and the command runs here as free functions. Four answers that used to collapse into one: - `ssh:x` with a rival row on `ssh:y` — routes to x. Previously the first row won, which is the reproduced cross-host leak. - `local` with a surviving `connectionId` — a row contradicting itself; no SSH connection is handed out. - `runtime:<env>` — throws `ExecutionHostNotDispatchableError`. Its repo row's connection names a target in the *server's* namespace; dialling it here reaches a same-named target on this client. - rival rows disagreeing with no worktree host — `worktree_execution_host_unresolved`, matching the launch path rather than guessing a row. An unreachable SSH host still throws `SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE`; loss of contact is never evidence of locality (docs/reference/ssh-execution-boundary.md). `resolveWorktreeLaunchHost` keeps its exact signature and now delegates to `resolveWorktreeHostRouting`, the same resolution answering "which host is this on" rather than "what may this client dial" — the git target needs the first question because `local` and `runtime:` are two different non-SSH answers. No wire change: `RuntimeGitTarget` is main-process internal, and the SSH and local model-discovery host keys are byte-identical to before. `RuntimeFileTarget` has the same defect in ~30 filesystem dispatches and is deliberately left for a follow-up.
70 lines
2.0 KiB
TypeScript
70 lines
2.0 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import type { GlobalSettings } from '../../shared/global-settings-types'
|
|
import { RuntimeGitCommands, type ResolvedRuntimeGitWorktree } from './orca-runtime-git'
|
|
|
|
const getSshGitProviderMock = vi.hoisted(() => vi.fn())
|
|
|
|
vi.mock('../providers/ssh-git-dispatch', () => ({
|
|
getSshGitProvider: getSshGitProviderMock
|
|
}))
|
|
|
|
function makeWorktree(path: string): ResolvedRuntimeGitWorktree {
|
|
const worktree = {
|
|
id: 'wt-1',
|
|
repoId: 'repo-1',
|
|
path,
|
|
linkedIssue: null,
|
|
git: {
|
|
path,
|
|
branch: 'main',
|
|
isBare: false,
|
|
isMainWorktree: false,
|
|
head: 'a'.repeat(40)
|
|
}
|
|
} satisfies Partial<ResolvedRuntimeGitWorktree>
|
|
return worktree as unknown as ResolvedRuntimeGitWorktree
|
|
}
|
|
|
|
describe('RuntimeGitCommands branch diff', () => {
|
|
beforeEach(() => {
|
|
getSshGitProviderMock.mockReset()
|
|
})
|
|
|
|
it('forwards the pinned head through normalized nested SSH paths', async () => {
|
|
const mergeBase = 'a'.repeat(40)
|
|
const headOid = 'b'.repeat(40)
|
|
const result = {
|
|
kind: 'text',
|
|
originalContent: 'left',
|
|
modifiedContent: 'right',
|
|
originalIsBinary: false,
|
|
modifiedIsBinary: false
|
|
}
|
|
const provider = { getBranchDiff: vi.fn().mockResolvedValue([result]) }
|
|
getSshGitProviderMock.mockReturnValue(provider)
|
|
const commands = new RuntimeGitCommands({
|
|
resolveRuntimeGitTarget: async () => ({
|
|
worktree: makeWorktree('/remote/repo'),
|
|
executionHostId: 'ssh:conn-1'
|
|
}),
|
|
getRuntimeSettings: () => ({}) as GlobalSettings
|
|
})
|
|
|
|
await expect(
|
|
commands.getRuntimeGitBranchDiff(
|
|
'id:wt-1',
|
|
{ mergeBase, headOid },
|
|
'src\\file.ts',
|
|
'src\\old-file.ts'
|
|
)
|
|
).resolves.toEqual(result)
|
|
|
|
expect(provider.getBranchDiff).toHaveBeenCalledWith('/remote/repo', mergeBase, {
|
|
includePatch: true,
|
|
headOid,
|
|
filePath: 'src/file.ts',
|
|
oldPath: 'src/old-file.ts'
|
|
})
|
|
})
|
|
})
|