import { execFile } from "node:child_process"; import { mkdir } from "node:fs/promises"; import { join, resolve } from "node:path"; import { promisify } from "node:util"; const execFileAsync = promisify(execFile); export interface Worktree { path: string; baseCommit: string } async function git(cwd: string, args: string[]): Promise { const { stdout } = await execFileAsync("git", args, { cwd, encoding: "utf8" }); return stdout.trim(); } export async function createWorktree(repo: string, root: string, runId: string, nodeId: string): Promise { if (!/^[\w-]+$/.test(runId) || !/^[\w-]+$/.test(nodeId)) throw new Error("Invalid worktree identifier"); const baseCommit = await git(repo, ["rev-parse", "HEAD"]); const path = resolve(root, runId, nodeId); await mkdir(join(root, runId), { recursive: true }); await git(repo, ["worktree", "add", "--detach", path, baseCommit]); return { path, baseCommit }; } export async function removeWorktree(repo: string, worktree: string): Promise { await git(repo, ["worktree", "remove", "--force", worktree]); }