feat(core): allow external workspace creation (#26212)

This commit is contained in:
James Long
2026-05-08 11:09:12 -04:00
committed by GitHub
parent c36ab3f935
commit c818c9dcb6
21 changed files with 2039 additions and 145 deletions

View File

@@ -117,6 +117,13 @@ export const ResetFailedError = NamedError.create(
}),
)
export const ListFailedError = NamedError.create(
"WorktreeListFailedError",
z.object({
message: z.string(),
}),
)
function slugify(input: string) {
return input
.trim()
@@ -149,6 +156,7 @@ export interface Interface {
readonly makeWorktreeInfo: (name?: string) => Effect.Effect<Info>
readonly createFromInfo: (info: Info, startCommand?: string) => Effect.Effect<void>
readonly create: (input?: CreateInput) => Effect.Effect<Info>
readonly list: () => Effect.Effect<(Omit<Info, "branch"> & { branch?: string })[]>
readonly remove: (input: RemoveInput) => Effect.Effect<boolean>
readonly reset: (input: ResetInput) => Effect.Effect<boolean>
}
@@ -341,6 +349,32 @@ export const layer: Layer.Layer<
return undefined
})
const list = Effect.fn("Worktree.list")(function* () {
const ctx = yield* InstanceState.context
if (ctx.project.vcs !== "git") {
return []
}
const result = yield* git(["worktree", "list", "--porcelain"], { cwd: ctx.worktree })
if (result.code !== 0) {
throw new ListFailedError({ message: result.stderr || result.text || "Failed to read git worktrees" })
}
const primary = yield* canonical(ctx.worktree)
return yield* Effect.forEach(parseWorktreeList(result.text), (entry) =>
Effect.gen(function* () {
if (!entry.path) return undefined
const directory = yield* canonical(entry.path)
if (directory === primary) return undefined
return {
name: pathSvc.basename(directory),
directory,
...(entry.branch ? { branch: entry.branch.replace(/^refs\/heads\//, "") } : {}),
}
}),
).pipe(Effect.map((items) => items.filter((item) => item !== undefined)))
})
function stopFsmonitor(target: string) {
return fs.exists(target).pipe(
Effect.orDie,
@@ -579,7 +613,7 @@ export const layer: Layer.Layer<
return true
})
return Service.of({ makeWorktreeInfo, createFromInfo, create, remove, reset })
return Service.of({ makeWorktreeInfo, createFromInfo, create, list, remove, reset })
}),
)