mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-21 15:53:27 +00:00
fix(core): reuse shared patch diff (#41186)
This commit is contained in:
parent
0df6aed6ca
commit
8c758e443b
2 changed files with 34 additions and 17 deletions
|
|
@ -3,7 +3,6 @@ export * as PatchTool from "./patch"
|
|||
import type { Context as PluginContext } from "@opencode-ai/plugin/effect/plugin"
|
||||
import { ToolFailure } from "@opencode-ai/ai"
|
||||
import { FileDiff } from "@opencode-ai/schema/file-diff"
|
||||
import { createTwoFilesPatch, diffLines } from "diff"
|
||||
import { Effect, Result, Schema } from "effect"
|
||||
import path from "path"
|
||||
import { Bom } from "@opencode-ai/util/bom"
|
||||
|
|
@ -15,6 +14,7 @@ import { Location } from "../../location"
|
|||
import { Patch } from "@opencode-ai/util/patch"
|
||||
import { Permission } from "../../permission"
|
||||
import DESCRIPTION from "../patch.txt"
|
||||
import { fileDiff } from "./file-diff"
|
||||
|
||||
export const name = "patch"
|
||||
|
||||
|
|
@ -353,22 +353,16 @@ function errorMessage(error: unknown) {
|
|||
|
||||
function patchFile(change: Prepared, after = change.after): typeof FileDiff.Info.Type {
|
||||
const target = (change.type === "update" ? change.moveTarget : undefined)?.resource ?? change.target.resource
|
||||
const patch = trimDiff(createTwoFilesPatch(change.target.absolute, change.target.absolute, change.before, after))
|
||||
const counts =
|
||||
change.type === "delete"
|
||||
? { additions: 0, deletions: change.before.split("\n").length }
|
||||
: diffLines(change.before, after).reduce(
|
||||
(result, item) => ({
|
||||
additions: result.additions + (item.added ? (item.count ?? 0) : 0),
|
||||
deletions: result.deletions + (item.removed ? (item.count ?? 0) : 0),
|
||||
}),
|
||||
{ additions: 0, deletions: 0 },
|
||||
)
|
||||
const diff = fileDiff(
|
||||
change.target.absolute,
|
||||
change.before,
|
||||
after,
|
||||
change.type === "add" ? "added" : change.type === "delete" ? "deleted" : "modified",
|
||||
)
|
||||
return {
|
||||
...diff,
|
||||
file: target,
|
||||
patch,
|
||||
status: change.type === "add" ? "added" : change.type === "delete" ? "deleted" : "modified",
|
||||
...counts,
|
||||
patch: trimDiff(diff.patch),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ describe("PatchTool", () => {
|
|||
file: "remove.txt",
|
||||
status: "deleted",
|
||||
additions: 0,
|
||||
deletions: 2,
|
||||
deletions: 1,
|
||||
patch: expect.stringContaining("-remove"),
|
||||
},
|
||||
],
|
||||
|
|
@ -248,6 +248,29 @@ describe("PatchTool", () => {
|
|||
),
|
||||
)
|
||||
|
||||
it.live("counts deleted lines with and without a trailing newline", () =>
|
||||
withTempTool((directory, registry) =>
|
||||
Effect.gen(function* () {
|
||||
yield* Effect.promise(() =>
|
||||
Promise.all([
|
||||
fs.writeFile(path.join(directory, "trailing.txt"), "remove\n"),
|
||||
fs.writeFile(path.join(directory, "unterminated.txt"), "remove"),
|
||||
]),
|
||||
)
|
||||
const settled = yield* executeTool(
|
||||
registry,
|
||||
call("*** Begin Patch\n*** Delete File: trailing.txt\n*** Delete File: unterminated.txt\n*** End Patch"),
|
||||
)
|
||||
expect(settled.status).toBe("completed")
|
||||
if (settled.status !== "completed") return
|
||||
expect(settled.output.files).toMatchObject([
|
||||
{ file: "trailing.txt", additions: 0, deletions: 1 },
|
||||
{ file: "unterminated.txt", additions: 0, deletions: 1 },
|
||||
])
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
it.live("serializes concurrent patch transactions", () =>
|
||||
withTempTool((directory, registry) => {
|
||||
const target = path.join(directory, "concurrent.txt")
|
||||
|
|
@ -446,7 +469,7 @@ describe("PatchTool", () => {
|
|||
{
|
||||
file: "renamed/dir/name.txt",
|
||||
status: "modified",
|
||||
patch: expect.stringContaining("-old content\n+new content"),
|
||||
patch: expect.stringContaining(`Index: ${source}`),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue