Browse Source

refactor(core): combine git discovery queries (#36321)

Kit Langton 1 month ago
parent
commit
6b3c4f5839
2 changed files with 26 additions and 8 deletions
  1. 6 8
      packages/core/src/git.ts
  2. 20 0
      packages/core/test/git.test.ts

+ 6 - 8
packages/core/src/git.ts

@@ -189,16 +189,14 @@ const layer = Layer.effect(
       if (!dotgit) return undefined
 
       const cwd = path.dirname(dotgit)
-      const git = run(cwd, proc)
-      const topLevel = yield* git(["rev-parse", "--show-toplevel"])
-      const gitDir = yield* git(["rev-parse", "--git-dir"])
-      const commonDir = yield* git(["rev-parse", "--git-common-dir"])
-      if (gitDir.exitCode !== 0 || commonDir.exitCode !== 0) return undefined
+      const result = yield* run(cwd, proc)(["rev-parse", "--git-dir", "--git-common-dir", "--show-toplevel"])
+      const [gitDir, commonDir, topLevel] = result.text.split(/\r?\n/)
+      if (!gitDir || !commonDir) return undefined
 
       return new Repository({
-        worktree: AbsolutePath.make(topLevel.exitCode === 0 ? resolvePath(cwd, topLevel.text) : cwd),
-        gitDirectory: AbsolutePath.make(resolvePath(cwd, gitDir.text)),
-        commonDirectory: AbsolutePath.make(resolvePath(cwd, commonDir.text)),
+        worktree: AbsolutePath.make(topLevel ? resolvePath(cwd, topLevel) : cwd),
+        gitDirectory: AbsolutePath.make(resolvePath(cwd, gitDir)),
+        commonDirectory: AbsolutePath.make(resolvePath(cwd, commonDir)),
       })
     })
 

+ 20 - 0
packages/core/test/git.test.ts

@@ -13,6 +13,26 @@ import { testEffect } from "./lib/effect"
 const it = testEffect(LayerNode.compile(Git.node))
 
 describe("Git", () => {
+  it.live("discovers repository metadata without a work tree", () =>
+    Effect.gen(function* () {
+      const root = yield* Effect.acquireRelease(
+        Effect.promise(() => tmpdir()),
+        (dir) => Effect.promise(() => dir[Symbol.asyncDispose]()),
+      )
+      yield* Effect.promise(async () => {
+        await initRepo(root.path)
+        await $`git config core.bare true`.cwd(root.path).quiet()
+      })
+      const directory = AbsolutePath.make(yield* Effect.promise(() => fs.realpath(root.path)))
+      const git = yield* Git.Service
+      const repository = yield* git.repo.discover(directory)
+
+      expect(repository?.worktree).toBe(directory)
+      expect(repository?.gitDirectory).toBe(AbsolutePath.make(path.join(directory, ".git")))
+      expect(repository?.commonDirectory).toBe(repository?.gitDirectory)
+    }),
+  )
+
   it.live("clones a remote and reads checkout metadata", () =>
     withRemote((fixture) =>
       Effect.gen(function* () {