refactor(hashline-edit): replace custom diff with diff library

🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2026-02-24 22:30:06 +09:00
parent ddf426c4b3
commit fcb90d92a4
4 changed files with 77 additions and 53 deletions
@@ -0,0 +1,71 @@
/// <reference types="bun-types" />
import { describe, expect, it } from "bun:test"
import { generateUnifiedDiff } from "./diff-utils"
function createNumberedLines(totalLineCount: number): string {
return Array.from({ length: totalLineCount }, (_, index) => `line ${index + 1}`).join("\n")
}
describe("generateUnifiedDiff", () => {
it("creates separate hunks for distant changes", () => {
//#given
const oldContent = createNumberedLines(60)
const newLines = oldContent.split("\n")
newLines[4] = "line 5 updated"
newLines[49] = "line 50 updated"
const newContent = newLines.join("\n")
//#when
const diff = generateUnifiedDiff(oldContent, newContent, "sample.txt")
//#then
const hunkHeaders = diff.match(/^@@/gm) ?? []
expect(hunkHeaders.length).toBe(2)
})
it("creates a single hunk for adjacent changes", () => {
//#given
const oldContent = createNumberedLines(20)
const newLines = oldContent.split("\n")
newLines[9] = "line 10 updated"
newLines[10] = "line 11 updated"
const newContent = newLines.join("\n")
//#when
const diff = generateUnifiedDiff(oldContent, newContent, "sample.txt")
//#then
const hunkHeaders = diff.match(/^@@/gm) ?? []
expect(hunkHeaders.length).toBe(1)
expect(diff).toContain(" line 8")
expect(diff).toContain(" line 13")
})
it("returns a diff string for identical content", () => {
//#given
const oldContent = "alpha\nbeta\ngamma"
const newContent = "alpha\nbeta\ngamma"
//#when
const diff = generateUnifiedDiff(oldContent, newContent, "sample.txt")
//#then
expect(typeof diff).toBe("string")
expect(diff).toContain("--- sample.txt")
expect(diff).toContain("+++ sample.txt")
})
it("returns a valid diff when old content is empty", () => {
//#given
const oldContent = ""
const newContent = "first line\nsecond line"
//#when
const diff = generateUnifiedDiff(oldContent, newContent, "sample.txt")
//#then
expect(diff).toContain("--- sample.txt")
expect(diff).toContain("+++ sample.txt")
expect(diff).toContain("+first line")
})
})
+2 -53
View File
@@ -1,3 +1,4 @@
import { createTwoFilesPatch } from "diff"
import { computeLineHash } from "./hash-computation"
export function toHashlineContent(content: string): string {
@@ -15,59 +16,7 @@ export function toHashlineContent(content: string): string {
}
export function generateUnifiedDiff(oldContent: string, newContent: string, filePath: string): string {
const oldLines = oldContent.split("\n")
const newLines = newContent.split("\n")
const maxLines = Math.max(oldLines.length, newLines.length)
let diff = `--- ${filePath}\n+++ ${filePath}\n`
let inHunk = false
let oldStart = 1
let newStart = 1
let oldCount = 0
let newCount = 0
let hunkLines: string[] = []
for (let i = 0; i < maxLines; i++) {
const oldLine = oldLines[i] ?? ""
const newLine = newLines[i] ?? ""
if (oldLine !== newLine) {
if (!inHunk) {
oldStart = i + 1
newStart = i + 1
oldCount = 0
newCount = 0
hunkLines = []
inHunk = true
}
if (oldLines[i] !== undefined) {
hunkLines.push(`-${oldLine}`)
oldCount++
}
if (newLines[i] !== undefined) {
hunkLines.push(`+${newLine}`)
newCount++
}
} else if (inHunk) {
hunkLines.push(` ${oldLine}`)
oldCount++
newCount++
if (hunkLines.length > 6) {
diff += `@@ -${oldStart},${oldCount} +${newStart},${newCount} @@\n`
diff += hunkLines.join("\n") + "\n"
inHunk = false
}
}
}
if (inHunk && hunkLines.length > 0) {
diff += `@@ -${oldStart},${oldCount} +${newStart},${newCount} @@\n`
diff += hunkLines.join("\n") + "\n"
}
return diff || `--- ${filePath}\n+++ ${filePath}\n`
return createTwoFilesPatch(filePath, filePath, oldContent, newContent)
}
export function countLineDiffs(oldContent: string, newContent: string): { additions: number; deletions: number } {