import { assertEquals } from "@std/assert"; import { narrow, parsePatch } from "./patch.ts"; Deno.test("renames, deletions, additions and mode changes read as what happened to each file", () => { const files = parsePatch([ "diff --git a/old.txt b/new.txt", "similarity index 79%", "rename from old.txt", "rename to new.txt", "index f384549..b2f931a 100644", "--- a/old.txt", "+++ b/new.txt", "@@ -1,2 +1,3 @@", " one", " two", "+three", "diff --git a/keep.txt b/keep.txt", "deleted file mode 100644", "index de98044..0000000", "--- a/keep.txt", "+++ /dev/null", "@@ -1 +0,0 @@", "-a", "diff --git a/empty b/empty", "new file mode 100644", "index 0000000..e69de29", "diff --git a/script.sh b/script.sh", "old mode 100644", "new mode 100755", "diff --git a/bin.dat b/bin.dat", "index bdc955b..8835708 100644", "Binary files a/bin.dat and b/bin.dat differ", "", ].join("\n")); assertEquals( files.map(({ path, from, status, modes, binary }) => ({ path, from, status, modes, binary })), [ { path: "new.txt", from: "old.txt", status: "renamed", modes: { old: "100644", new: "100644" }, binary: false, }, { path: "keep.txt", from: null, status: "deleted", modes: { old: "100644", new: null }, binary: false, }, { path: "empty", from: null, status: "added", modes: { old: null, new: "100644" }, binary: false, }, { path: "script.sh", from: null, status: "modified", modes: { old: "100644", new: "100755" }, binary: false, }, { path: "bin.dat", from: null, status: "modified", modes: { old: "100644", new: "100644" }, binary: true, }, ], ); assertEquals(files[0].hunks, [{ old: 1, new: 1, lines: [" one", " two", "+three"] }]); assertEquals(files[1].hunks, [{ old: 1, new: 0, lines: ["-a"] }]); assertEquals(files[2].hunks, []); }); Deno.test("hunks keep missing newlines, carriage returns, and lines that look like headers", () => { const [file] = parsePatch([ "commit header that comes first", "", "diff --git a/x b/x", "--- a/x", "+++ b/x", "@@ -1,3 +1,3 @@", "-diff --git a/y b/y", "+--- a/y\r", "", " last", "\\ No newline at end of file", "", ].join("\n")); assertEquals(file.hunks, [{ old: 1, new: 1, lines: ["-diff --git a/y b/y", "+--- a/y\r", " ", " last", "\\ No newline at end of file"], }]); }); Deno.test("unusual paths read as themselves, quoted or not", () => { const files = parsePatch([ 'diff --git a/a.txt "b/b \\"c\\".txt"', "similarity index 100%", "rename from a.txt", 'rename to "b \\"c\\".txt"', 'diff --git "a/we ird\\\\t\\"q\\".txt" "b/we ird\\\\t\\"q\\".txt"', "index 45b983b..ab4a981 100644", '--- "a/we ird\\\\t\\"q\\".txt"\t', '+++ "b/we ird\\\\t\\"q\\".txt"\t', "@@ -1 +1 @@", "-hi", "+ho", "diff --git a/ünï cødé.txt b/ünï cødé.txt", "new file mode 100644", "index 0000000..e69de29", 'diff --git "a/\\303\\274.txt" "b/\\303\\274.txt"', "old mode 100644", "new mode 100755", "diff --git a/sp ace b/sp ace", "--- a/sp ace\t", "+++ b/sp ace\t", "@@ -1 +1 @@", "-a", "+b", ].join("\n")); assertEquals(files.map(({ path, from }) => [path, from]), [ ['b "c".txt', "a.txt"], ['we ird\\t"q".txt', null], ["ünï cødé.txt", null], ["ü.txt", null], ["sp ace", null], ]); }); Deno.test("narrowing a long file keeps the changes and their context, at their own line numbers", () => { const lines = Array.from({ length: 30 }, (_, i) => ` ${i + 1}`); lines[4] = "-5"; lines.splice(5, 0, "+five"); lines[25] = "-25"; const [file] = parsePatch( ["diff --git a/f b/f", "--- a/f", "+++ b/f", "@@ -1,30 +1,30 @@", ...lines].join("\n"), ); assertEquals(narrow(file, 2).hunks, [ { old: 3, new: 3, lines: [" 3", " 4", "-5", "+five", " 6", " 7"] }, { old: 23, new: 23, lines: [" 23", " 24", "-25", " 26", " 27"] }, ]); });