Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
TypeScript
at icy/tmrrpn
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147import type { ChangeContent, ContextContent, FileDiffMetadata, Hunk } from "@pierre/diffs";import { LineOp, type DiffFile } from "$lib/api/diff";
// old alone collides when one file is deleted and another renamed onto its// path in the same commit so we need new tooexport const diffRowKey = (file: DiffFile): string => `${file.name.old}→${file.name.new}`;
// pierre parses patch text into FileDiffMetadata, but the wire already hands// us hunks, so we can skip the text roundtrip by mappingexport const toFileDiffMetadata = (file: DiffFile): FileDiffMetadata => { const fragments = file.text_fragments ?? [];
const hunks: Hunk[] = []; const deletionLines: string[] = []; const additionLines: string[] = []; let splitLineCount = 0; let unifiedLineCount = 0; let lastHunkEnd = 0;
for (const fragment of fragments) { const additionStart = fragment.NewPosition ?? 0; const additionCount = fragment.NewLines ?? 0; const deletionStart = fragment.OldPosition ?? 0; const deletionCount = fragment.OldLines ?? 0;
const collapsedBefore = Math.max(additionStart - 1 - lastHunkEnd, 0); lastHunkEnd = additionStart + additionCount - 1;
const hunk: Hunk = { collapsedBefore, additionStart, additionCount, additionLines: 0, additionLineIndex: additionLines.length, deletionStart, deletionCount, deletionLines: 0, deletionLineIndex: deletionLines.length, hunkContent: [], hunkContext: fragment.Comment, hunkSpecs: `@@ -${deletionStart},${deletionCount} +${additionStart},${additionCount} @@`, splitLineStart: 0, splitLineCount: 0, unifiedLineStart: 0, unifiedLineCount: 0, noEOFCRDeletions: false, noEOFCRAdditions: false };
let current: ContextContent | ChangeContent | null = null; let lastOp: LineOp | null = null; for (const { Op: op, Line: raw } of fragment.Lines ?? []) { if (op === LineOp.Context) { if (current?.type !== "context") { current = { type: "context", lines: 0, additionLineIndex: additionLines.length, deletionLineIndex: deletionLines.length }; hunk.hunkContent.push(current); } current.lines++; additionLines.push(raw); deletionLines.push(raw); } else { if (current?.type !== "change") { current = { type: "change", additions: 0, deletions: 0, additionLineIndex: additionLines.length, deletionLineIndex: deletionLines.length }; hunk.hunkContent.push(current); } if (op === LineOp.Add) { current.additions++; hunk.additionLines++; additionLines.push(raw); } else { current.deletions++; hunk.deletionLines++; deletionLines.push(raw); } } lastOp = op; }
// a line without a trailing newline is the patch's "\ No newline" // marker, only possible at the end of the file const last = fragment.Lines?.[fragment.Lines.length - 1]; if (last && !last.Line.endsWith("\n")) { if (last.Op === LineOp.Context) { hunk.noEOFCRAdditions = true; hunk.noEOFCRDeletions = true; } else if (last.Op === LineOp.Delete) { hunk.noEOFCRDeletions = true; } else { hunk.noEOFCRAdditions = true; } if (lastOp === LineOp.Add || lastOp === LineOp.Context) { additionLines[additionLines.length - 1] = last.Line; } if (lastOp === LineOp.Delete || lastOp === LineOp.Context) { deletionLines[deletionLines.length - 1] = last.Line; } }
for (const content of hunk.hunkContent) { if (content.type === "context") { hunk.splitLineCount += content.lines; hunk.unifiedLineCount += content.lines; } else { hunk.splitLineCount += Math.max(content.additions, content.deletions); hunk.unifiedLineCount += content.deletions + content.additions; } } hunk.splitLineStart = splitLineCount + collapsedBefore; hunk.unifiedLineStart = unifiedLineCount + collapsedBefore; splitLineCount += collapsedBefore + hunk.splitLineCount; unifiedLineCount += collapsedBefore + hunk.unifiedLineCount;
hunks.push(hunk); }
const type: FileDiffMetadata["type"] = file.is_new ? "new" : file.is_delete ? "deleted" : file.is_rename ? "rename-changed" : "change";
return { name: file.name.new || file.name.old, prevName: type === "rename-changed" ? file.name.old : undefined, type, hunks, splitLineCount, unifiedLineCount, isPartial: true, deletionLines, additionLines };};