fix: preserve BOM in text tool round-trips (#23797)
This commit is contained in:
@@ -18,6 +18,7 @@ import { Instance } from "../project/instance"
|
||||
import { Snapshot } from "@/snapshot"
|
||||
import { assertExternalDirectoryEffect } from "./external-directory"
|
||||
import { AppFileSystem } from "@opencode-ai/shared/filesystem"
|
||||
import * as Bom from "@/util/bom"
|
||||
|
||||
function normalizeLineEndings(text: string): string {
|
||||
return text.replaceAll("\r\n", "\n")
|
||||
@@ -84,7 +85,11 @@ export const EditTool = Tool.define(
|
||||
Effect.gen(function* () {
|
||||
if (params.oldString === "") {
|
||||
const existed = yield* afs.existsSafe(filePath)
|
||||
contentNew = params.newString
|
||||
const source = existed ? yield* Bom.readFile(afs, filePath) : { bom: false, text: "" }
|
||||
const next = Bom.split(params.newString)
|
||||
const desiredBom = source.bom || next.bom
|
||||
contentOld = source.text
|
||||
contentNew = next.text
|
||||
diff = trimDiff(createTwoFilesPatch(filePath, filePath, contentOld, contentNew))
|
||||
yield* ctx.ask({
|
||||
permission: "edit",
|
||||
@@ -95,8 +100,10 @@ export const EditTool = Tool.define(
|
||||
diff,
|
||||
},
|
||||
})
|
||||
yield* afs.writeWithDirs(filePath, params.newString)
|
||||
yield* format.file(filePath)
|
||||
yield* afs.writeWithDirs(filePath, Bom.join(contentNew, desiredBom))
|
||||
if (yield* format.file(filePath)) {
|
||||
contentNew = yield* Bom.syncFile(afs, filePath, desiredBom)
|
||||
}
|
||||
yield* bus.publish(File.Event.Edited, { file: filePath })
|
||||
yield* bus.publish(FileWatcher.Event.Updated, {
|
||||
file: filePath,
|
||||
@@ -108,13 +115,16 @@ export const EditTool = Tool.define(
|
||||
const info = yield* afs.stat(filePath).pipe(Effect.catch(() => Effect.succeed(undefined)))
|
||||
if (!info) throw new Error(`File ${filePath} not found`)
|
||||
if (info.type === "Directory") throw new Error(`Path is a directory, not a file: ${filePath}`)
|
||||
contentOld = yield* afs.readFileString(filePath)
|
||||
const source = yield* Bom.readFile(afs, filePath)
|
||||
contentOld = source.text
|
||||
|
||||
const ending = detectLineEnding(contentOld)
|
||||
const old = convertToLineEnding(normalizeLineEndings(params.oldString), ending)
|
||||
const next = convertToLineEnding(normalizeLineEndings(params.newString), ending)
|
||||
const replacement = convertToLineEnding(normalizeLineEndings(params.newString), ending)
|
||||
|
||||
contentNew = replace(contentOld, old, next, params.replaceAll)
|
||||
const next = Bom.split(replace(contentOld, old, replacement, params.replaceAll))
|
||||
const desiredBom = source.bom || next.bom
|
||||
contentNew = next.text
|
||||
|
||||
diff = trimDiff(
|
||||
createTwoFilesPatch(
|
||||
@@ -134,14 +144,15 @@ export const EditTool = Tool.define(
|
||||
},
|
||||
})
|
||||
|
||||
yield* afs.writeWithDirs(filePath, contentNew)
|
||||
yield* format.file(filePath)
|
||||
yield* afs.writeWithDirs(filePath, Bom.join(contentNew, desiredBom))
|
||||
if (yield* format.file(filePath)) {
|
||||
contentNew = yield* Bom.syncFile(afs, filePath, desiredBom)
|
||||
}
|
||||
yield* bus.publish(File.Event.Edited, { file: filePath })
|
||||
yield* bus.publish(FileWatcher.Event.Updated, {
|
||||
file: filePath,
|
||||
event: "change",
|
||||
})
|
||||
contentNew = yield* afs.readFileString(filePath)
|
||||
diff = trimDiff(
|
||||
createTwoFilesPatch(
|
||||
filePath,
|
||||
|
||||
Reference in New Issue
Block a user