1// Copyright 2014 The Gogs Authors. All rights reserved.
2// Copyright 2019 The Gitea Authors. All rights reserved.
3// SPDX-License-Identifier: MIT
4
5package gitdiff
6
7import (
8 "strconv"
9 "strings"
10 "testing"
11
12 "forgejo.org/models/db"
13 issues_model "forgejo.org/models/issues"
14 "forgejo.org/models/unittest"
15 user_model "forgejo.org/models/user"
16 "forgejo.org/modules/git"
17 "forgejo.org/modules/json"
18 "forgejo.org/modules/setting"
19
20 dmp "github.com/sergi/go-diff/diffmatchpatch"
21 "github.com/stretchr/testify/assert"
22 "github.com/stretchr/testify/require"
23)
24
25func TestDiffToHTML(t *testing.T) {
26 assert.Equal(t, "foo <span class=\"added-code\">bar</span> biz", diffToHTML(nil, []dmp.Diff{
27 {Type: dmp.DiffEqual, Text: "foo "},
28 {Type: dmp.DiffInsert, Text: "bar"},
29 {Type: dmp.DiffDelete, Text: " baz"},
30 {Type: dmp.DiffEqual, Text: " biz"},
31 }, DiffLineAdd))
32
33 assert.Equal(t, "foo <span class=\"removed-code\">bar</span> biz", diffToHTML(nil, []dmp.Diff{
34 {Type: dmp.DiffEqual, Text: "foo "},
35 {Type: dmp.DiffDelete, Text: "bar"},
36 {Type: dmp.DiffInsert, Text: " baz"},
37 {Type: dmp.DiffEqual, Text: " biz"},
38 }, DiffLineDel))
39}
40
41func TestParsePatch_skipTo(t *testing.T) {
42 type testcase struct {
43 name string
44 gitdiff string
45 wantErr bool
46 addition int
47 deletion int
48 oldFilename string
49 filename string
50 skipTo string
51 }
52 tests := []testcase{
53 {
54 name: "readme.md2readme.md",
55 gitdiff: `diff --git "a/A \\ B" "b/A \\ B"
56--- "a/A \\ B"
57+++ "b/A \\ B"
58@@ -1,3 +1,6 @@
59 # gitea-github-migrator
60+
61+ Build Status
62- Latest Release
63 Docker Pulls
64+ cut off
65+ cut off
66diff --git "\\a/README.md" "\\b/README.md"
67--- "\\a/README.md"
68+++ "\\b/README.md"
69@@ -1,3 +1,6 @@
70 # gitea-github-migrator
71+
72+ Build Status
73- Latest Release
74 Docker Pulls
75+ cut off
76+ cut off
77`,
78 addition: 4,
79 deletion: 1,
80 filename: "README.md",
81 oldFilename: "README.md",
82 skipTo: "README.md",
83 },
84 {
85 name: "A \\ B",
86 gitdiff: `diff --git "a/A \\ B" "b/A \\ B"
87--- "a/A \\ B"
88+++ "b/A \\ B"
89@@ -1,3 +1,6 @@
90 # gitea-github-migrator
91+
92+ Build Status
93- Latest Release
94 Docker Pulls
95+ cut off
96+ cut off`,
97 addition: 4,
98 deletion: 1,
99 filename: "A \\ B",
100 oldFilename: "A \\ B",
101 skipTo: "A \\ B",
102 },
103 {
104 name: "A \\ B",
105 gitdiff: `diff --git "\\a/README.md" "\\b/README.md"
106--- "\\a/README.md"
107+++ "\\b/README.md"
108@@ -1,3 +1,6 @@
109 # gitea-github-migrator
110+
111+ Build Status
112- Latest Release
113 Docker Pulls
114+ cut off
115+ cut off
116diff --git "a/A \\ B" "b/A \\ B"
117--- "a/A \\ B"
118+++ "b/A \\ B"
119@@ -1,3 +1,6 @@
120 # gitea-github-migrator
121+
122+ Build Status
123- Latest Release
124 Docker Pulls
125+ cut off
126+ cut off`,
127 addition: 4,
128 deletion: 1,
129 filename: "A \\ B",
130 oldFilename: "A \\ B",
131 skipTo: "A \\ B",
132 },
133 {
134 name: "readme.md2readme.md",
135 gitdiff: `diff --git "a/A \\ B" "b/A \\ B"
136--- "a/A \\ B"
137+++ "b/A \\ B"
138@@ -1,3 +1,6 @@
139 # gitea-github-migrator
140+
141+ Build Status
142- Latest Release
143 Docker Pulls
144+ cut off
145+ cut off
146diff --git "a/A \\ B" "b/A \\ B"
147--- "a/A \\ B"
148+++ "b/A \\ B"
149@@ -1,3 +1,6 @@
150 # gitea-github-migrator
151+
152+ Build Status
153- Latest Release
154 Docker Pulls
155+ cut off
156+ cut off
157diff --git "\\a/README.md" "\\b/README.md"
158--- "\\a/README.md"
159+++ "\\b/README.md"
160@@ -1,3 +1,6 @@
161 # gitea-github-migrator
162+
163+ Build Status
164- Latest Release
165 Docker Pulls
166+ cut off
167+ cut off
168`,
169 addition: 4,
170 deletion: 1,
171 filename: "README.md",
172 oldFilename: "README.md",
173 skipTo: "README.md",
174 },
175 }
176 for _, testcase := range tests {
177 t.Run(testcase.name, func(t *testing.T) {
178 got, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), testcase.skipTo)
179 if (err != nil) != testcase.wantErr {
180 t.Errorf("ParsePatch(%q) error = %v, wantErr %v", testcase.name, err, testcase.wantErr)
181 return
182 }
183
184 gotMarshaled, _ := json.MarshalIndent(got, "", " ")
185 if got.NumFiles != 1 {
186 t.Errorf("ParsePath(%q) did not receive 1 file:\n%s", testcase.name, string(gotMarshaled))
187 return
188 }
189 if got.TotalAddition != testcase.addition {
190 t.Errorf("ParsePath(%q) does not have correct totalAddition %d, wanted %d", testcase.name, got.TotalAddition, testcase.addition)
191 }
192 if got.TotalDeletion != testcase.deletion {
193 t.Errorf("ParsePath(%q) did not have correct totalDeletion %d, wanted %d", testcase.name, got.TotalDeletion, testcase.deletion)
194 }
195 file := got.Files[0]
196 if file.Addition != testcase.addition {
197 t.Errorf("ParsePath(%q) does not have correct file addition %d, wanted %d", testcase.name, file.Addition, testcase.addition)
198 }
199 if file.Deletion != testcase.deletion {
200 t.Errorf("ParsePath(%q) did not have correct file deletion %d, wanted %d", testcase.name, file.Deletion, testcase.deletion)
201 }
202 if file.OldName != testcase.oldFilename {
203 t.Errorf("ParsePath(%q) did not have correct OldName %q, wanted %q", testcase.name, file.OldName, testcase.oldFilename)
204 }
205 if file.Name != testcase.filename {
206 t.Errorf("ParsePath(%q) did not have correct Name %q, wanted %q", testcase.name, file.Name, testcase.filename)
207 }
208 })
209 }
210}
211
212func TestParsePatch_singlefile(t *testing.T) {
213 type testcase struct {
214 name string
215 gitdiff string
216 wantErr bool
217 addition int
218 deletion int
219 oldFilename string
220 filename string
221 }
222
223 tests := []testcase{
224 {
225 name: "readme.md2readme.md",
226 gitdiff: `diff --git "\\a/README.md" "\\b/README.md"
227--- "\\a/README.md"
228+++ "\\b/README.md"
229@@ -1,3 +1,6 @@
230 # gitea-github-migrator
231+
232+ Build Status
233- Latest Release
234 Docker Pulls
235+ cut off
236+ cut off
237`,
238 addition: 4,
239 deletion: 1,
240 filename: "README.md",
241 oldFilename: "README.md",
242 },
243 {
244 name: "A \\ B",
245 gitdiff: `diff --git "a/A \\ B" "b/A \\ B"
246--- "a/A \\ B"
247+++ "b/A \\ B"
248@@ -1,3 +1,6 @@
249 # gitea-github-migrator
250+
251+ Build Status
252- Latest Release
253 Docker Pulls
254+ cut off
255+ cut off`,
256 addition: 4,
257 deletion: 1,
258 filename: "A \\ B",
259 oldFilename: "A \\ B",
260 },
261 {
262 name: "really weird filename",
263 gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/file b/a a/file"
264index d2186f1..f5c8ed2 100644
265--- "\\a/a b/file b/a a/file" ` + `
266+++ "\\b/a b/file b/a a/file" ` + `
267@@ -1,3 +1,2 @@
268 Create a weird file.
269 ` + `
270-and what does diff do here?
271\ No newline at end of file`,
272 addition: 0,
273 deletion: 1,
274 filename: "a b/file b/a a/file",
275 oldFilename: "a b/file b/a a/file",
276 },
277 {
278 name: "delete file with blanks",
279 gitdiff: `diff --git "\\a/file with blanks" "\\b/file with blanks"
280deleted file mode 100644
281index 898651a..0000000
282--- "\\a/file with blanks" ` + `
283+++ /dev/null
284@@ -1,5 +0,0 @@
285-a blank file
286-
287-has a couple o line
288-
289-the 5th line is the last
290`,
291 addition: 0,
292 deletion: 5,
293 filename: "file with blanks",
294 oldFilename: "file with blanks",
295 },
296 {
297 name: "rename a—as",
298 gitdiff: `diff --git "a/\360\243\220\265b\342\200\240vs" "b/a\342\200\224as"
299similarity index 100%
300rename from "\360\243\220\265b\342\200\240vs"
301rename to "a\342\200\224as"
302`,
303 addition: 0,
304 deletion: 0,
305 oldFilename: "𣐵b†vs",
306 filename: "a—as",
307 },
308 {
309 name: "rename with spaces",
310 gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/a a/file b/b file"
311similarity index 100%
312rename from a b/file b/a a/file
313rename to a b/a a/file b/b file
314`,
315 oldFilename: "a b/file b/a a/file",
316 filename: "a b/a a/file b/b file",
317 },
318 {
319 name: "ambiguous deleted",
320 gitdiff: `diff --git a/b b/b b/b b/b
321deleted file mode 100644
322index 92e798b..0000000
323--- a/b b/b` + "\t" + `
324+++ /dev/null
325@@ -1 +0,0 @@
326-b b/b
327`,
328 oldFilename: "b b/b",
329 filename: "b b/b",
330 addition: 0,
331 deletion: 1,
332 },
333 {
334 name: "ambiguous addition",
335 gitdiff: `diff --git a/b b/b b/b b/b
336new file mode 100644
337index 0000000..92e798b
338--- /dev/null
339+++ b/b b/b` + "\t" + `
340@@ -0,0 +1 @@
341+b b/b
342`,
343 oldFilename: "b b/b",
344 filename: "b b/b",
345 addition: 1,
346 deletion: 0,
347 },
348 {
349 name: "rename",
350 gitdiff: `diff --git a/b b/b b/b b/b b/b b/b
351similarity index 100%
352rename from b b/b b/b b/b b/b
353rename to b
354`,
355 oldFilename: "b b/b b/b b/b b/b",
356 filename: "b",
357 },
358 {
359 name: "ambiguous 1",
360 gitdiff: `diff --git a/b b/b b/b b/b b/b b/b
361similarity index 100%
362rename from b b/b b/b b/b b/b
363rename to b
364`,
365 oldFilename: "b b/b b/b b/b b/b",
366 filename: "b",
367 },
368 {
369 name: "ambiguous 2",
370 gitdiff: `diff --git a/b b/b b/b b/b b/b b/b
371similarity index 100%
372rename from b b/b b/b b/b
373rename to b b/b
374`,
375 oldFilename: "b b/b b/b b/b",
376 filename: "b b/b",
377 },
378 {
379 name: "minuses-and-pluses",
380 gitdiff: `diff --git a/minuses-and-pluses b/minuses-and-pluses
381index 6961180..9ba1a00 100644
382--- a/minuses-and-pluses
383+++ b/minuses-and-pluses
384@@ -1,4 +1,4 @@
385--- 1st line
386-++ 2nd line
387--- 3rd line
388-++ 4th line
389+++ 1st line
390+-- 2nd line
391+++ 3rd line
392+-- 4th line
393`,
394 oldFilename: "minuses-and-pluses",
395 filename: "minuses-and-pluses",
396 addition: 4,
397 deletion: 4,
398 },
399 }
400
401 for _, testcase := range tests {
402 t.Run(testcase.name, func(t *testing.T) {
403 got, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "")
404 if (err != nil) != testcase.wantErr {
405 t.Errorf("ParsePatch(%q) error = %v, wantErr %v", testcase.name, err, testcase.wantErr)
406 return
407 }
408
409 gotMarshaled, _ := json.MarshalIndent(got, "", " ")
410 if got.NumFiles != 1 {
411 t.Errorf("ParsePath(%q) did not receive 1 file:\n%s", testcase.name, string(gotMarshaled))
412 return
413 }
414 if got.TotalAddition != testcase.addition {
415 t.Errorf("ParsePath(%q) does not have correct totalAddition %d, wanted %d", testcase.name, got.TotalAddition, testcase.addition)
416 }
417 if got.TotalDeletion != testcase.deletion {
418 t.Errorf("ParsePath(%q) did not have correct totalDeletion %d, wanted %d", testcase.name, got.TotalDeletion, testcase.deletion)
419 }
420 file := got.Files[0]
421 if file.Addition != testcase.addition {
422 t.Errorf("ParsePath(%q) does not have correct file addition %d, wanted %d", testcase.name, file.Addition, testcase.addition)
423 }
424 if file.Deletion != testcase.deletion {
425 t.Errorf("ParsePath(%q) did not have correct file deletion %d, wanted %d", testcase.name, file.Deletion, testcase.deletion)
426 }
427 if file.OldName != testcase.oldFilename {
428 t.Errorf("ParsePath(%q) did not have correct OldName %q, wanted %q", testcase.name, file.OldName, testcase.oldFilename)
429 }
430 if file.Name != testcase.filename {
431 t.Errorf("ParsePath(%q) did not have correct Name %q, wanted %q", testcase.name, file.Name, testcase.filename)
432 }
433 })
434 }
435
436 // Test max lines
437 diffBuilder := &strings.Builder{}
438
439 diff := `diff --git a/newfile2 b/newfile2
440new file mode 100644
441index 0000000..6bb8f39
442--- /dev/null
443+++ b/newfile2
444@@ -0,0 +1,35 @@
445`
446 diffBuilder.WriteString(diff)
447
448 for i := 0; i < 35; i++ {
449 diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n")
450 }
451 diff = diffBuilder.String()
452 result, err := ParsePatch(db.DefaultContext, 20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "")
453 if err != nil {
454 t.Errorf("There should not be an error: %v", err)
455 }
456 if !result.Files[0].IsIncomplete {
457 t.Errorf("Files should be incomplete! %v", result.Files[0])
458 }
459 result, err = ParsePatch(db.DefaultContext, 40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "")
460 if err != nil {
461 t.Errorf("There should not be an error: %v", err)
462 }
463 if result.Files[0].IsIncomplete {
464 t.Errorf("Files should not be incomplete! %v", result.Files[0])
465 }
466 result, err = ParsePatch(db.DefaultContext, 40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "")
467 if err != nil {
468 t.Errorf("There should not be an error: %v", err)
469 }
470 if !result.Files[0].IsIncomplete {
471 t.Errorf("Files should be incomplete! %v", result.Files[0])
472 }
473
474 // Test max characters
475 diff = `diff --git a/newfile2 b/newfile2
476new file mode 100644
477index 0000000..6bb8f39
478--- /dev/null
479+++ b/newfile2
480@@ -0,0 +1,35 @@
481`
482 diffBuilder.Reset()
483 diffBuilder.WriteString(diff)
484
485 for i := 0; i < 33; i++ {
486 diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n")
487 }
488 diffBuilder.WriteString("+line33")
489 for i := 0; i < 512; i++ {
490 diffBuilder.WriteString("0123456789ABCDEF")
491 }
492 diffBuilder.WriteByte('\n')
493 diffBuilder.WriteString("+line" + strconv.Itoa(34) + "\n")
494 diffBuilder.WriteString("+line" + strconv.Itoa(35) + "\n")
495 diff = diffBuilder.String()
496
497 result, err = ParsePatch(db.DefaultContext, 20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "")
498 if err != nil {
499 t.Errorf("There should not be an error: %v", err)
500 }
501 if !result.Files[0].IsIncomplete {
502 t.Errorf("Files should be incomplete! %v", result.Files[0])
503 }
504 result, err = ParsePatch(db.DefaultContext, 40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "")
505 if err != nil {
506 t.Errorf("There should not be an error: %v", err)
507 }
508 if !result.Files[0].IsIncomplete {
509 t.Errorf("Files should be incomplete! %v", result.Files[0])
510 }
511
512 diff = `diff --git "a/README.md" "b/README.md"
513--- a/README.md
514+++ b/README.md
515@@ -1,3 +1,6 @@
516 # gitea-github-migrator
517+
518+ Build Status
519- Latest Release
520 Docker Pulls
521+ cut off
522+ cut off`
523 _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "")
524 if err != nil {
525 t.Errorf("ParsePatch failed: %s", err)
526 }
527
528 diff2 := `diff --git "a/A \\ B" "b/A \\ B"
529--- "a/A \\ B"
530+++ "b/A \\ B"
531@@ -1,3 +1,6 @@
532 # gitea-github-migrator
533+
534+ Build Status
535- Latest Release
536 Docker Pulls
537+ cut off
538+ cut off`
539 _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2), "")
540 if err != nil {
541 t.Errorf("ParsePatch failed: %s", err)
542 }
543
544 diff2a := `diff --git "a/A \\ B" b/A/B
545--- "a/A \\ B"
546+++ b/A/B
547@@ -1,3 +1,6 @@
548 # gitea-github-migrator
549+
550+ Build Status
551- Latest Release
552 Docker Pulls
553+ cut off
554+ cut off`
555 _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a), "")
556 if err != nil {
557 t.Errorf("ParsePatch failed: %s", err)
558 }
559
560 diff3 := `diff --git a/README.md b/README.md
561--- a/README.md
562+++ b/README.md
563@@ -1,3 +1,6 @@
564 # gitea-github-migrator
565+
566+ Build Status
567- Latest Release
568 Docker Pulls
569+ cut off
570+ cut off`
571 _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3), "")
572 if err != nil {
573 t.Errorf("ParsePatch failed: %s", err)
574 }
575}
576
577func setupDefaultDiff() *Diff {
578 return &Diff{
579 Files: []*DiffFile{
580 {
581 Name: "README.md",
582 Sections: []*DiffSection{
583 {
584 Lines: []*DiffLine{
585 {
586 LeftIdx: 4,
587 RightIdx: 4,
588 },
589 },
590 },
591 },
592 },
593 },
594 }
595}
596
597func TestDiff_LoadCommentsNoOutdated(t *testing.T) {
598 require.NoError(t, unittest.PrepareTestDatabase())
599
600 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
601 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
602 diff := setupDefaultDiff()
603 require.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, false))
604 assert.Len(t, diff.Files[0].Sections[0].Lines[0].Conversations, 2)
605}
606
607func TestDiff_LoadCommentsWithOutdated(t *testing.T) {
608 require.NoError(t, unittest.PrepareTestDatabase())
609
610 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
611 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
612 diff := setupDefaultDiff()
613 require.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, true))
614 assert.Len(t, diff.Files[0].Sections[0].Lines[0].Conversations, 2)
615 assert.Len(t, diff.Files[0].Sections[0].Lines[0].Conversations[0], 2)
616 assert.Len(t, diff.Files[0].Sections[0].Lines[0].Conversations[1], 1)
617}
618
619func TestDiffLine_CanComment(t *testing.T) {
620 assert.False(t, (&DiffLine{Type: DiffLineSection}).CanComment())
621 assert.False(t, (&DiffLine{Type: DiffLineAdd, Conversations: []issues_model.CodeConversation{{{Content: "bla"}}}}).CanComment())
622 assert.True(t, (&DiffLine{Type: DiffLineAdd}).CanComment())
623 assert.True(t, (&DiffLine{Type: DiffLineDel}).CanComment())
624 assert.True(t, (&DiffLine{Type: DiffLinePlain}).CanComment())
625}
626
627func TestDiffLine_GetCommentSide(t *testing.T) {
628 assert.Equal(t, "previous", (&DiffLine{Conversations: []issues_model.CodeConversation{{{Line: -3}}}}).GetCommentSide())
629 assert.Equal(t, "proposed", (&DiffLine{Conversations: []issues_model.CodeConversation{{{Line: 3}}}}).GetCommentSide())
630}
631
632func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) {
633 gitRepo, err := git.OpenRepository(git.DefaultContext, "./testdata/academic-module")
634 require.NoError(t, err)
635
636 defer gitRepo.Close()
637 for _, behavior := range []git.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} {
638 diffs, err := GetDiff(db.DefaultContext, gitRepo,
639 &DiffOptions{
640 AfterCommitID: "bd7063cc7c04689c4d082183d32a604ed27a24f9",
641 BeforeCommitID: "559c156f8e0178b71cb44355428f24001b08fc68",
642 MaxLines: setting.Git.MaxGitDiffLines,
643 MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
644 MaxFiles: setting.Git.MaxGitDiffFiles,
645 WhitespaceBehavior: behavior,
646 })
647 require.NoError(t, err, "Error when diff with %s", behavior)
648 for _, f := range diffs.Files {
649 assert.NotEmpty(t, f.Sections, "%s should have sections", f.Name)
650 }
651 }
652}
653
654func TestNoCrashes(t *testing.T) {
655 type testcase struct {
656 gitdiff string
657 }
658
659 tests := []testcase{
660 {
661 gitdiff: "diff --git \n--- a\t\n",
662 },
663 {
664 gitdiff: "diff --git \"0\n",
665 },
666 }
667 for _, testcase := range tests {
668 // It shouldn't crash, so don't care about the output.
669 ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "")
670 }
671}