1 | const parse = require("../index");
|
2 |
|
3 | describe("diff parser", function () {
|
4 | it("should parse null", () => {
|
5 | expect(parse(null).length).toBe(0);
|
6 | });
|
7 |
|
8 | it("should parse empty string", () => {
|
9 | expect(parse("").length).toBe(0);
|
10 | });
|
11 |
|
12 | it("should parse whitespace", () => {
|
13 | expect(parse(" ").length).toBe(0);
|
14 | });
|
15 |
|
16 | it("should parse simple git-like diff", function () {
|
17 | const diff = `\
|
18 | diff --git a/file b/file
|
19 | index 123..456 789
|
20 | --- a/file
|
21 | +++ b/file
|
22 | @@ -1,2 +1,2 @@
|
23 | - line1
|
24 | + line2\
|
25 | `;
|
26 | const files = parse(diff);
|
27 | expect(files.length).toBe(1);
|
28 | const file = files[0];
|
29 | expect(file.from).toBe("file");
|
30 | expect(file.to).toBe("file");
|
31 | expect(file.deletions).toBe(1);
|
32 | expect(file.additions).toBe(1);
|
33 | expect(file.chunks.length).toBe(1);
|
34 | const chunk = file.chunks[0];
|
35 | expect(chunk.content).toBe("@@ -1,2 +1,2 @@");
|
36 | expect(chunk.changes.length).toBe(2);
|
37 | expect(chunk.changes[0].content).toBe("- line1");
|
38 | expect(chunk.changes[1].content).toBe("+ line2");
|
39 | });
|
40 |
|
41 | it("should parse file names when diff.mnemonicPrefix equals true", function () {
|
42 | const diff = `\
|
43 | diff --git i/file w/file
|
44 | index 123..456 789
|
45 | --- i/file
|
46 | +++ w/file
|
47 | @@ -1,2 +1,2 @@
|
48 | - line1
|
49 | + line2\
|
50 | `;
|
51 | const files = parse(diff);
|
52 | expect(files.length).toBe(1);
|
53 | const file = files[0];
|
54 | expect(file.from).toBe("file");
|
55 | expect(file.to).toBe("file");
|
56 | });
|
57 |
|
58 | it("should parse simple git-like diff with file enclosed by double-quote", function () {
|
59 | const diff = `\
|
60 | diff --git "a/file1" "b/file2"
|
61 | similarity index 100%
|
62 | rename from "file1"
|
63 | rename to "file2"\
|
64 | `;
|
65 | const files = parse(diff);
|
66 | expect(files.length).toBe(1);
|
67 | const file = files[0];
|
68 | expect(file.from).toBe("file1");
|
69 | expect(file.to).toBe("file2");
|
70 | expect(file.chunks.length).toBe(0);
|
71 | });
|
72 |
|
73 | it("should parse file names for changed binaries with spaces in their names", function () {
|
74 | const diff = `\
|
75 | diff --git a/Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png b/Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png
|
76 | index fc72ba34b..ec373e9a4 100644
|
77 | Binary files a/Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png and b/Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png differ\
|
78 | `;
|
79 | const files = parse(diff);
|
80 | expect(files.length).toBe(1);
|
81 | const file = files[0];
|
82 | expect(file.from).toBe(
|
83 | "Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png"
|
84 | );
|
85 | expect(file.to).toBe(
|
86 | "Artsy_Tests/ReferenceImages/ARTopMenuViewControllerSpec/selects 'home' by default as ipad@2x.png"
|
87 | );
|
88 | });
|
89 |
|
90 | it("should parse diff with new file mode line", function () {
|
91 | const diff = `\
|
92 | diff --git a/test b/test
|
93 | new file mode 100644
|
94 | index 0000000..db81be4
|
95 | --- /dev/null
|
96 | +++ b/test
|
97 | @@ -0,0 +1,2 @@
|
98 | +line1
|
99 | +line2\
|
100 | `;
|
101 | const files = parse(diff);
|
102 | expect(files.length).toBe(1);
|
103 | const file = files[0];
|
104 | expect(file.new).toBeTruthy();
|
105 | expect(file.from).toBe("/dev/null");
|
106 | expect(file.to).toBe("test");
|
107 | expect(file.chunks[0].content).toBe("@@ -0,0 +1,2 @@");
|
108 | expect(file.chunks[0].changes.length).toBe(2);
|
109 | expect(file.chunks[0].changes[0].content).toBe("+line1");
|
110 | expect(file.chunks[0].changes[1].content).toBe("+line2");
|
111 | });
|
112 |
|
113 | it("should parse diff with deleted file mode line", function () {
|
114 | const diff = `\
|
115 | diff --git a/test b/test
|
116 | deleted file mode 100644
|
117 | index db81be4..0000000
|
118 | --- b/test
|
119 | +++ /dev/null
|
120 | @@ -1,2 +0,0 @@
|
121 | -line1
|
122 | -line2\
|
123 | `;
|
124 | const files = parse(diff);
|
125 | expect(files.length).toBe(1);
|
126 | const file = files[0];
|
127 | expect(file.deleted).toBeTruthy();
|
128 | expect(file.from).toBe("test");
|
129 | expect(file.to).toBe("/dev/null");
|
130 | expect(file.chunks[0].content).toBe("@@ -1,2 +0,0 @@");
|
131 | expect(file.chunks[0].changes.length).toBe(2);
|
132 | expect(file.chunks[0].changes[0].content).toBe("-line1");
|
133 | expect(file.chunks[0].changes[1].content).toBe("-line2");
|
134 | });
|
135 |
|
136 | it("should parse diff with single line files", function () {
|
137 | const diff = `\
|
138 | diff --git a/file1 b/file1
|
139 | deleted file mode 100644
|
140 | index db81be4..0000000
|
141 | --- b/file1
|
142 | +++ /dev/null
|
143 | @@ -1 +0,0 @@
|
144 | -line1
|
145 | diff --git a/file2 b/file2
|
146 | new file mode 100644
|
147 | index 0000000..db81be4
|
148 | --- /dev/null
|
149 | +++ b/file2
|
150 | @@ -0,0 +1 @@
|
151 | +line1\
|
152 | `;
|
153 | const files = parse(diff);
|
154 | expect(files.length).toBe(2);
|
155 | let file = files[0];
|
156 | expect(file.deleted).toBeTruthy();
|
157 | expect(file.from).toBe("file1");
|
158 | expect(file.to).toBe("/dev/null");
|
159 | expect(file.chunks[0].content).toBe("@@ -1 +0,0 @@");
|
160 | expect(file.chunks[0].changes.length).toBe(1);
|
161 | expect(file.chunks[0].changes[0].content).toBe("-line1");
|
162 | expect(file.chunks[0].changes[0].type).toBe("del");
|
163 | file = files[1];
|
164 | expect(file.new).toBeTruthy();
|
165 | expect(file.from).toBe("/dev/null");
|
166 | expect(file.to).toBe("file2");
|
167 | expect(file.chunks[0].content).toBe("@@ -0,0 +1 @@");
|
168 | expect(file.chunks[0].oldStart).toBe(0);
|
169 | expect(file.chunks[0].oldLines).toBe(0);
|
170 | expect(file.chunks[0].newStart).toBe(1);
|
171 | expect(file.chunks[0].newLines).toBe(1);
|
172 | expect(file.chunks[0].changes.length).toBe(1);
|
173 | expect(file.chunks[0].changes[0].content).toBe("+line1");
|
174 | expect(file.chunks[0].changes[0].type).toBe("add");
|
175 | });
|
176 |
|
177 | it("should parse multiple files in diff", function () {
|
178 | const diff = `\
|
179 | diff --git a/file1 b/file1
|
180 | index 123..456 789
|
181 | --- a/file1
|
182 | +++ b/file1
|
183 | @@ -1,1 +1,1 @@
|
184 | - line1
|
185 | + line2
|
186 | diff --git a/file2 b/file2
|
187 | index 123..456 789
|
188 | --- a/file2
|
189 | +++ b/file2
|
190 | @@ -1,1 +1,1 @@
|
191 | - line1
|
192 | + line2\
|
193 | `;
|
194 | const files = parse(diff);
|
195 | expect(files.length).toBe(2);
|
196 | let file = files[0];
|
197 | expect(file.from).toBe("file1");
|
198 | expect(file.to).toBe("file1");
|
199 | expect(file.chunks[0].content).toBe("@@ -1,1 +1,1 @@");
|
200 | expect(file.chunks[0].changes.length).toBe(2);
|
201 | expect(file.chunks[0].changes[0].content).toBe("- line1");
|
202 | expect(file.chunks[0].changes[1].content).toBe("+ line2");
|
203 | file = files[1];
|
204 | expect(file.from).toBe("file2");
|
205 | expect(file.to).toBe("file2");
|
206 | expect(file.chunks[0].content).toBe("@@ -1,1 +1,1 @@");
|
207 | expect(file.chunks[0].changes.length).toBe(2);
|
208 | expect(file.chunks[0].changes[0].content).toBe("- line1");
|
209 | expect(file.chunks[0].changes[1].content).toBe("+ line2");
|
210 | });
|
211 |
|
212 | it("should parse diff with EOF flag", function () {
|
213 | const diff = `\
|
214 | diff --git a/file1 b/file1
|
215 | index 123..456 789
|
216 | --- a/file1
|
217 | +++ b/file1
|
218 | @@ -1,1 +1,1 @@
|
219 | - line1
|
220 | + line2
|
221 | \\ No newline at end of file\
|
222 | `;
|
223 | const files = parse(diff);
|
224 | expect(files.length).toBe(1);
|
225 | const file = files[0];
|
226 | expect(file.from).toBe("file1");
|
227 | expect(file.to).toBe("file1");
|
228 | const chunk = file.chunks[0];
|
229 | expect(chunk.content).toBe("@@ -1,1 +1,1 @@");
|
230 | expect(chunk.changes.length).toBe(3);
|
231 | expect(chunk.changes[0].content).toBe("- line1");
|
232 | expect(chunk.changes[1].content).toBe("+ line2");
|
233 | expect(chunk.changes[2].type).toBe("add");
|
234 | expect(chunk.changes[2].content).toBe("\\ No newline at end of file");
|
235 | });
|
236 |
|
237 | it("should parse gnu sample diff", function () {
|
238 | const diff = `\
|
239 | --- lao 2002-02-21 23:30:39.942229878 -0800
|
240 | +++ tzu 2002-02-21 23:30:50.442260588 -0800
|
241 | @@ -1,7 +1,6 @@
|
242 | -The Way that can be told of is not the eternal Way;
|
243 | -The name that can be named is not the eternal name.
|
244 | The Nameless is the origin of Heaven and Earth;
|
245 | -The Named is the mother of all things.
|
246 | +The named is the mother of all things.
|
247 | +
|
248 | Therefore let there always be non-being,
|
249 | so we may see their subtlety,
|
250 | And let there always be being,
|
251 | @@ -9,3 +8,6 @@
|
252 | The two are the same,
|
253 | But after they are produced,
|
254 | they have different names.
|
255 | +They both may be called deep and profound.
|
256 | +Deeper and more profound,
|
257 | +The door of all subtleties!\
|
258 | `;
|
259 | const files = parse(diff);
|
260 | expect(files.length).toBe(1);
|
261 | const file = files[0];
|
262 | expect(file.from).toBe("lao");
|
263 | expect(file.to).toBe("tzu");
|
264 | expect(file.chunks.length).toBe(2);
|
265 | const chunk0 = file.chunks[0];
|
266 | expect(chunk0.oldStart).toBe(1);
|
267 | expect(chunk0.oldLines).toBe(7);
|
268 | expect(chunk0.newStart).toBe(1);
|
269 | expect(chunk0.newLines).toBe(6);
|
270 | const chunk1 = file.chunks[1];
|
271 | expect(chunk1.oldStart).toBe(9);
|
272 | expect(chunk1.oldLines).toBe(3);
|
273 | expect(chunk1.newStart).toBe(8);
|
274 | expect(chunk1.newLines).toBe(6);
|
275 | });
|
276 |
|
277 | it("should parse hg diff output", function () {
|
278 | const diff = `\
|
279 | diff -r 514fc757521e lib/parsers.coffee
|
280 | --- a/lib/parsers.coffee Thu Jul 09 00:56:36 2015 +0200
|
281 | +++ b/lib/parsers.coffee Fri Jul 10 16:23:43 2015 +0200
|
282 | @@ -43,6 +43,9 @@
|
283 | files[file] = { added: added, deleted: deleted }
|
284 | files
|
285 |
|
286 | + diff: (out) ->
|
287 | + files = {}
|
288 | +
|
289 | module.exports = Parsers
|
290 |
|
291 | module.exports.version = (out) ->\
|
292 | `;
|
293 | const files = parse(diff);
|
294 | expect(files.length).toBe(1);
|
295 | const file = files[0];
|
296 | expect(file.chunks[0].content).toBe("@@ -43,6 +43,9 @@");
|
297 | expect(file.from).toBe("lib/parsers.coffee");
|
298 | expect(file.to).toBe("lib/parsers.coffee");
|
299 | });
|
300 |
|
301 | it("should parse svn diff output", function () {
|
302 | const diff = `\
|
303 | Index: new.txt
|
304 | ===================================================================
|
305 | --- new.txt (revision 0)
|
306 | +++ new.txt (working copy)
|
307 | @@ -0,0 +1 @@
|
308 | +test
|
309 | Index: text.txt
|
310 | ===================================================================
|
311 | --- text.txt (revision 6)
|
312 | +++ text.txt (working copy)
|
313 | @@ -1,7 +1,5 @@
|
314 | -This part of the
|
315 | -document has stayed the
|
316 | -same from version to
|
317 | -version. It shouldn't
|
318 | +This is an important
|
319 | +notice! It shouldn't
|
320 | be shown if it doesn't
|
321 | change. Otherwise, that
|
322 | would not be helping to\
|
323 | `;
|
324 | const files = parse(diff);
|
325 | expect(files.length).toBe(2);
|
326 | const file = files[0];
|
327 | expect(file.from).toBe("new.txt");
|
328 | expect(file.to).toBe("new.txt");
|
329 | expect(file.chunks[0].changes.length).toBe(1);
|
330 | });
|
331 |
|
332 | it("should parse file names for n new empty file", function () {
|
333 | const diff = `\
|
334 | diff --git a/newFile.txt b/newFile.txt
|
335 | new file mode 100644
|
336 | index 0000000..e6a2e28\
|
337 | `;
|
338 | const files = parse(diff);
|
339 | expect(files.length).toBe(1);
|
340 | const file = files[0];
|
341 | expect(file.from).toBe("/dev/null");
|
342 | expect(file.to).toBe("newFile.txt");
|
343 | });
|
344 |
|
345 | it("should parse file names for a deleted file", function () {
|
346 | const diff = `\
|
347 | diff --git a/deletedFile.txt b/deletedFile.txt
|
348 | deleted file mode 100644
|
349 | index e6a2e28..0000000\
|
350 | `;
|
351 | const files = parse(diff);
|
352 | expect(files.length).toBe(1);
|
353 | const file = files[0];
|
354 | expect(file.from).toBe("deletedFile.txt");
|
355 | expect(file.to).toBe("/dev/null");
|
356 | });
|
357 |
|
358 | it("should parse rename diff with space in path with no changes", function () {
|
359 | const diff = `\
|
360 | diff --git a/My Folder/File b/My Folder/a/File
|
361 | similarity index 100%
|
362 | rename from a/My Folder/File
|
363 | rename to My Folder/a/File\
|
364 | `;
|
365 | const files = parse(diff);
|
366 | expect(files.length).toBe(1);
|
367 | const file = files[0];
|
368 | expect(file.from).toBe("My Folder/File");
|
369 | expect(file.to).toBe("My Folder/a/File");
|
370 | expect(file.chunks.length).toBe(0);
|
371 | });
|
372 |
|
373 | it("should parse rename diff with space in path with changes", function () {
|
374 | const diff = `\
|
375 | diff --git a/My Folder/File b/My Folder/a/File
|
376 | similarity index 100%
|
377 | rename from a/My Folder/File
|
378 | rename to My Folder/a/File
|
379 | @@ -1,2 +1,2 @@
|
380 | - line1
|
381 | + line2\
|
382 | `;
|
383 | const files = parse(diff);
|
384 | expect(files.length).toBe(1);
|
385 | const file = files[0];
|
386 | expect(file.from).toBe("My Folder/File");
|
387 | expect(file.to).toBe("My Folder/a/File");
|
388 | expect(file.chunks.length).toBe(1);
|
389 | const chunk = file.chunks[0];
|
390 | expect(chunk.content).toBe("@@ -1,2 +1,2 @@");
|
391 | expect(chunk.changes.length).toBe(2);
|
392 | expect(chunk.changes[0].content).toBe("- line1");
|
393 | expect(chunk.changes[1].content).toBe("+ line2");
|
394 | });
|
395 |
|
396 | it("should parse diff with single line quote escaped file names", function () {
|
397 | const diff = `
|
398 | diff --git "a/file \\"space\\"" "b/file \\"space\\""
|
399 | index 9daeafb..88bd214 100644
|
400 | --- "a/file \\"space\\""
|
401 | +++ "b/file \\"space\\""
|
402 | @@ -1 +1 @@
|
403 | -test
|
404 | +test\n1234
|
405 | `;
|
406 | const files = parse(diff);
|
407 | expect(files.length).toBe(1);
|
408 | const [file] = files;
|
409 | expect(file.from).toBe(`file \\"space\\"`);
|
410 | expect(file.to).toBe(`file \\"space\\"`);
|
411 | });
|
412 |
|
413 | it("should parse files with additional '-' and '+'", function () {
|
414 | const diff = `\
|
415 | diff --git a/file1 b/file1
|
416 | index 123..456 789
|
417 | --- a/file1
|
418 | +++ b/file1
|
419 | @@ -1,2 +1,1 @@
|
420 | - line11
|
421 | --- line12
|
422 | + line21
|
423 | diff --git a/file2 b/file2
|
424 | index 123..456 789
|
425 | --- a/file2
|
426 | +++ b/file2
|
427 | @@ -1,2 +1,1 @@
|
428 | - line11
|
429 | +++ line21
|
430 | + line22\
|
431 | `;
|
432 | const files = parse(diff);
|
433 | expect(files.length).toBe(2);
|
434 | const [file1, file2] = files;
|
435 |
|
436 | expect(file1.from).toBe(`file1`);
|
437 | expect(file1.to).toBe(`file1`);
|
438 | expect(file1.chunks[0].changes.length).toBe(3);
|
439 |
|
440 | expect(file2.from).toBe(`file2`);
|
441 | expect(file2.to).toBe(`file2`);
|
442 | expect(file2.chunks[0].changes.length).toBe(3);
|
443 | });
|
444 | });
|