Просмотр исходного кода

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

James Long 1 месяц назад
Родитель
Сommit
4c4aed5a87
2 измененных файлов с 38 добавлено и 27 удалено
  1. 37 26
      packages/opencode/src/project/project.ts
  2. 1 1
      packages/opencode/src/worktree/index.ts

+ 37 - 26
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) {
   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"))
-          .then((x) => x.trim())
-          .catch(() => undefined)
+        let id = await readCachedId(dotgit)
 
 
         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),
+          }
+        }
+
+        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),
             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,

+ 1 - 1
packages/opencode/src/worktree/index.ts

@@ -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 })
       })
       })
     }
     }