Files
orca/src/shared/git-branch-compare-head.ts
NeilandOrca a49d68f8c2 perf(git): overlap getBranchCompare's head-of-chain reads (#10895)
* perf(git): overlap getBranchCompare's head-of-chain reads

Four git spawns ran strictly in series before any compare work began:
branch --show-current, the base-ref probe, rev-parse HEAD, and rev-parse <base>.

Three are independent -- compareRef is display-only metadata and HEAD's oid does
not depend on the base ref -- so they now run concurrently. The fourth was
redundant outright: the probe already runs `rev-parse --verify --quiet
<ref>^{commit}` and discarded the oid it printed, which was then re-resolved by a
second spawn. resolveWorktreeBaseCommitOid returns that oid so it can be reused;
hasWorktreeBaseCommitRef now delegates to it, leaving its other 4 callers
untouched.

3.6-3.7x on a short remote base label (192ms -> 52ms), 1.44x on an
already-qualified refs/... base, which skips the probe by design.

Reuse is keyed by ref: resolveWorktreeAddBaseRef returns at its first successful
candidate, so only that ref's oid is ever read back. Peeling is safe because only
refs/heads and refs/remotes candidates reach the probe, where ^{commit} is a
no-op.

No new git features: this removes a spawn rather than adopting an option.

Co-authored-by: Orca <help@stably.ai>

* fix(git): preserve compare semantics across providers

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-27 17:17:03 -07:00

41 lines
1.3 KiB
TypeScript

export type BranchCompareOidResult = { ok: true; oid: string } | { ok: false; error: unknown }
type BranchCompareHeadReaders = {
readCompareRef: () => Promise<string>
resolveBaseRef: () => Promise<string>
readHeadOid: () => Promise<string>
readBaseOid: (resolvedBaseRef: string) => Promise<string>
}
export type BranchCompareHead = {
compareRef: string
resolvedBaseRef: string
headOidResult: BranchCompareOidResult
baseOidResult: BranchCompareOidResult
}
function settleOid(read: Promise<string>): Promise<BranchCompareOidResult> {
return read.then(
(oid) => ({ ok: true as const, oid }),
(error) => ({ ok: false as const, error })
)
}
export async function readBranchCompareHead(
readers: BranchCompareHeadReaders
): Promise<BranchCompareHead> {
const compareRefPromise = readers.readCompareRef()
const resolvedBaseRefPromise = readers.resolveBaseRef()
const headOidResultPromise = settleOid(readers.readHeadOid())
const baseOidResultPromise = resolvedBaseRefPromise.then((resolvedBaseRef) =>
settleOid(readers.readBaseOid(resolvedBaseRef))
)
const [compareRef, resolvedBaseRef, headOidResult, baseOidResult] = await Promise.all([
compareRefPromise,
resolvedBaseRefPromise,
headOidResultPromise,
baseOidResultPromise
])
return { compareRef, resolvedBaseRef, headOidResult, baseOidResult }
}