Files
orca/src/main/git/worktree-base-refresh.ts
T
Neil 037cc2e531 Split Git worktree responsibilities (#17253)
* Split speech session lifecycle

* Split terminal output scheduler pipeline

* Split mobile browser pane modules

* Prune resolved max-lines suppressions

* Split pane tree equalization logic

* Extract mobile troubleshoot screen styles

* Split external automation manager

* Split main window service attachments

* Split hosted review creation checks

* Split automation dispatch event handling

* Split settings navigation metadata

* Split daemon initialization lifecycle

* Split GitLab item dialog

* Split relay dispatcher layers

* Split mobile host screen

* Retarget mobile view settings source test

* Split runtime file client layers

* Split ports panel layers

* Split runtime environments pane layers

* Split local PTY provider responsibilities

* Split CDP bridge responsibilities

* Split relay Git handler responsibilities

* Track moved relay Git fetch audit

* Split Linear item drawer responsibilities

* Split telemetry event schema responsibilities

* Split resource usage status responsibilities

* Split remote terminal multiplexer responsibilities

* Split Git worktree responsibilities

* Fix F3-speech for #17123

* Fix F1-cycle for #17131

* Fix F4-navtest for #17157

* Fix F2-allowlist for #17161
2026-08-29 20:20:55 -07:00

77 lines
2.8 KiB
TypeScript

import type { LocalBaseRefRefreshResult } from '../../shared/worktree/base-ref-drift-types'
import { gitExecFileAsync, translateWslOutputPaths } from './runner'
import {
evaluateLocalBaseRefRefreshability,
getLocalBaseRefUpdateSuggestionForWorktreeCreate
} from './worktree-base-refresh-analysis'
import { parseWorktreeList } from './worktree-list-parser'
import type { AddWorktreeOptions, GitWorktreeExecOptions } from './worktree-operation-options'
import { gitExecOptions } from './worktree-operation-options'
export { getLocalBaseRefUpdateSuggestionForWorktreeCreate }
export async function refreshLocalBaseRefForWorktreeCreate(
repoPath: string,
baseBranch: string,
remoteTrackingRef: string,
remoteTrackingBase?: AddWorktreeOptions['remoteTrackingBase'],
options: GitWorktreeExecOptions = {}
): Promise<LocalBaseRefRefreshResult | undefined> {
const evaluation = await evaluateLocalBaseRefRefreshability(
repoPath,
baseBranch,
remoteTrackingRef,
remoteTrackingBase,
options
)
if (!evaluation) {
return undefined
}
if (!evaluation.refreshable) {
return evaluation.result
}
const resultBase = { baseRef: evaluation.baseRef, localBranch: evaluation.localBranch }
try {
if (evaluation.ownerWorktreePath) {
const { stdout: worktreeListOutput } = await gitExecFileAsync(
['worktree', 'list', '--porcelain'],
gitExecOptions(repoPath, options)
)
const worktrees = parseWorktreeList(
translateWslOutputPaths(worktreeListOutput, repoPath, options)
)
const currentOwner = worktrees.find((wt) => wt.branch === evaluation.fullRef)
if (!currentOwner || currentOwner.path !== evaluation.ownerWorktreePath) {
return { ...resultBase, status: 'skipped_error' }
}
const { stdout: status } = await gitExecFileAsync(
['status', '--porcelain', '--untracked-files=no'],
gitExecOptions(currentOwner.path, options)
)
if (status.trim()) {
return {
...resultBase,
status: 'skipped_dirty_worktree',
ownerWorktreePath: currentOwner.path
}
}
await gitExecFileAsync(
['reset', '--hard', evaluation.remoteOid],
gitExecOptions(currentOwner.path, options)
)
return { ...resultBase, status: 'updated', ownerWorktreePath: currentOwner.path }
}
// Why: no owner worktree — fast-forward the bare ref; the expected-old-OID form is a no-op-safe CAS if the ref moved since evaluation.
await gitExecFileAsync(
['update-ref', evaluation.fullRef, evaluation.remoteOid, evaluation.localOid],
gitExecOptions(repoPath, options)
)
return { ...resultBase, status: 'updated' }
} catch {
// update-ref/reset can fail on locked refs or odd worktree states; worktree creation should still proceed.
return { ...resultBase, status: 'skipped_error' }
}
}