feat(core): add managed repository cache (#30408)
This commit is contained in:
parent
a78adb1b09
commit
371ee321e0
7 changed files with 839 additions and 4 deletions
|
|
@ -30,6 +30,15 @@ export interface Interface {
|
|||
readonly find: (input: AbsolutePath) => Effect.Effect<Repo | undefined>
|
||||
readonly remote: (repo: Repo, name?: string) => Effect.Effect<string | undefined>
|
||||
readonly roots: (repo: Repo) => Effect.Effect<string[]>
|
||||
readonly origin: (directory: string) => Effect.Effect<string | undefined>
|
||||
readonly head: (directory: string) => Effect.Effect<string | undefined>
|
||||
readonly branch: (directory: string) => Effect.Effect<string | undefined>
|
||||
readonly remoteHead: (directory: string) => Effect.Effect<string | undefined>
|
||||
readonly clone: (input: { remote: string; target: string; branch?: string; depth?: number }) => Effect.Effect<Result, AppProcess.AppProcessError>
|
||||
readonly fetch: (directory: string) => Effect.Effect<Result, AppProcess.AppProcessError>
|
||||
readonly fetchBranch: (directory: string, branch: string) => Effect.Effect<Result, AppProcess.AppProcessError>
|
||||
readonly checkout: (directory: string, branch: string) => Effect.Effect<Result, AppProcess.AppProcessError>
|
||||
readonly reset: (directory: string, target: string) => Effect.Effect<Result, AppProcess.AppProcessError>
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/GitV2") {}
|
||||
|
|
@ -75,7 +84,57 @@ export const layer = Layer.effect(
|
|||
.toSorted()
|
||||
})
|
||||
|
||||
return Service.of({ find, remote, roots })
|
||||
const origin = Effect.fn("Git.origin")(function* (directory: string) {
|
||||
const result = yield* run(directory, proc)(["config", "--get", "remote.origin.url"])
|
||||
if (result.exitCode !== 0) return undefined
|
||||
return result.text.trim() || undefined
|
||||
})
|
||||
|
||||
const head = Effect.fn("Git.head")(function* (directory: string) {
|
||||
const result = yield* run(directory, proc)(["rev-parse", "HEAD"])
|
||||
if (result.exitCode !== 0) return undefined
|
||||
return result.text.trim() || undefined
|
||||
})
|
||||
|
||||
const branch = Effect.fn("Git.branch")(function* (directory: string) {
|
||||
const result = yield* run(directory, proc)(["symbolic-ref", "--quiet", "--short", "HEAD"])
|
||||
if (result.exitCode !== 0) return undefined
|
||||
return result.text.trim() || undefined
|
||||
})
|
||||
|
||||
const remoteHead = Effect.fn("Git.remoteHead")(function* (directory: string) {
|
||||
const result = yield* run(directory, proc)(["symbolic-ref", "refs/remotes/origin/HEAD"])
|
||||
if (result.exitCode !== 0) return undefined
|
||||
return result.text.trim().replace(/^refs\/remotes\//, "") || undefined
|
||||
})
|
||||
|
||||
const clone = Effect.fn("Git.clone")((input: { remote: string; target: string; branch?: string; depth?: number }) =>
|
||||
execute(path.dirname(input.target), proc)([
|
||||
"clone",
|
||||
"--depth",
|
||||
String(input.depth ?? 100),
|
||||
...(input.branch ? ["--branch", input.branch] : []),
|
||||
"--",
|
||||
input.remote,
|
||||
input.target,
|
||||
]),
|
||||
)
|
||||
|
||||
const fetch = Effect.fn("Git.fetch")((directory: string) => execute(directory, proc)(["fetch", "--all", "--prune"]))
|
||||
|
||||
const fetchBranch = Effect.fn("Git.fetchBranch")((directory: string, branch: string) =>
|
||||
execute(directory, proc)(["fetch", "origin", `+refs/heads/${branch}:refs/remotes/origin/${branch}`]),
|
||||
)
|
||||
|
||||
const checkout = Effect.fn("Git.checkout")((directory: string, branch: string) =>
|
||||
execute(directory, proc)(["checkout", "-B", branch, `origin/${branch}`]),
|
||||
)
|
||||
|
||||
const reset = Effect.fn("Git.reset")((directory: string, target: string) =>
|
||||
execute(directory, proc)(["reset", "--hard", target]),
|
||||
)
|
||||
|
||||
return Service.of({ find, remote, roots, origin, head, branch, remoteHead, clone, fetch, fetchBranch, checkout, reset })
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -84,12 +143,17 @@ export const defaultLayer = layer.pipe(
|
|||
Layer.provide(AppProcess.defaultLayer),
|
||||
)
|
||||
|
||||
interface Result {
|
||||
export interface Result {
|
||||
readonly exitCode: number
|
||||
readonly text: string
|
||||
readonly stderr: string
|
||||
}
|
||||
|
||||
function run(cwd: string, proc: AppProcess.Interface) {
|
||||
return (args: string[]) => execute(cwd, proc)(args).pipe(Effect.catch(() => Effect.succeed({ exitCode: 1, text: "", stderr: "" })))
|
||||
}
|
||||
|
||||
function execute(cwd: string, proc: AppProcess.Interface) {
|
||||
return (args: string[]) =>
|
||||
proc
|
||||
.run(
|
||||
|
|
@ -100,8 +164,10 @@ function run(cwd: string, proc: AppProcess.Interface) {
|
|||
}),
|
||||
)
|
||||
.pipe(
|
||||
Effect.map((result) => ({ exitCode: result.exitCode, text: result.stdout.toString("utf8") }) satisfies Result),
|
||||
Effect.catch(() => Effect.succeed({ exitCode: 1, text: "" } satisfies Result)),
|
||||
Effect.map(
|
||||
(result) =>
|
||||
({ exitCode: result.exitCode, text: result.stdout.toString("utf8"), stderr: result.stderr.toString("utf8") }) satisfies Result,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue