mirror of
https://github.com/stablyai/orca.git
synced 2026-10-05 08:02:33 +00:00
The speculative warm-up that runs while the create composer is open resolved
refs and fetched with host Git even when the project's runtime is a WSL distro,
while both the checkout preparation it feeds (`prepareWorktreeCreateForRepo`,
which already resolves `{ wslDistro }` itself) and the real create path run
inside the distro.
The concrete cost was a discarded fetch: `getCanonicalFetchKey` namespaces the
runtime's remote-fetch cache `wsl:<distro>` vs `local`, so the warm-up's fetch
landed in a namespace create never looks at, and create fetched again. On a
Windows host with no usable host-side Git the probes also failed outright, so
that cohort got no warm-up at all.
Thread the project's worktree Git options through the prefetch (resolved by a
non-throwing helper, because an optimistic warm-up must not surface a
repair-required runtime as a failure) so every probe and fetch runs where create
runs. `gitOptions` is a required argument, so a caller cannot drop the routing
silently. Host-routed calls keep their original arity, so macOS, Linux,
native-Windows-host projects, SSH repos and folder workspaces are unchanged.
Narrower than it looks: for a repo under \\wsl.localhost\<distro>\... the probes
were already routed by cwd, and for a repo on a Windows drive letter host Git
and WSL Git read the same on-disk repository, so the answers were already
correct there. What those cohorts gain is a fetch create can reuse; what they
pay is that the probes now run inside the distro (over /mnt/c for drive-letter
repos, which also newly arms the linked-worktree routing probe) and the
speculative fetch now shares create's per-remote fetch queue, as it always has
on native platforms.
Also collapse the three byte-equivalent copies of `hasLocalWorktreeBaseRef`
(create, prefetch, remote-repo create) into one in
git/worktree-base-ref-probe.ts, drop the host-only `hasLocalCommitObject` that
caused the routing bug, and add the first routing assertions on the create-path
consumers of the now-shared probe.
104 lines
3.2 KiB
TypeScript
104 lines
3.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const gitExecFileAsync = vi.hoisted(() => vi.fn())
|
|
|
|
vi.mock('./runner', () => ({ gitExecFileAsync }))
|
|
|
|
import { hasLocalWorktreeBaseRef, probeWorktreeBaseRefPresence } from './worktree-base-ref-probe'
|
|
|
|
describe('probeWorktreeBaseRefPresence', () => {
|
|
it('uses an exact show-ref probe and reports a present ref', async () => {
|
|
const runGit = vi.fn().mockResolvedValue({ stdout: '' })
|
|
|
|
await expect(probeWorktreeBaseRefPresence(runGit, 'refs/heads/release/2026')).resolves.toBe(
|
|
'present'
|
|
)
|
|
expect(runGit).toHaveBeenCalledWith([
|
|
'show-ref',
|
|
'--verify',
|
|
'--quiet',
|
|
'--',
|
|
'refs/heads/release/2026'
|
|
])
|
|
})
|
|
|
|
it('treats show-ref exit 1 as an absent ref', async () => {
|
|
const runGit = vi.fn().mockRejectedValue(Object.assign(new Error('missing ref'), { code: 1 }))
|
|
|
|
await expect(probeWorktreeBaseRefPresence(runGit, 'refs/heads/release/2026')).resolves.toBe(
|
|
'absent'
|
|
)
|
|
})
|
|
|
|
it('keeps repository and transport failures inconclusive', async () => {
|
|
const runGit = vi
|
|
.fn()
|
|
.mockRejectedValue(Object.assign(new Error('not a git repository'), { code: 128 }))
|
|
|
|
await expect(probeWorktreeBaseRefPresence(runGit, 'refs/heads/release/2026')).resolves.toBe(
|
|
'unknown'
|
|
)
|
|
})
|
|
|
|
it('does not treat a string transport code as a missing ref', async () => {
|
|
const runGit = vi
|
|
.fn()
|
|
.mockRejectedValue(Object.assign(new Error('connection lost'), { code: '1' }))
|
|
|
|
await expect(probeWorktreeBaseRefPresence(runGit, 'refs/heads/release/2026')).resolves.toBe(
|
|
'unknown'
|
|
)
|
|
})
|
|
|
|
it('does not execute malformed ref input', async () => {
|
|
const runGit = vi.fn()
|
|
|
|
await expect(probeWorktreeBaseRefPresence(runGit, 'refs/heads/*')).resolves.toBe('unknown')
|
|
expect(runGit).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('hasLocalWorktreeBaseRef', () => {
|
|
const repoPath = String.raw`C:\workspace\repo`
|
|
|
|
function resolveOnly(present: string[]): void {
|
|
gitExecFileAsync.mockImplementation(async (args: string[]) => ({
|
|
stdout: present.includes(args.at(-1)?.replace('^{commit}', '') ?? '') ? 'f'.repeat(40) : '',
|
|
stderr: ''
|
|
}))
|
|
}
|
|
|
|
beforeEach(() => {
|
|
gitExecFileAsync.mockReset()
|
|
})
|
|
|
|
it('prefers the remote namespace for a slashed short name', async () => {
|
|
resolveOnly(['refs/remotes/origin/main'])
|
|
|
|
await expect(hasLocalWorktreeBaseRef(repoPath, 'origin/main')).resolves.toBe(true)
|
|
expect(gitExecFileAsync).toHaveBeenCalledWith(
|
|
['rev-parse', '--verify', '--quiet', 'refs/remotes/origin/main^{commit}'],
|
|
{ cwd: repoPath }
|
|
)
|
|
})
|
|
|
|
it('probes a bare commit id as an object, not as a ref', async () => {
|
|
const sha = 'a'.repeat(40)
|
|
resolveOnly([sha])
|
|
|
|
await expect(hasLocalWorktreeBaseRef(repoPath, sha, { wslDistro: 'Ubuntu' })).resolves.toBe(
|
|
true
|
|
)
|
|
expect(gitExecFileAsync).toHaveBeenCalledWith(
|
|
['rev-parse', '--verify', '--quiet', `${sha}^{commit}`],
|
|
{ cwd: repoPath, wslDistro: 'Ubuntu' }
|
|
)
|
|
})
|
|
|
|
it('reports a base no namespace resolves as absent', async () => {
|
|
resolveOnly([])
|
|
|
|
await expect(hasLocalWorktreeBaseRef(repoPath, 'feature/topic')).resolves.toBe(false)
|
|
})
|
|
})
|