import type { ConfigDiffView, DiffLine } from "../contracts/workspace"; export function computeLineDiff(previous: string, next: string): DiffLine[] { const previousLines = previous.split("\n"); const nextLines = next.split("\n"); const m = previousLines.length; const n = nextLines.length; // classic LCS table; config files are small enough for O(m*n) const lcs: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); for (let i = m - 1; i >= 0; i -= 1) { for (let j = n - 1; j >= 0; j -= 1) { lcs[i][j] = previousLines[i] === nextLines[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1]); } } const lines: DiffLine[] = []; let i = 0; let j = 0; while (i < m && j < n) { if (previousLines[i] === nextLines[j]) { lines.push({ kind: "same", text: previousLines[i] }); i += 1; j += 1; } else if (lcs[i + 1][j] >= lcs[i][j + 1]) { lines.push({ kind: "removed", text: previousLines[i] }); i += 1; } else { lines.push({ kind: "added", text: nextLines[j] }); j += 1; } } while (i < m) { lines.push({ kind: "removed", text: previousLines[i] }); i += 1; } while (j < n) { lines.push({ kind: "added", text: nextLines[j] }); j += 1; } return lines; } export function buildConfigDiff(serverInstanceId: string, previous: string, next: string): ConfigDiffView { const lines = computeLineDiff(previous, next); const added = lines.filter((line) => line.kind === "added").length; const removed = lines.filter((line) => line.kind === "removed").length; return { serverInstanceId, summary: `+${added} / -${removed} 行变更`, lines, nextContent: next }; } export function diffHasChanges(diff: ConfigDiffView): boolean { return diff.lines.some((line) => line.kind !== "same"); }