mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 00:02:29 +00:00
53 lines
1.9 KiB
TypeScript
53 lines
1.9 KiB
TypeScript
export type WorktreeBaseRefExists = (qualifiedRef: string) => Promise<boolean>
|
|
|
|
export async function resolveWorktreeAddBaseRef(
|
|
baseRef: string,
|
|
refExists: WorktreeBaseRefExists
|
|
): Promise<string> {
|
|
if (baseRef.startsWith('refs/')) {
|
|
return baseRef
|
|
}
|
|
|
|
// Why: `git worktree add` receives a revision, so short names can collide
|
|
// with tags. Prefer the namespace implied by Orca's base picker: remote
|
|
// display names like `origin/main` first, otherwise local branches.
|
|
const candidates = baseRef.includes('/')
|
|
? [`refs/remotes/${baseRef}`, `refs/heads/${baseRef}`]
|
|
: [`refs/heads/${baseRef}`]
|
|
|
|
for (const candidate of candidates) {
|
|
if (await refExists(candidate)) {
|
|
return candidate
|
|
}
|
|
}
|
|
|
|
return baseRef
|
|
}
|
|
|
|
/**
|
|
* The branch identity two base refs share when one is the local branch and the
|
|
* other is a remote-tracking copy of it: `refs/heads/main` and
|
|
* `refs/remotes/origin/main` both return `main`.
|
|
*
|
|
* Bounds the prepared-checkout retarget. A prepared checkout may only be reused
|
|
* for a different base when both name the same branch, so the retarget reset is
|
|
* bounded by that branch's drift across remotes rather than by an arbitrary
|
|
* divergence. Anything unqualified — a bare name, a commit id — has no family.
|
|
*/
|
|
export function worktreeBaseRefFamily(qualifiedRef: string): string | null {
|
|
if (qualifiedRef.startsWith('refs/heads/')) {
|
|
return qualifiedRef.slice('refs/heads/'.length) || null
|
|
}
|
|
if (qualifiedRef.startsWith('refs/remotes/')) {
|
|
const withoutRemote = qualifiedRef.slice('refs/remotes/'.length)
|
|
const separator = withoutRemote.indexOf('/')
|
|
if (separator <= 0) {
|
|
return null
|
|
}
|
|
const branch = withoutRemote.slice(separator + 1)
|
|
// `refs/remotes/<remote>/HEAD` is a symbolic pointer, not a branch identity.
|
|
return branch && branch !== 'HEAD' ? branch : null
|
|
}
|
|
return null
|
|
}
|