1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.diff;
12
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertNull;
16 import static org.junit.Assert.assertTrue;
17
18 import java.io.BufferedOutputStream;
19 import java.io.ByteArrayOutputStream;
20 import java.io.File;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.eclipse.jgit.api.Git;
25 import org.eclipse.jgit.api.Status;
26 import org.eclipse.jgit.diff.DiffEntry.ChangeType;
27 import org.eclipse.jgit.dircache.DirCacheIterator;
28 import org.eclipse.jgit.junit.RepositoryTestCase;
29 import org.eclipse.jgit.junit.TestRepository;
30 import org.eclipse.jgit.lib.AnyObjectId;
31 import org.eclipse.jgit.lib.ConfigConstants;
32 import org.eclipse.jgit.lib.FileMode;
33 import org.eclipse.jgit.lib.ObjectId;
34 import org.eclipse.jgit.lib.Repository;
35 import org.eclipse.jgit.patch.FileHeader;
36 import org.eclipse.jgit.patch.HunkHeader;
37 import org.eclipse.jgit.revwalk.RevCommit;
38 import org.eclipse.jgit.storage.file.FileBasedConfig;
39 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
40 import org.eclipse.jgit.treewalk.FileTreeIterator;
41 import org.eclipse.jgit.treewalk.filter.OrTreeFilter;
42 import org.eclipse.jgit.treewalk.filter.PathFilter;
43 import org.eclipse.jgit.treewalk.filter.PathSuffixFilter;
44 import org.eclipse.jgit.treewalk.filter.TreeFilter;
45 import org.eclipse.jgit.util.FileUtils;
46 import org.eclipse.jgit.util.RawParseUtils;
47 import org.eclipse.jgit.util.io.DisabledOutputStream;
48 import org.junit.After;
49 import org.junit.Before;
50 import org.junit.Test;
51
52 public class DiffFormatterTest extends RepositoryTestCase {
53 private static final String DIFF = "diff --git ";
54
55 private static final String REGULAR_FILE = "100644";
56
57 private static final String GITLINK = "160000";
58
59 private static final String PATH_A = "src/a";
60
61 private static final String PATH_B = "src/b";
62
63 private DiffFormatter df;
64
65 private TestRepository<Repository> testDb;
66
67 @Override
68 @Before
69 public void setUp() throws Exception {
70 super.setUp();
71 testDb = new TestRepository<>(db);
72 df = new DiffFormatter(DisabledOutputStream.INSTANCE);
73 df.setRepository(db);
74 df.setAbbreviationLength(8);
75 }
76
77 @Override
78 @After
79 public void tearDown() throws Exception {
80 if (df != null) {
81 df.close();
82 }
83 super.tearDown();
84 }
85
86 @Test
87 public void testDefaultRenameDetectorSettings() throws Exception {
88 RenameDetector rd = df.getRenameDetector();
89 assertNull(rd);
90 df.setDetectRenames(true);
91 rd = df.getRenameDetector();
92 assertNotNull(rd);
93 assertEquals(400, rd.getRenameLimit());
94 assertEquals(60, rd.getRenameScore());
95 }
96
97 @Test
98 public void testCreateFileHeader_Add() throws Exception {
99 ObjectId adId = blob("a\nd\n");
100 DiffEntry ent = DiffEntry.add("FOO", adId);
101 FileHeader fh = df.toFileHeader(ent);
102
103 String diffHeader = "diff --git a/FOO b/FOO\n"
104 + "new file mode " + REGULAR_FILE + "\n"
105 + "index "
106 + ObjectId.zeroId().abbreviate(8).name()
107 + ".."
108 + adId.abbreviate(8).name() + "\n"
109 + "--- /dev/null\n"
110 + "+++ b/FOO\n";
111 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
112
113 assertEquals(0, fh.getStartOffset());
114 assertEquals(fh.getBuffer().length, fh.getEndOffset());
115 assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
116
117 assertEquals(1, fh.getHunks().size());
118
119 HunkHeader hh = fh.getHunks().get(0);
120 assertEquals(1, hh.toEditList().size());
121
122 EditList el = hh.toEditList();
123 assertEquals(1, el.size());
124
125 Edit e = el.get(0);
126 assertEquals(0, e.getBeginA());
127 assertEquals(0, e.getEndA());
128 assertEquals(0, e.getBeginB());
129 assertEquals(2, e.getEndB());
130 assertEquals(Edit.Type.INSERT, e.getType());
131 }
132
133 @Test
134 public void testCreateFileHeader_Delete() throws Exception {
135 ObjectId adId = blob("a\nd\n");
136 DiffEntry ent = DiffEntry.delete("FOO", adId);
137 FileHeader fh = df.toFileHeader(ent);
138
139 String diffHeader = "diff --git a/FOO b/FOO\n"
140 + "deleted file mode " + REGULAR_FILE + "\n"
141 + "index "
142 + adId.abbreviate(8).name()
143 + ".."
144 + ObjectId.zeroId().abbreviate(8).name() + "\n"
145 + "--- a/FOO\n"
146 + "+++ /dev/null\n";
147 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
148
149 assertEquals(0, fh.getStartOffset());
150 assertEquals(fh.getBuffer().length, fh.getEndOffset());
151 assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
152
153 assertEquals(1, fh.getHunks().size());
154
155 HunkHeader hh = fh.getHunks().get(0);
156 assertEquals(1, hh.toEditList().size());
157
158 EditList el = hh.toEditList();
159 assertEquals(1, el.size());
160
161 Edit e = el.get(0);
162 assertEquals(0, e.getBeginA());
163 assertEquals(2, e.getEndA());
164 assertEquals(0, e.getBeginB());
165 assertEquals(0, e.getEndB());
166 assertEquals(Edit.Type.DELETE, e.getType());
167 }
168
169 @Test
170 public void testCreateFileHeader_Modify() throws Exception {
171 ObjectId adId = blob("a\nd\n");
172 ObjectId abcdId = blob("a\nb\nc\nd\n");
173
174 String diffHeader = makeDiffHeader(PATH_A, PATH_A, adId, abcdId);
175
176 DiffEntry ad = DiffEntry.delete(PATH_A, adId);
177 DiffEntry abcd = DiffEntry.add(PATH_A, abcdId);
178
179 DiffEntry mod = DiffEntry.pair(ChangeType.MODIFY, ad, abcd, 0);
180
181 FileHeader fh = df.toFileHeader(mod);
182
183 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
184 assertEquals(0, fh.getStartOffset());
185 assertEquals(fh.getBuffer().length, fh.getEndOffset());
186 assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
187
188 assertEquals(1, fh.getHunks().size());
189
190 HunkHeader hh = fh.getHunks().get(0);
191 assertEquals(1, hh.toEditList().size());
192
193 EditList el = hh.toEditList();
194 assertEquals(1, el.size());
195
196 Edit e = el.get(0);
197 assertEquals(1, e.getBeginA());
198 assertEquals(1, e.getEndA());
199 assertEquals(1, e.getBeginB());
200 assertEquals(3, e.getEndB());
201 assertEquals(Edit.Type.INSERT, e.getType());
202 }
203
204 @Test
205 public void testCreateFileHeader_Binary() throws Exception {
206 ObjectId adId = blob("a\nd\n");
207 ObjectId binId = blob("a\nb\nc\n\0\0\0\0d\n");
208
209 String diffHeader = makeDiffHeader(PATH_A, PATH_B, adId, binId)
210 + "Binary files differ\n";
211
212 DiffEntry ad = DiffEntry.delete(PATH_A, adId);
213 DiffEntry abcd = DiffEntry.add(PATH_B, binId);
214
215 DiffEntry mod = DiffEntry.pair(ChangeType.MODIFY, ad, abcd, 0);
216
217 FileHeader fh = df.toFileHeader(mod);
218
219 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
220 assertEquals(FileHeader.PatchType.BINARY, fh.getPatchType());
221
222 assertEquals(1, fh.getHunks().size());
223
224 HunkHeader hh = fh.getHunks().get(0);
225 assertEquals(0, hh.toEditList().size());
226 }
227
228 @Test
229 public void testCreateFileHeader_GitLink() throws Exception {
230 ObjectId aId = blob("a\n");
231 ObjectId bId = blob("b\n");
232
233 String diffHeader = makeDiffHeaderModeChange(PATH_A, PATH_A, aId, bId,
234 GITLINK, REGULAR_FILE);
235
236 DiffEntry ad = DiffEntry.delete(PATH_A, aId);
237 ad.oldMode = FileMode.GITLINK;
238 DiffEntry abcd = DiffEntry.add(PATH_A, bId);
239
240 DiffEntry mod = DiffEntry.pair(ChangeType.MODIFY, ad, abcd, 0);
241
242 FileHeader fh = df.toFileHeader(mod);
243
244 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
245
246 assertEquals(1, fh.getHunks().size());
247
248 HunkHeader hh = fh.getHunks().get(0);
249 assertEquals(1, hh.toEditList().size());
250 }
251
252 @Test
253 public void testCreateFileHeader_AddGitLink() throws Exception {
254 ObjectId adId = blob("a\nd\n");
255 DiffEntry ent = DiffEntry.add("FOO", adId);
256 ent.newMode = FileMode.GITLINK;
257 FileHeader fh = df.toFileHeader(ent);
258
259 String diffHeader = "diff --git a/FOO b/FOO\n"
260 + "new file mode " + GITLINK + "\n"
261 + "index "
262 + ObjectId.zeroId().abbreviate(8).name()
263 + ".."
264 + adId.abbreviate(8).name() + "\n"
265 + "--- /dev/null\n"
266 + "+++ b/FOO\n";
267 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
268
269 assertEquals(1, fh.getHunks().size());
270 HunkHeader hh = fh.getHunks().get(0);
271
272 EditList el = hh.toEditList();
273 assertEquals(1, el.size());
274
275 Edit e = el.get(0);
276 assertEquals(0, e.getBeginA());
277 assertEquals(0, e.getEndA());
278 assertEquals(0, e.getBeginB());
279 assertEquals(1, e.getEndB());
280 assertEquals(Edit.Type.INSERT, e.getType());
281 }
282
283 @Test
284 public void testCreateFileHeader_DeleteGitLink() throws Exception {
285 ObjectId adId = blob("a\nd\n");
286 DiffEntry ent = DiffEntry.delete("FOO", adId);
287 ent.oldMode = FileMode.GITLINK;
288 FileHeader fh = df.toFileHeader(ent);
289
290 String diffHeader = "diff --git a/FOO b/FOO\n"
291 + "deleted file mode " + GITLINK + "\n"
292 + "index "
293 + adId.abbreviate(8).name()
294 + ".."
295 + ObjectId.zeroId().abbreviate(8).name() + "\n"
296 + "--- a/FOO\n"
297 + "+++ /dev/null\n";
298 assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
299
300 assertEquals(1, fh.getHunks().size());
301 HunkHeader hh = fh.getHunks().get(0);
302
303 EditList el = hh.toEditList();
304 assertEquals(1, el.size());
305
306 Edit e = el.get(0);
307 assertEquals(0, e.getBeginA());
308 assertEquals(1, e.getEndA());
309 assertEquals(0, e.getBeginB());
310 assertEquals(0, e.getEndB());
311 assertEquals(Edit.Type.DELETE, e.getType());
312 }
313
314 @Test
315 public void testCreateFileHeaderWithoutIndexLine() throws Exception {
316 DiffEntry m = DiffEntry.modify(PATH_A);
317 m.oldMode = FileMode.REGULAR_FILE;
318 m.newMode = FileMode.EXECUTABLE_FILE;
319
320 FileHeader fh = df.toFileHeader(m);
321 String expected = DIFF + "a/src/a b/src/a\n" +
322 "old mode 100644\n" +
323 "new mode 100755\n";
324 assertEquals(expected, fh.getScriptText());
325 }
326
327 @Test
328 public void testCreateFileHeaderForRenameWithoutContentChange() throws Exception {
329 DiffEntry a = DiffEntry.delete(PATH_A, ObjectId.zeroId());
330 DiffEntry b = DiffEntry.add(PATH_B, ObjectId.zeroId());
331 DiffEntry m = DiffEntry.pair(ChangeType.RENAME, a, b, 100);
332 m.oldId = null;
333 m.newId = null;
334
335 FileHeader fh = df.toFileHeader(m);
336 String expected = DIFF + "a/src/a b/src/b\n" +
337 "similarity index 100%\n" +
338 "rename from src/a\n" +
339 "rename to src/b\n";
340 assertEquals(expected, fh.getScriptText());
341 }
342
343 @Test
344 public void testCreateFileHeaderForRenameModeChange()
345 throws Exception {
346 DiffEntry a = DiffEntry.delete(PATH_A, ObjectId.zeroId());
347 DiffEntry b = DiffEntry.add(PATH_B, ObjectId.zeroId());
348 b.oldMode = FileMode.REGULAR_FILE;
349 b.newMode = FileMode.EXECUTABLE_FILE;
350 DiffEntry m = DiffEntry.pair(ChangeType.RENAME, a, b, 100);
351 m.oldId = null;
352 m.newId = null;
353
354 FileHeader fh = df.toFileHeader(m);
355
356 String expected = DIFF + "a/src/a b/src/b\n" +
357 "old mode 100644\n" +
358 "new mode 100755\n" +
359 "similarity index 100%\n" +
360 "rename from src/a\n" +
361 "rename to src/b\n";
362
363 assertEquals(expected, fh.getScriptText());
364 }
365
366 @Test
367 public void testDiff() throws Exception {
368 write(new File(db.getDirectory().getParent(), "test.txt"), "test");
369 File folder = new File(db.getDirectory().getParent(), "folder");
370 FileUtils.mkdir(folder);
371 write(new File(folder, "folder.txt"), "folder");
372 try (Git git = new Git(db);
373 ByteArrayOutputStream os = new ByteArrayOutputStream();
374 DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
375 git.add().addFilepattern(".").call();
376 git.commit().setMessage("Initial commit").call();
377 write(new File(folder, "folder.txt"), "folder change");
378 dfmt.setRepository(db);
379 dfmt.setPathFilter(PathFilter.create("folder"));
380 DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache());
381 FileTreeIterator newTree = new FileTreeIterator(db);
382
383 dfmt.format(oldTree, newTree);
384 dfmt.flush();
385
386 String actual = os.toString("UTF-8");
387 String expected =
388 "diff --git a/folder/folder.txt b/folder/folder.txt\n"
389 + "index 0119635..95c4c65 100644\n"
390 + "--- a/folder/folder.txt\n" + "+++ b/folder/folder.txt\n"
391 + "@@ -1 +1 @@\n" + "-folder\n"
392 + "\\ No newline at end of file\n" + "+folder change\n"
393 + "\\ No newline at end of file\n";
394
395 assertEquals(expected, actual);
396 }
397 }
398
399 @Test
400 public void testDiffRootNullToTree() throws Exception {
401 write(new File(db.getDirectory().getParent(), "test.txt"), "test");
402 File folder = new File(db.getDirectory().getParent(), "folder");
403 FileUtils.mkdir(folder);
404 write(new File(folder, "folder.txt"), "folder");
405 try (Git git = new Git(db);
406 ByteArrayOutputStream os = new ByteArrayOutputStream();
407 DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
408 git.add().addFilepattern(".").call();
409 RevCommit commit = git.commit().setMessage("Initial commit").call();
410 write(new File(folder, "folder.txt"), "folder change");
411
412 dfmt.setRepository(db);
413 dfmt.setPathFilter(PathFilter.create("folder"));
414 dfmt.format(null, commit.getTree().getId());
415 dfmt.flush();
416
417 String actual = os.toString("UTF-8");
418 String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
419 + "new file mode 100644\n"
420 + "index 0000000..0119635\n"
421 + "--- /dev/null\n"
422 + "+++ b/folder/folder.txt\n"
423 + "@@ -0,0 +1 @@\n"
424 + "+folder\n"
425 + "\\ No newline at end of file\n";
426
427 assertEquals(expected, actual);
428 }
429 }
430
431 @Test
432 public void testDiffRootTreeToNull() throws Exception {
433 write(new File(db.getDirectory().getParent(), "test.txt"), "test");
434 File folder = new File(db.getDirectory().getParent(), "folder");
435 FileUtils.mkdir(folder);
436 write(new File(folder, "folder.txt"), "folder");
437 try (Git git = new Git(db);
438 ByteArrayOutputStream os = new ByteArrayOutputStream();
439 DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os));) {
440 git.add().addFilepattern(".").call();
441 RevCommit commit = git.commit().setMessage("Initial commit").call();
442 write(new File(folder, "folder.txt"), "folder change");
443
444 dfmt.setRepository(db);
445 dfmt.setPathFilter(PathFilter.create("folder"));
446 dfmt.format(commit.getTree().getId(), null);
447 dfmt.flush();
448
449 String actual = os.toString("UTF-8");
450 String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
451 + "deleted file mode 100644\n"
452 + "index 0119635..0000000\n"
453 + "--- a/folder/folder.txt\n"
454 + "+++ /dev/null\n"
455 + "@@ -1 +0,0 @@\n"
456 + "-folder\n"
457 + "\\ No newline at end of file\n";
458
459 assertEquals(expected, actual);
460 }
461 }
462
463 @Test
464 public void testDiffNullToNull() throws Exception {
465 try (ByteArrayOutputStream os = new ByteArrayOutputStream();
466 DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
467 dfmt.setRepository(db);
468 dfmt.format((AnyObjectId) null, null);
469 dfmt.flush();
470
471 String actual = os.toString("UTF-8");
472 String expected = "";
473
474 assertEquals(expected, actual);
475 }
476 }
477
478 @Test
479 public void testTrackedFileInIgnoredFolderUnchanged()
480 throws Exception {
481 commitFile("empty/empty/foo", "", "master");
482 commitFile(".gitignore", "empty/*", "master");
483 try (Git git = new Git(db)) {
484 Status status = git.status().call();
485 assertTrue(status.isClean());
486 }
487 try (ByteArrayOutputStream os = new ByteArrayOutputStream();
488 DiffFormatter dfmt = new DiffFormatter(os)) {
489 dfmt.setRepository(db);
490 dfmt.format(new DirCacheIterator(db.readDirCache()),
491 new FileTreeIterator(db));
492 dfmt.flush();
493
494 String actual = os.toString("UTF-8");
495
496 assertEquals("", actual);
497 }
498 }
499
500 @Test
501 public void testFilter() throws Exception {
502 RevCommit parent;
503 RevCommit head;
504 try (Git git = new Git(db)) {
505 writeTrashFile("foo.txt", "foo\n");
506 writeTrashFile("src/some.txt", "some\n");
507 writeTrashFile("src/image.png", "image\n");
508 writeTrashFile("src/test.pdf", "test\n");
509 writeTrashFile("src/xyz.txt", "xyz\n");
510 git.add().addFilepattern(".").call();
511 parent = git.commit().setMessage("initial").call();
512 writeTrashFile("foo.txt", "FOO\n");
513 writeTrashFile("src/some.txt", "SOME\n");
514 writeTrashFile("src/image.png", "IMAGE\n");
515 writeTrashFile("src/test.pdf", "TEST\n");
516 writeTrashFile("src/xyz.txt", "XYZ\n");
517 git.add().addFilepattern(".").call();
518 head = git.commit().setMessage("second").call();
519 }
520 try (ByteArrayOutputStream os = new ByteArrayOutputStream();
521 DiffFormatter dfmt = new DiffFormatter(os)) {
522 dfmt.setRepository(db);
523 List<TreeFilter> skip = new ArrayList<>();
524 skip.add(PathSuffixFilter.create(".png"));
525 skip.add(PathSuffixFilter.create(".pdf"));
526 dfmt.setPathFilter(OrTreeFilter.create(skip).negate());
527 dfmt.format(
528 new CanonicalTreeParser(null, db.newObjectReader(),
529 parent.getTree()),
530 new CanonicalTreeParser(null, db.newObjectReader(),
531 head.getTree()));
532 dfmt.flush();
533
534 String actual = os.toString("UTF-8");
535
536 String expected = "diff --git a/foo.txt b/foo.txt\n"
537 + "index 257cc56..b7d6715 100644\n"
538 + "--- a/foo.txt\n"
539 + "+++ b/foo.txt\n"
540 + "@@ -1 +1 @@\n"
541 + "-foo\n"
542 + "+FOO\n"
543 + "diff --git a/src/some.txt b/src/some.txt\n"
544 + "index 363ef61..76cea5f 100644\n"
545 + "--- a/src/some.txt\n"
546 + "+++ b/src/some.txt\n"
547 + "@@ -1 +1 @@\n"
548 + "-some\n"
549 + "+SOME\n"
550 + "diff --git a/src/xyz.txt b/src/xyz.txt\n"
551 + "index cd470e6..d4e3ab0 100644\n"
552 + "--- a/src/xyz.txt\n"
553 + "+++ b/src/xyz.txt\n"
554 + "@@ -1 +1 @@\n"
555 + "-xyz\n"
556 + "+XYZ\n";
557
558 assertEquals(expected, actual);
559 }
560 }
561
562 @Test
563 public void testTrackedFileInIgnoredFolderChanged()
564 throws Exception {
565 String expectedDiff = "diff --git a/empty/empty/foo b/empty/empty/foo\n"
566 + "index e69de29..5ea2ed4 100644\n"
567 + "--- a/empty/empty/foo\n"
568 + "+++ b/empty/empty/foo\n"
569 + "@@ -0,0 +1 @@\n"
570 + "+changed\n";
571
572 commitFile("empty/empty/foo", "", "master");
573 commitFile(".gitignore", "empty/*", "master");
574 try (Git git = new Git(db)) {
575 Status status = git.status().call();
576 assertTrue(status.isClean());
577 }
578 try (ByteArrayOutputStream os = new ByteArrayOutputStream();
579 DiffFormatter dfmt = new DiffFormatter(os)) {
580 writeTrashFile("empty/empty/foo", "changed\n");
581 dfmt.setRepository(db);
582 dfmt.format(new DirCacheIterator(db.readDirCache()),
583 new FileTreeIterator(db));
584 dfmt.flush();
585
586 String actual = os.toString("UTF-8");
587
588 assertEquals(expectedDiff, actual);
589 }
590 }
591
592 @Test
593 public void testDiffAutoCrlfSmallFile() throws Exception {
594 String content = "01234\r\n01234\r\n01234\r\n";
595 String expectedDiff = "diff --git a/test.txt b/test.txt\n"
596 + "index fe25983..a44a032 100644\n"
597 + "--- a/test.txt\n"
598 + "+++ b/test.txt\n"
599 + "@@ -1,3 +1,4 @@\n"
600 + " 01234\n"
601 + "+ABCD\n"
602 + " 01234\n"
603 + " 01234\n";
604 doAutoCrLfTest(content, expectedDiff);
605 }
606
607 @Test
608 public void testDiffAutoCrlfMediumFile() throws Exception {
609 String content = mediumCrLfString();
610 String expectedDiff = "diff --git a/test.txt b/test.txt\n"
611 + "index 6d9ffed..50d7b5a 100644\n"
612 + "--- a/test.txt\n"
613 + "+++ b/test.txt\n"
614 + "@@ -1,4 +1,5 @@\n"
615 + " 01234567\n"
616 + "+ABCD\n"
617 + " 01234567\n"
618 + " 01234567\n"
619 + " 01234567\n";
620 doAutoCrLfTest(content, expectedDiff);
621 }
622
623 @Test
624 public void testDiffAutoCrlfLargeFile() throws Exception {
625 String content = largeCrLfString();
626 String expectedDiff = "diff --git a/test.txt b/test.txt\n"
627 + "index d6399a1..de26ce5 100644\n"
628 + "--- a/test.txt\n"
629 + "+++ b/test.txt\n"
630 + "@@ -1,4 +1,5 @@\n"
631 + " 012345678901234567890123456789012345678901234567\n"
632 + "+ABCD\n"
633 + " 012345678901234567890123456789012345678901234567\n"
634 + " 012345678901234567890123456789012345678901234567\n"
635 + " 012345678901234567890123456789012345678901234567\n";
636 doAutoCrLfTest(content, expectedDiff);
637 }
638
639 private void doAutoCrLfTest(String content, String expectedDiff)
640 throws Exception {
641 FileBasedConfig config = db.getConfig();
642 config.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
643 ConfigConstants.CONFIG_KEY_AUTOCRLF, "true");
644 config.save();
645 commitFile("test.txt", content, "master");
646
647 int i = content.indexOf('\n');
648 content = content.substring(0, i + 1) + "ABCD\r\n"
649 + content.substring(i + 1);
650 writeTrashFile("test.txt", content);
651
652 try (ByteArrayOutputStream os = new ByteArrayOutputStream();
653 DiffFormatter dfmt = new DiffFormatter(
654 new BufferedOutputStream(os))) {
655 dfmt.setRepository(db);
656 dfmt.format(new DirCacheIterator(db.readDirCache()),
657 new FileTreeIterator(db));
658 dfmt.flush();
659
660 String actual = os.toString("UTF-8");
661
662 assertEquals(expectedDiff, actual);
663 }
664 }
665
666 private static String largeCrLfString() {
667 String line = "012345678901234567890123456789012345678901234567\r\n";
668 int bufferSize = RawText.getBufferSize();
669 StringBuilder builder = new StringBuilder(2 * bufferSize);
670 while (builder.length() < 2 * bufferSize) {
671 builder.append(line);
672 }
673 return builder.toString();
674 }
675
676 private static String mediumCrLfString() {
677
678
679 String line = "01234567\r\n";
680 int bufferSize = RawText.getBufferSize();
681 StringBuilder builder = new StringBuilder(bufferSize + line.length());
682 while (builder.length() <= bufferSize) {
683 builder.append(line);
684 }
685 return builder.toString();
686 }
687
688 private static String makeDiffHeader(String pathA, String pathB,
689 ObjectId aId,
690 ObjectId bId) {
691 String a = aId.abbreviate(8).name();
692 String b = bId.abbreviate(8).name();
693 return DIFF + "a/" + pathA + " " + "b/" + pathB + "\n" +
694 "index " + a + ".." + b + " " + REGULAR_FILE + "\n" +
695 "--- a/" + pathA + "\n" +
696 "+++ b/" + pathB + "\n";
697 }
698
699 private static String makeDiffHeaderModeChange(String pathA, String pathB,
700 ObjectId aId, ObjectId bId, String modeA, String modeB) {
701 String a = aId.abbreviate(8).name();
702 String b = bId.abbreviate(8).name();
703 return DIFF + "a/" + pathA + " " + "b/" + pathB + "\n" +
704 "old mode " + modeA + "\n" +
705 "new mode " + modeB + "\n" +
706 "index " + a + ".." + b + "\n" +
707 "--- a/" + pathA + "\n" +
708 "+++ b/" + pathB + "\n";
709 }
710
711 private ObjectId blob(String content) throws Exception {
712 return testDb.blob(content).copy();
713 }
714 }