mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 00:03:15 +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.
111 lines
3.6 KiB
TypeScript
111 lines
3.6 KiB
TypeScript
import type { Store } from './persistence'
|
|
import type { Repo } from '../shared/repo-types'
|
|
import { isFolderRepo } from '../shared/repo-kind'
|
|
import {
|
|
resolveLocalProjectRuntimeForRepo,
|
|
type ProjectRuntimeResolutionStore
|
|
} from './local-project-runtime-resolution'
|
|
import type { ProjectExecutionRuntimeResolution } from '../shared/project-execution-runtime'
|
|
|
|
export {
|
|
resolveLocalProjectRuntimeForRepo,
|
|
resolveLocalProjectRuntimesForRepos
|
|
} from './local-project-runtime-resolution'
|
|
|
|
export type LocalProjectGitExecOptions = {
|
|
cwd: string
|
|
wslDistro?: string
|
|
}
|
|
|
|
export type LocalProjectWorktreeGitOptions = {
|
|
wslDistro?: string
|
|
}
|
|
|
|
export function getLocalProjectGitExecOptions(
|
|
store: Store,
|
|
repo: Repo
|
|
): LocalProjectGitExecOptions {
|
|
// Why: local git must run in the same resolved project runtime as agents,
|
|
// terminals, and preflight; repair states must not silently fall back to host git.
|
|
return getLocalProjectGitExecOptionsForRuntime(
|
|
repo,
|
|
resolveLocalProjectRuntimeForRepo(store, repo)
|
|
)
|
|
}
|
|
|
|
function getLocalProjectGitExecOptionsForRuntime(
|
|
repo: Repo,
|
|
projectRuntime: ProjectExecutionRuntimeResolution | undefined
|
|
): LocalProjectGitExecOptions {
|
|
if (!projectRuntime) {
|
|
return { cwd: repo.path }
|
|
}
|
|
if (projectRuntime.status === 'repair-required') {
|
|
throw new Error(
|
|
`Project runtime requires repair before git execution: ${projectRuntime.repair.reason}`
|
|
)
|
|
}
|
|
if (projectRuntime.runtime.kind === 'wsl') {
|
|
return { cwd: repo.path, wslDistro: projectRuntime.runtime.distro }
|
|
}
|
|
return { cwd: repo.path }
|
|
}
|
|
|
|
export function getLocalProjectWorktreeGitOptions(
|
|
store: Store,
|
|
repo: Repo
|
|
): LocalProjectWorktreeGitOptions {
|
|
const { wslDistro } = getLocalProjectGitExecOptions(store, repo)
|
|
return wslDistro ? { wslDistro } : {}
|
|
}
|
|
|
|
/**
|
|
* Git routing for the speculative worktree-create warm-up.
|
|
*
|
|
* Deliberately non-throwing where `getLocalProjectWorktreeGitOptions` throws: an
|
|
* optimistic prefetch must not report a repair-required runtime as a failure, so
|
|
* an unresolved runtime falls back to the host Git the warm-up used before
|
|
* routing existed.
|
|
*/
|
|
export function getWorktreeCreatePrefetchGitOptions(
|
|
store: Store,
|
|
repo: Repo
|
|
): LocalProjectWorktreeGitOptions {
|
|
if (isFolderRepo(repo)) {
|
|
return {}
|
|
}
|
|
const projectRuntime = resolveLocalProjectRuntimeForRepo(store, repo)
|
|
if (!projectRuntime || projectRuntime.status !== 'resolved') {
|
|
return {}
|
|
}
|
|
return getLocalProjectWorktreeGitOptionsForRuntime(repo, projectRuntime)
|
|
}
|
|
|
|
export function getLocalProjectWorktreeGitOptionsForRuntime(
|
|
repo: Repo,
|
|
projectRuntime: ProjectExecutionRuntimeResolution | undefined
|
|
): LocalProjectWorktreeGitOptions {
|
|
// Why: callers that already batch-resolved project runtimes must not rescan
|
|
// every project once per repo on a polling path.
|
|
const { wslDistro } = getLocalProjectGitExecOptionsForRuntime(repo, projectRuntime)
|
|
return wslDistro ? { wslDistro } : {}
|
|
}
|
|
|
|
/**
|
|
* Distro whose filesystem this repo's worktrees belong on, or undefined.
|
|
*
|
|
* Deliberately non-throwing where `getLocalProjectGitExecOptions` throws: a
|
|
* runtime that needs repair must not block creating a worktree, it just falls
|
|
* back to the Windows-side placement that has always been used.
|
|
*/
|
|
export function getWorktreeMirrorDistro(
|
|
store: ProjectRuntimeResolutionStore,
|
|
repo: Repo
|
|
): string | undefined {
|
|
const projectRuntime = resolveLocalProjectRuntimeForRepo(store, repo)
|
|
if (!projectRuntime || projectRuntime.status !== 'resolved') {
|
|
return undefined
|
|
}
|
|
return projectRuntime.runtime.kind === 'wsl' ? projectRuntime.runtime.distro : undefined
|
|
}
|