fix(opencode): lost sessions across worktrees and orphan branches (#16389)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
This commit is contained in:
co-authored by
Aiden Cline
parent
f54abe58cf
commit
4b9b86b544
@@ -147,7 +147,7 @@ export namespace Project {
|
|||||||
|
|
||||||
// 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", "HEAD"], {
|
||||||
cwd: sandbox,
|
cwd: sandbox,
|
||||||
})
|
})
|
||||||
.then(async (result) =>
|
.then(async (result) =>
|
||||||
@@ -170,7 +170,8 @@ export namespace Project {
|
|||||||
|
|
||||||
id = roots[0] ? ProjectID.make(roots[0]) : undefined
|
id = roots[0] ? ProjectID.make(roots[0]) : undefined
|
||||||
if (id) {
|
if (id) {
|
||||||
await Filesystem.write(path.join(dotgit, "opencode"), id).catch(() => undefined)
|
// Write to common dir so the cache is shared across worktrees.
|
||||||
|
await Filesystem.write(path.join(worktree, ".git", "opencode"), id).catch(() => undefined)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ mock.module("../../src/util/git", () => ({
|
|||||||
mode === "rev-list-fail" &&
|
mode === "rev-list-fail" &&
|
||||||
cmd.includes("git rev-list") &&
|
cmd.includes("git rev-list") &&
|
||||||
cmd.includes("--max-parents=0") &&
|
cmd.includes("--max-parents=0") &&
|
||||||
cmd.includes("--all")
|
cmd.includes("HEAD")
|
||||||
) {
|
) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
exitCode: 128,
|
exitCode: 128,
|
||||||
@@ -172,6 +172,52 @@ describe("Project.fromDirectory with worktrees", () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("worktree should share project ID with main repo", async () => {
|
||||||
|
const p = await loadProject()
|
||||||
|
await using tmp = await tmpdir({ git: true })
|
||||||
|
|
||||||
|
const { project: main } = await p.fromDirectory(tmp.path)
|
||||||
|
|
||||||
|
const worktreePath = path.join(tmp.path, "..", path.basename(tmp.path) + "-wt-shared")
|
||||||
|
try {
|
||||||
|
await $`git worktree add ${worktreePath} -b shared-${Date.now()}`.cwd(tmp.path).quiet()
|
||||||
|
|
||||||
|
const { project: wt } = await p.fromDirectory(worktreePath)
|
||||||
|
|
||||||
|
expect(wt.id).toBe(main.id)
|
||||||
|
|
||||||
|
// Cache should live in the common .git dir, not the worktree's .git file
|
||||||
|
const cache = path.join(tmp.path, ".git", "opencode")
|
||||||
|
const exists = await Filesystem.exists(cache)
|
||||||
|
expect(exists).toBe(true)
|
||||||
|
} finally {
|
||||||
|
await $`git worktree remove ${worktreePath}`
|
||||||
|
.cwd(tmp.path)
|
||||||
|
.quiet()
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test("separate clones of the same repo should share project ID", async () => {
|
||||||
|
const p = await loadProject()
|
||||||
|
await using tmp = await tmpdir({ git: true })
|
||||||
|
|
||||||
|
// Create a bare remote, push, then clone into a second directory
|
||||||
|
const bare = tmp.path + "-bare"
|
||||||
|
const clone = tmp.path + "-clone"
|
||||||
|
try {
|
||||||
|
await $`git clone --bare ${tmp.path} ${bare}`.quiet()
|
||||||
|
await $`git clone ${bare} ${clone}`.quiet()
|
||||||
|
|
||||||
|
const { project: a } = await p.fromDirectory(tmp.path)
|
||||||
|
const { project: b } = await p.fromDirectory(clone)
|
||||||
|
|
||||||
|
expect(b.id).toBe(a.id)
|
||||||
|
} finally {
|
||||||
|
await $`rm -rf ${bare} ${clone}`.quiet().nothrow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test("should accumulate multiple worktrees in sandboxes", async () => {
|
test("should accumulate multiple worktrees in sandboxes", async () => {
|
||||||
const p = await loadProject()
|
const p = await loadProject()
|
||||||
await using tmp = await tmpdir({ git: true })
|
await using tmp = await tmpdir({ git: true })
|
||||||
|
|||||||
Reference in New Issue
Block a user