Files
orca/src/main/git/worktree-sparse-add.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

80 lines
2.8 KiB
TypeScript

import { windowsLongPathGitArgs } from '../../shared/windows-long-path-git-args'
import { gitExecFileAsync } from './runner'
import { addWorktree, unsetWorktreeCreationBase } from './worktree-add'
import type {
AddWorktreeOptions,
AddWorktreeResult,
SparseWorktreeCreateError
} from './worktree-operation-options'
import { gitExecOptions } from './worktree-operation-options'
import { removeWorktree } from './worktree-removal'
export async function addSparseWorktree(
repoPath: string,
worktreePath: string,
branch: string,
directories: string[],
baseBranch?: string,
refreshLocalBaseRef = false,
options: AddWorktreeOptions = {}
): Promise<AddWorktreeResult> {
let created = false
let addResult: AddWorktreeResult = {}
try {
addResult = await addWorktree(
repoPath,
worktreePath,
branch,
baseBranch,
refreshLocalBaseRef,
true,
options
)
created = true
// Why: `worktree add --no-checkout` writes no files, so these are the calls that
// actually materialize the deep path and need the long-path escape hatch.
const longPathArgs = windowsLongPathGitArgs(worktreePath)
await gitExecFileAsync(
['sparse-checkout', 'init', '--cone'],
gitExecOptions(worktreePath, options)
)
await gitExecFileAsync(
[...longPathArgs, 'sparse-checkout', 'set', '--', ...directories],
gitExecOptions(worktreePath, options)
)
await gitExecFileAsync(
[...longPathArgs, 'checkout', branch],
gitExecOptions(worktreePath, options)
)
return addResult
} catch (error) {
const wrapped: SparseWorktreeCreateError =
error instanceof Error ? (error as SparseWorktreeCreateError) : new Error(String(error))
if (created) {
if (!options.checkoutExistingBranch) {
try {
await unsetWorktreeCreationBase(worktreePath, branch, options)
} catch (cleanupError) {
console.warn(
`addSparseWorktree: failed to clear creation base for ${worktreePath}`,
cleanupError
)
}
}
try {
await removeWorktree(repoPath, worktreePath, true, {
deleteBranch: !options.checkoutExistingBranch,
// Why: failed-creation rollback — the fresh branch has no user commits, so force-delete rather than orphan it.
forceBranchDelete: !options.checkoutExistingBranch,
...(options.wslDistro ? { wslDistro: options.wslDistro } : {})
})
} catch {
wrapped.cleanupFailed = true
// Why: surface that manual cleanup may be needed, else a half-created worktree lingers silently on disk.
wrapped.message = `${wrapped.message} (cleanup also failed — the partially created worktree at "${worktreePath}" may need manual removal)`
}
}
throw wrapped
}
}