diff options
| author | Dax <[email protected]> | 2026-04-07 19:48:23 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-04-07 19:48:23 -0400 |
| commit | b7fab49b64275b83bcec8200d7492fc5d15ffe06 (patch) | |
| tree | d9dadf65ca69eb4b8fe75654eb15666ee2b23774 /packages/ui/src/components/session-diff.ts | |
| parent | 463318486f94fa20e8d864d77708a347fa8423e3 (diff) | |
| download | opencode-b7fab49b64275b83bcec8200d7492fc5d15ffe06.tar.gz opencode-b7fab49b64275b83bcec8200d7492fc5d15ffe06.zip | |
refactor(snapshot): store unified patches in file diffs (#21244)
Co-authored-by: Adam <[email protected]>
Diffstat (limited to 'packages/ui/src/components/session-diff.ts')
| -rw-r--r-- | packages/ui/src/components/session-diff.ts | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/packages/ui/src/components/session-diff.ts b/packages/ui/src/components/session-diff.ts new file mode 100644 index 000000000..cc2b1ce52 --- /dev/null +++ b/packages/ui/src/components/session-diff.ts @@ -0,0 +1,83 @@ +import { parsePatchFiles, type FileDiffMetadata } from "@pierre/diffs" +import { sampledChecksum } from "@opencode-ai/util/encode" +import { formatPatch, structuredPatch } from "diff" +import type { SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2" + +type LegacyDiff = { + file: string + patch?: string + before?: string + after?: string + additions: number + deletions: number + status?: "added" | "deleted" | "modified" +} + +type ReviewDiff = SnapshotFileDiff | VcsFileDiff | LegacyDiff + +export type ViewDiff = { + file: string + patch: string + additions: number + deletions: number + status?: "added" | "deleted" | "modified" + fileDiff: FileDiffMetadata +} + +const cache = new Map<string, FileDiffMetadata>() + +function empty(file: string, key: string) { + return { + name: file, + type: "change", + hunks: [], + splitLineCount: 0, + unifiedLineCount: 0, + isPartial: true, + deletionLines: [], + additionLines: [], + cacheKey: key, + } satisfies FileDiffMetadata +} + +function patch(diff: ReviewDiff) { + if (typeof diff.patch === "string") return diff.patch + return formatPatch( + structuredPatch( + diff.file, + diff.file, + "before" in diff && typeof diff.before === "string" ? diff.before : "", + "after" in diff && typeof diff.after === "string" ? diff.after : "", + "", + "", + { context: Number.MAX_SAFE_INTEGER }, + ), + ) +} + +function file(file: string, patch: string) { + const hit = cache.get(patch) + if (hit) return hit + + const key = sampledChecksum(patch) ?? file + const value = parsePatchFiles(patch, key).flatMap((item) => item.files)[0] ?? empty(file, key) + cache.set(patch, value) + return value +} + +export function normalize(diff: ReviewDiff): ViewDiff { + const next = patch(diff) + return { + file: diff.file, + patch: next, + additions: diff.additions, + deletions: diff.deletions, + status: diff.status, + fileDiff: file(diff.file, next), + } +} + +export function text(diff: ViewDiff, side: "deletions" | "additions") { + if (side === "deletions") return diff.fileDiff.deletionLines.join("") + return diff.fileDiff.additionLines.join("") +} |
