mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-09 22:25:02 +03:00
fix(core): keep trailing blank lines a patch does not touch
derive() split the file into lines, dropped the terminating empty element, and then restored a final newline only when the last line was not already empty. A file ending in a blank line therefore lost that blank line on every update, and a hunk adding an empty line at the end of a file had it silently dropped. Always restoring the terminator preserves the file's own trailing newlines while still adding one to a file that lacked it.
This commit is contained in:
@@ -248,6 +248,15 @@ describe("Patch", () => {
|
||||
).toBe("line 1\nline 2\nadded 1\nadded 2\n")
|
||||
})
|
||||
|
||||
test("keeps trailing blank lines the patch did not touch", () => {
|
||||
expect(
|
||||
Patch.derive("update.txt", [{ oldLines: ["line 2"], newLines: ["LINE 2"] }], "line 1\nline 2\n\n").content,
|
||||
).toBe("line 1\nLINE 2\n\n")
|
||||
expect(
|
||||
Patch.derive("update.txt", [{ oldLines: ["line 1"], newLines: ["line 1", ""] }], "line 1\n").content,
|
||||
).toBe("line 1\n\n")
|
||||
})
|
||||
|
||||
test.each(["", "original\n"])("preserves equal-offset insertion order and frozen chunks for %j", (original) => {
|
||||
const chunks = Object.freeze([
|
||||
Object.freeze({ oldLines: Object.freeze([]), newLines: Object.freeze(["first"]) }),
|
||||
|
||||
@@ -131,7 +131,10 @@ export function derive(path: string, chunks: ReadonlyArray<UpdateFileChunk>, ori
|
||||
if (lines.at(-1) === "") lines.pop()
|
||||
const replacements = computeReplacements(lines, path, chunks)
|
||||
for (const [start, remove, insert] of replacements.reverse()) lines.splice(start, remove, ...insert)
|
||||
if (lines.at(-1) !== "") lines.push("")
|
||||
// The split above lost the final newline as an empty element, and the file must end with one. Always
|
||||
// restoring it keeps any other trailing blank lines the patch did not touch, which is why this is not
|
||||
// conditional on the array's last line.
|
||||
lines.push("")
|
||||
const next = Bom.split(lines.join("\n"))
|
||||
return { content: next.text, bom: source.bom || next.bom }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user