fix(core): make worktrees read the project id from local workspace (#16795)

This commit is contained in:
James Long
2026-03-10 11:11:28 -04:00
committed by GitHub
parent 5a40158abf
commit 4c4aed5a87
2 changed files with 38 additions and 27 deletions

View File

@@ -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) { export async function fromDirectory(directory: string) {
log.info("fromDirectory", { directory }) log.info("fromDirectory", { directory })
@@ -101,19 +107,43 @@ export namespace Project {
const gitBinary = which("git") const gitBinary = which("git")
// cached id calculation // cached id calculation
let id = await Filesystem.readText(path.join(dotgit, "opencode")) let id = await readCachedId(dotgit)
.then((x) => x.trim())
.catch(() => undefined)
if (!gitBinary) { if (!gitBinary) {
return { return {
id: id ?? "global", id: id ?? "global",
worktree: sandbox, worktree: sandbox,
sandbox: sandbox, sandbox,
vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), 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 // generate id from root commit
if (!id) { if (!id) {
const roots = await git(["rev-list", "--max-parents=0", "--all"], { const roots = await git(["rev-list", "--max-parents=0", "--all"], {
@@ -132,7 +162,7 @@ export namespace Project {
return { return {
id: "global", id: "global",
worktree: sandbox, worktree: sandbox,
sandbox: sandbox, sandbox,
vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS),
} }
} }
@@ -147,7 +177,7 @@ export namespace Project {
return { return {
id: "global", id: "global",
worktree: sandbox, worktree: sandbox,
sandbox: sandbox, sandbox,
vcs: "git", vcs: "git",
} }
} }
@@ -161,33 +191,14 @@ export namespace Project {
if (!top) { if (!top) {
return { return {
id, id,
sandbox,
worktree: sandbox, worktree: sandbox,
sandbox,
vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS), vcs: Info.shape.vcs.parse(Flag.OPENCODE_FAKE_VCS),
} }
} }
sandbox = top 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 { return {
id, id,
sandbox, sandbox,

View File

@@ -413,7 +413,7 @@ export namespace Worktree {
await runStartScripts(info.directory, { projectID, extra }) await runStartScripts(info.directory, { projectID, extra })
} }
void start().catch((error) => { return start().catch((error) => {
log.error("worktree start task failed", { directory: info.directory, error }) log.error("worktree start task failed", { directory: info.directory, error })
}) })
} }