Files
orca/src/main/git/worktree.ts
T
Neil d3501f7ad6 fix(worktrees): stop a failed worktree scan from being recorded as an authoritative empty listing (#18456)
* fix(worktrees): stop a failed worktree scan from pruning as an authoritative empty listing

A `git worktree list` that could not run at all — a WSL distro that stopped
resolving, a hung mount, a git binary that errored — was softened to `[]` by the
lenient listing path, so the detected scan published it as
`authoritative: true, worktrees: []`. That disables the #1158 retention guard,
drops every persisted tab for the repo, and the pruned session is written back to
disk on the next launch. The loss is permanent, not a transient glitch.

Route the detected scan through a strict listing that still reports the two
genuinely empty states (repo path gone, not a Git repo) as `[]`. Everything else
rejects, so the existing catch answers `authoritative: false` and the destructive
halves (`rememberLocalWorktreeRoots`, `pruneLineageForMissingRepoWorktrees`)
never see a failed scan.

Also make the failure readable: wsl.exe reports its own launch failures as exit
0xFFFFFFFF with an EMPTY stderr and the `Wsl/Service/WSL_E_*` line on stdout as
UTF-16LE, which is why the field bundle carried a git error with no text. Set
WSL_UTF8 for WSL-routed git (matching the wsl runner, #9010) and attach that
stdout diagnostic to the error so `git.exec` spans name the cause.

* fix(worktrees): surface a failed worktree scan's cause on the repo header with a retry

A failed scan now travels with its reason (optional unavailableReason on
DetectedWorktreeListResult), the repo header shows it with click-to-retry,
and the WSL deleted-guest-directory shape measured on a real Windows host is
pinned as retained-not-pruned.
2026-09-04 15:23:09 -07:00

41 lines
1.6 KiB
TypeScript

export { addWorktree } from './worktree-add'
export {
configurePushAutoSetupRemote,
persistWorktreeCreationBase,
resolveWorktreeAddBaseContext
} from './worktree-add'
export { forceDeleteLocalBranch } from './worktree-branch-removal'
export { parseWorktreeList } from '../../shared/git-worktree-porcelain-parser'
// Unshared by design: verification-after-mutation callers must not join an
// in-flight scan that predates a raw `git worktree prune` or an external client.
// Opt into coalescing with `listWorktreesSharedStrict`.
export { describeCreatedWorktree, listWorktreesStrict } from './worktree-listing'
export { moveWorktree } from './worktree-move'
export {
WORKTREE_ADD_TIMEOUT_MAX_MS,
WORKTREE_ADD_TIMEOUT_MS,
WORKTREE_LIST_TIMEOUT_MS,
WORKTREE_REMOVAL_PREFLIGHT_TIMEOUT_MS,
WORKTREE_REMOVAL_REGISTRATION_TIMEOUT_MS,
resolveWorktreeAddTimeoutMs
} from './worktree-operation-options'
export type {
AddWorktreeOptions,
AddWorktreeResult,
GitWorktreeExecOptions,
RemoveWorktreeOptions
} from './worktree-operation-options'
export { assertWorktreeCleanForRemoval } from './worktree-removal-preflight'
export { removeWorktree } from './worktree-removal'
export {
_getWorktreeScanCacheSizesForTests,
_resetWorktreeScanCacheForTests,
listWorktreeGraph,
listWorktrees,
listWorktreesSharedStrict,
listWorktreesSharedStrictAllowingTrueEmpty
} from './worktree-scan-cache'
export { bumpWorktreeScanGeneration as notifyPreparedWorktreeMutation } from './worktree-scan-cache'
export { addSparseWorktree } from './worktree-sparse-add'
export { parseCoreSparseCheckoutFlag } from './worktree-sparse-state'