mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-22 18:25:32 -04:00
feat(plugin): bound vcs adapter diffs
This commit is contained in:
@@ -10,6 +10,7 @@ import { AppProcess } from "./process"
|
||||
import { VcsBackends } from "./vcs/backends"
|
||||
import { VcsGit } from "./vcs/git"
|
||||
import { VcsHg } from "./vcs/hg"
|
||||
import { MAX_TOTAL_PATCH_BYTES, PATCH_CONTEXT_LINES } from "./vcs/patch"
|
||||
|
||||
export { FileStatus, Mode }
|
||||
|
||||
@@ -60,7 +61,10 @@ const layer = Layer.effect(
|
||||
diff: Effect.fn("Vcs.diff")(function* (mode: Mode, options?: DiffOptions) {
|
||||
const impl = yield* adapter()
|
||||
if (!impl) return []
|
||||
return yield* impl.diff(mode, options)
|
||||
return yield* impl.diff(mode, {
|
||||
context: options?.context ?? PATCH_CONTEXT_LINES,
|
||||
maxOutputBytes: MAX_TOTAL_PATCH_BYTES,
|
||||
})
|
||||
}),
|
||||
})
|
||||
}),
|
||||
|
||||
@@ -81,10 +81,22 @@ function guard(type: string, make: () => Vcs.Adapter): Vcs.Adapter {
|
||||
adapter.pipe(
|
||||
Effect.flatMap((impl) => impl.diff(mode, options)),
|
||||
sanitize(type, "diff", decodeDiff),
|
||||
Effect.map((rows) => boundDiff(rows, options.maxOutputBytes)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
function boundDiff(rows: readonly FileDiff.Info[], maxOutputBytes: number) {
|
||||
let total = 0
|
||||
return rows.map((row) => {
|
||||
if (row.patch === undefined) return row
|
||||
const bytes = Buffer.byteLength(row.patch)
|
||||
if (total + bytes > maxOutputBytes) return { ...row, patch: undefined }
|
||||
total += bytes
|
||||
return row
|
||||
})
|
||||
}
|
||||
|
||||
function sanitize<A>(type: string, operation: string, decode: (input: unknown) => Option.Option<readonly A[]>) {
|
||||
return <E, R>(effect: Effect.Effect<readonly A[], E, R>) =>
|
||||
effect.pipe(
|
||||
|
||||
@@ -53,6 +53,23 @@ describe("VcsBackends", () => {
|
||||
}).pipe(Effect.scoped, provide),
|
||||
)
|
||||
|
||||
it.live("passes normalized options and bounds plugin diffs", () =>
|
||||
Effect.gen(function* () {
|
||||
let received: Parameters<PluginVcs.Adapter["diff"]>[1] | undefined
|
||||
yield* register(
|
||||
backend({
|
||||
diff: (_mode, options) => {
|
||||
received = options
|
||||
return Effect.succeed([{ ...diff[0], patch: "x".repeat(options.maxOutputBytes + 1) }])
|
||||
},
|
||||
}),
|
||||
)
|
||||
const vcs = yield* Vcs.Service
|
||||
expect(yield* vcs.diff("working", { context: 3 })).toEqual([{ ...diff[0], patch: undefined }])
|
||||
expect(received).toEqual({ context: 3, maxOutputBytes: 10_000_000 })
|
||||
}).pipe(Effect.scoped, provide),
|
||||
)
|
||||
|
||||
it.live("passes the location scope to the adapter factory", () =>
|
||||
Effect.gen(function* () {
|
||||
let scope: PluginVcs.AdapterScope | undefined
|
||||
|
||||
@@ -15,12 +15,14 @@ export interface AdapterScope {
|
||||
readonly store: string
|
||||
}
|
||||
|
||||
export interface DiffOptions {
|
||||
readonly context: number
|
||||
readonly maxOutputBytes: number
|
||||
}
|
||||
|
||||
export interface Adapter {
|
||||
readonly status: () => Effect.Effect<readonly FileStatus[]>
|
||||
readonly diff: (
|
||||
mode: Mode,
|
||||
options?: { readonly context?: number },
|
||||
) => Effect.Effect<readonly FileDiff.Info[]>
|
||||
readonly diff: (mode: Mode, options: DiffOptions) => Effect.Effect<readonly FileDiff.Info[]>
|
||||
}
|
||||
|
||||
export interface Backend {
|
||||
|
||||
Reference in New Issue
Block a user