diff --git a/packages/opencode/src/project/project.ts b/packages/opencode/src/project/project.ts index e1fff1a1470..68cece0a52a 100644 --- a/packages/opencode/src/project/project.ts +++ b/packages/opencode/src/project/project.ts @@ -88,6 +88,12 @@ export namespace Project { } } + function readCachedId(dir: string) { + return Filesystem.readText(path.join(dir, "opencode")) + .then((x) => x.trim()) + .catch(() => undefined) + } + export async function fromDirectory(directory: string) { log.info("fromDirectory", { directory }) @@ -101,19 +107,43 @@ export namespace Project { const gitBinary = which("git") // cached id calculation - let id = await Filesystem.readText(path.join(dotgit, "opencode")) - .then((x) => x.trim()) - .catch(() => undefined) + let id = await readCachedId(dotgit) if (!gitBinary) { return { id: id ?? "global", worktree: sandbox, - sandbox: sandbox, + sandbox, + vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), + } + } + + const worktree = await git(["rev-parse", "--git-common-dir"], { + cwd: sandbox, + }) + .then(async (result) => { + const common = gitpath(sandbox, await result.text()) + // Avoid going to parent of sandbox when git-common-dir is empty. + return common === sandbox ? sandbox : path.dirname(common) + }) + .catch(() => undefined) + + if (!worktree) { + return { + id: id ?? "global", + worktree: sandbox, + sandbox, vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), } } + // In the case of a git worktree, it can't cache the id + // because `.git` is not a folder, but it always needs the + // same project id as the common dir, so we resolve it now + if (id == null) { + id = await readCachedId(path.join(worktree, ".git")) + } + // generate id from root commit if (!id) { const roots = await git(["rev-list", "--max-parents=0", "--all"], { @@ -132,7 +162,7 @@ export namespace Project { return { id: "global", worktree: sandbox, - sandbox: sandbox, + sandbox, vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), } } @@ -147,7 +177,7 @@ export namespace Project { return { id: "global", worktree: sandbox, - sandbox: sandbox, + sandbox, vcs: "git", } } @@ -161,33 +191,14 @@ export namespace Project { if (!top) { return { id, - sandbox, worktree: sandbox, + sandbox, vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), } } sandbox = top - const worktree = await git(["rev-parse", "--git-common-dir"], { - cwd: sandbox, - }) - .then(async (result) => { - const common = gitpath(sandbox, await result.text()) - // Avoid going to parent of sandbox when git-common-dir is empty. - return common === sandbox ? sandbox : path.dirname(common) - }) - .catch(() => undefined) - - if (!worktree) { - return { - id, - sandbox, - worktree: sandbox, - vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), - } - } - return { id, sandbox, diff --git a/packages/opencode/src/worktree/index.ts b/packages/opencode/src/worktree/index.ts index 15efcea3869..8f10620f1de 100644 --- a/packages/opencode/src/worktree/index.ts +++ b/packages/opencode/src/worktree/index.ts @@ -411,7 +411,7 @@ export namespace Worktree { await runStartScripts(info.directory, { projectID, extra }) } - void start().catch((error) => { + return start().catch((error) => { log.error("worktree start task failed", { directory: info.directory, error }) }) }