(repo: string)
| 105 | } |
| 106 | |
| 107 | /** Create a fresh isolated worktree on a `kild/<name>` branch, force-resetting any |
| 108 | * pre-existing one. For the brain's explicit "new worktree" — NOT the session path |
| 109 | * (which must never reset a shared tree; use {@link ensureWorktree}). `name` is the |
| 110 | * kild worktree name (the branch is derived as `kild/<name>`); `base` is the |
| 111 | * start-point ref (default: current HEAD). */ |
| 112 | export async function createWorktree(repo: string, name: string, base?: string): Promise<Worktree> { |
| 113 | assertSafeBranch(name); |
| 114 | const wtPath = worktreePath(name); |
| 115 | const ref = worktreeRef(name); |
| 116 | // Best-effort pre-clean of a same-named worktree before the force re-create. |
| 117 | // Force is intentional here ("new worktree" is destructive-by-request). |
| 118 | await execFile('git', ['-C', repo, 'worktree', 'remove', '--force', wtPath]).catch(() => {}); |
| 119 | const add = ['-C', repo, 'worktree', 'add', '-B', ref, wtPath, ...(base ? [base] : [])]; |
| 120 | await execFile('git', add); |
| 121 | return { branch: ref, path: wtPath, name }; |
| 122 | } |
| 123 | |
| 124 | /** Create the worktree if missing, ATTACH (reuse) it if it already exists. The |
| 125 | * session path uses this — naming the same worktree as another session must join |
| 126 | * its tree, never reset it (which would blow away a coder's work when a reviewer |
| 127 | * joins). Never resets: an existing dir attaches; an existing *branch* (worktree |
| 128 | * removed but branch kept) is checked out, preserving its commits. */ |
| 129 | export async function ensureWorktree(repo: string, name: string, base?: string): Promise<Worktree> { |
| 130 | const wtPath = worktreePath(name); |
| 131 | const ref = worktreeRef(name); |
| 132 | const attached = { branch: ref, path: wtPath, name }; |
| 133 | if (existsSync(wtPath)) { |
no test coverage detected