mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
Fall back to local base ref when worktree-create refresh fails (#7335)
Creating a workspace hard-failed with "Could not refresh base ref …"
whenever the pre-create git fetch of a remote-tracking base (e.g.
origin/main) failed — offline, transient, or (common on Linux GUI) the
Electron process lacking SSH_AUTH_SOCK so `ssh -o BatchMode=yes` cannot
auth. This blocked creation even when a perfectly usable local
origin/main already existed and `git worktree add` from it would succeed.
Regression introduced by #2310 (5c93579e40), which replaced the prior
best-effort fetch + post-create reconcile with a hard network gate.
Fix: at all three create sites (local runtime, local IPC, SSH), only
throw when the refresh failed AND no usable local base ref exists;
otherwise create from the local ref (a possibly stale but valid base).
Also: move the SSH local-ref probe after session.registerRoot so relays
that gate generic git.exec don't false-negative and defeat the fallback.
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -2355,10 +2355,21 @@ describe('OrcaRuntimeService', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('does not create runtime local worktrees when remote-tracking base refresh fails', async () => {
|
||||
it('creates a runtime local worktree from an existing local base ref when the refresh fails', async () => {
|
||||
// Regression: an offline/auth failure while refreshing the remote-tracking
|
||||
// base must not block creation when a usable local base ref already exists.
|
||||
const runtime = new OrcaRuntimeService(store)
|
||||
computeWorktreePathMock.mockReturnValue('/tmp/workspaces/cli-refresh-fails')
|
||||
ensurePathWithinWorkspaceMock.mockReturnValue('/tmp/workspaces/cli-refresh-fails')
|
||||
const createdWorktree = {
|
||||
path: '/tmp/workspaces/cli-refresh-fails',
|
||||
head: 'base-sha',
|
||||
branch: 'cli-refresh-fails',
|
||||
isBare: false,
|
||||
isMainWorktree: false
|
||||
}
|
||||
computeWorktreePathMock.mockReturnValue(createdWorktree.path)
|
||||
ensurePathWithinWorkspaceMock.mockReturnValue(createdWorktree.path)
|
||||
vi.mocked(addWorktree).mockResolvedValueOnce({})
|
||||
vi.mocked(listWorktrees).mockResolvedValue([createdWorktree])
|
||||
const gitSpy = vi.spyOn(gitRunner, 'gitExecFileAsync').mockImplementation(async (args) => {
|
||||
if (args[0] === 'remote') {
|
||||
return { stdout: 'origin\n', stderr: '' }
|
||||
@@ -2366,6 +2377,7 @@ describe('OrcaRuntimeService', () => {
|
||||
if (args[0] === 'rev-parse' && args.includes('--git-common-dir')) {
|
||||
return { stdout: '/tmp/repo/.git\n', stderr: '' }
|
||||
}
|
||||
// Local remote-tracking base ref resolves -> usable fallback exists.
|
||||
if (args[0] === 'rev-parse' && args[1] === '--verify') {
|
||||
return { stdout: 'base-sha\n', stderr: '' }
|
||||
}
|
||||
@@ -2380,6 +2392,40 @@ describe('OrcaRuntimeService', () => {
|
||||
repoSelector: 'id:repo-1',
|
||||
name: 'cli-refresh-fails'
|
||||
})
|
||||
).resolves.toBeDefined()
|
||||
|
||||
expect(addWorktree).toHaveBeenCalled()
|
||||
} finally {
|
||||
gitSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('does not create a runtime local worktree when the refresh fails and no local base ref exists', async () => {
|
||||
const runtime = new OrcaRuntimeService(store)
|
||||
computeWorktreePathMock.mockReturnValue('/tmp/workspaces/cli-refresh-no-local')
|
||||
ensurePathWithinWorkspaceMock.mockReturnValue('/tmp/workspaces/cli-refresh-no-local')
|
||||
const gitSpy = vi.spyOn(gitRunner, 'gitExecFileAsync').mockImplementation(async (args) => {
|
||||
if (args[0] === 'remote') {
|
||||
return { stdout: 'origin\n', stderr: '' }
|
||||
}
|
||||
if (args[0] === 'rev-parse' && args.includes('--git-common-dir')) {
|
||||
return { stdout: '/tmp/repo/.git\n', stderr: '' }
|
||||
}
|
||||
// No local remote-tracking base ref -> nothing to fall back on.
|
||||
if (args[0] === 'rev-parse' && args[1] === '--verify') {
|
||||
throw new Error('missing ref')
|
||||
}
|
||||
if (args[0] === 'fetch') {
|
||||
throw new Error('network unavailable')
|
||||
}
|
||||
return { stdout: '', stderr: '' }
|
||||
})
|
||||
try {
|
||||
await expect(
|
||||
runtime.createManagedWorktree({
|
||||
repoSelector: 'id:repo-1',
|
||||
name: 'cli-refresh-no-local'
|
||||
})
|
||||
).rejects.toThrow(
|
||||
'Could not refresh base ref "origin/main" from "origin". Check your network and try again.'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user