fix(core): branch-keyed repository cache with gated reference readiness (#38759)

This commit is contained in:
Kit Langton 2026-07-24 21:23:44 -04:00 committed by GitHub
commit 065dc274ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 89 additions and 52 deletions

View file

@ -47,7 +47,7 @@ describe("Reference", () => {
expect(yield* references.list()).toEqual([
new Reference.Info({
name: "sdk",
path: AbsolutePath.make(Repository.cachePath(Global.Path.repos, repository)),
path: AbsolutePath.make(Repository.cachePath(Global.Path.repos, repository, "main")),
source,
}),
])

View file

@ -8,7 +8,7 @@ import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { Global } from "@opencode-ai/core/global"
import { Repository } from "@opencode-ai/core/repository"
import { RepositoryCache } from "@opencode-ai/core/repository-cache"
import { git, gitRemote } from "./fixture/git"
import { branch, git, gitRemote } from "./fixture/git"
import { tmpdir } from "./fixture/tmpdir"
import { testEffect } from "./lib/effect"
@ -66,6 +66,41 @@ describe("RepositoryCache", () => {
),
)
it.live("keeps branch checkouts isolated from branchless refreshes", () =>
withRemote((fixture) =>
Effect.gen(function* () {
yield* Effect.promise(() => branch(fixture.source, "feature", "two\n"))
const cache = yield* RepositoryCache.Service
const featured = yield* cache.ensure({ reference: fixture.reference, branch: "feature" })
expect(featured.branch).toBe("feature")
expect(featured.localPath.endsWith("repo@feature")).toBe(true)
expect(yield* read(path.join(featured.localPath, "README.md"))).toBe("two\n")
const refreshed = yield* cache.ensure({ reference: fixture.reference, refresh: true })
expect(refreshed.localPath).not.toBe(featured.localPath)
expect(yield* read(path.join(refreshed.localPath, "README.md"))).toBe("one\n")
const cached = yield* cache.ensure({ reference: fixture.reference, branch: "feature" })
expect(cached.status).toBe("cached")
expect(yield* read(path.join(cached.localPath, "README.md"))).toBe("two\n")
}).pipe(Effect.provide(cacheLayer(fixture.root))),
),
)
it.live("does not mistake an enclosing repository for the cache checkout", () =>
withRemote((fixture) =>
Effect.gen(function* () {
yield* Effect.promise(() => git(fixture.root, "clone", fixture.remote, path.join(fixture.root, "repos")))
const result = yield* (yield* RepositoryCache.Service).ensure({ reference: fixture.reference })
expect(result.status).toBe("cloned")
expect(yield* read(path.join(result.localPath, "README.md"))).toBe("one\n")
}).pipe(Effect.provide(cacheLayer(fixture.root))),
),
)
it.live("returns typed validation and clone failures", () =>
withRemote((fixture) =>
Effect.gen(function* () {

View file

@ -17,6 +17,12 @@ describe("Repository", () => {
label: "owner/repo",
})
expect(Repository.cachePath("/cache", reference)).toBe(path.join("/cache", "github.com", "owner", "repo"))
expect(Repository.cachePath("/cache", reference, "main")).toBe(
path.join("/cache", "github.com", "owner", "repo@main"),
)
expect(Repository.cachePath("/cache", reference, "feature/x")).toBe(
path.join("/cache", "github.com", "owner", "repo@feature%2Fx"),
)
expect(Repository.cacheIdentity(reference)).toBe("github.com/owner/repo")
})