You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DiffFormatterTest.java 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. * Copyright (C) 2010, 2020 Google Inc. and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.diff;
  11. import static org.junit.Assert.assertEquals;
  12. import static org.junit.Assert.assertNotNull;
  13. import static org.junit.Assert.assertNull;
  14. import static org.junit.Assert.assertTrue;
  15. import java.io.BufferedOutputStream;
  16. import java.io.ByteArrayOutputStream;
  17. import java.io.File;
  18. import org.eclipse.jgit.api.Git;
  19. import org.eclipse.jgit.api.Status;
  20. import org.eclipse.jgit.diff.DiffEntry.ChangeType;
  21. import org.eclipse.jgit.dircache.DirCacheIterator;
  22. import org.eclipse.jgit.junit.RepositoryTestCase;
  23. import org.eclipse.jgit.junit.TestRepository;
  24. import org.eclipse.jgit.lib.AnyObjectId;
  25. import org.eclipse.jgit.lib.ConfigConstants;
  26. import org.eclipse.jgit.lib.FileMode;
  27. import org.eclipse.jgit.lib.ObjectId;
  28. import org.eclipse.jgit.lib.Repository;
  29. import org.eclipse.jgit.patch.FileHeader;
  30. import org.eclipse.jgit.patch.HunkHeader;
  31. import org.eclipse.jgit.revwalk.RevCommit;
  32. import org.eclipse.jgit.storage.file.FileBasedConfig;
  33. import org.eclipse.jgit.treewalk.FileTreeIterator;
  34. import org.eclipse.jgit.treewalk.filter.PathFilter;
  35. import org.eclipse.jgit.util.FileUtils;
  36. import org.eclipse.jgit.util.RawParseUtils;
  37. import org.eclipse.jgit.util.io.DisabledOutputStream;
  38. import org.junit.After;
  39. import org.junit.Before;
  40. import org.junit.Test;
  41. public class DiffFormatterTest extends RepositoryTestCase {
  42. private static final String DIFF = "diff --git ";
  43. private static final String REGULAR_FILE = "100644";
  44. private static final String GITLINK = "160000";
  45. private static final String PATH_A = "src/a";
  46. private static final String PATH_B = "src/b";
  47. private DiffFormatter df;
  48. private TestRepository<Repository> testDb;
  49. @Override
  50. @Before
  51. public void setUp() throws Exception {
  52. super.setUp();
  53. testDb = new TestRepository<>(db);
  54. df = new DiffFormatter(DisabledOutputStream.INSTANCE);
  55. df.setRepository(db);
  56. df.setAbbreviationLength(8);
  57. }
  58. @Override
  59. @After
  60. public void tearDown() throws Exception {
  61. if (df != null) {
  62. df.close();
  63. }
  64. super.tearDown();
  65. }
  66. @Test
  67. public void testDefaultRenameDetectorSettings() throws Exception {
  68. RenameDetector rd = df.getRenameDetector();
  69. assertNull(rd);
  70. df.setDetectRenames(true);
  71. rd = df.getRenameDetector();
  72. assertNotNull(rd);
  73. assertEquals(400, rd.getRenameLimit());
  74. assertEquals(60, rd.getRenameScore());
  75. }
  76. @Test
  77. public void testCreateFileHeader_Add() throws Exception {
  78. ObjectId adId = blob("a\nd\n");
  79. DiffEntry ent = DiffEntry.add("FOO", adId);
  80. FileHeader fh = df.toFileHeader(ent);
  81. String diffHeader = "diff --git a/FOO b/FOO\n" //
  82. + "new file mode " + REGULAR_FILE + "\n"
  83. + "index "
  84. + ObjectId.zeroId().abbreviate(8).name()
  85. + ".."
  86. + adId.abbreviate(8).name() + "\n" //
  87. + "--- /dev/null\n"//
  88. + "+++ b/FOO\n";
  89. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  90. assertEquals(0, fh.getStartOffset());
  91. assertEquals(fh.getBuffer().length, fh.getEndOffset());
  92. assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
  93. assertEquals(1, fh.getHunks().size());
  94. HunkHeader hh = fh.getHunks().get(0);
  95. assertEquals(1, hh.toEditList().size());
  96. EditList el = hh.toEditList();
  97. assertEquals(1, el.size());
  98. Edit e = el.get(0);
  99. assertEquals(0, e.getBeginA());
  100. assertEquals(0, e.getEndA());
  101. assertEquals(0, e.getBeginB());
  102. assertEquals(2, e.getEndB());
  103. assertEquals(Edit.Type.INSERT, e.getType());
  104. }
  105. @Test
  106. public void testCreateFileHeader_Delete() throws Exception {
  107. ObjectId adId = blob("a\nd\n");
  108. DiffEntry ent = DiffEntry.delete("FOO", adId);
  109. FileHeader fh = df.toFileHeader(ent);
  110. String diffHeader = "diff --git a/FOO b/FOO\n" //
  111. + "deleted file mode " + REGULAR_FILE + "\n"
  112. + "index "
  113. + adId.abbreviate(8).name()
  114. + ".."
  115. + ObjectId.zeroId().abbreviate(8).name() + "\n" //
  116. + "--- a/FOO\n"//
  117. + "+++ /dev/null\n";
  118. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  119. assertEquals(0, fh.getStartOffset());
  120. assertEquals(fh.getBuffer().length, fh.getEndOffset());
  121. assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
  122. assertEquals(1, fh.getHunks().size());
  123. HunkHeader hh = fh.getHunks().get(0);
  124. assertEquals(1, hh.toEditList().size());
  125. EditList el = hh.toEditList();
  126. assertEquals(1, el.size());
  127. Edit e = el.get(0);
  128. assertEquals(0, e.getBeginA());
  129. assertEquals(2, e.getEndA());
  130. assertEquals(0, e.getBeginB());
  131. assertEquals(0, e.getEndB());
  132. assertEquals(Edit.Type.DELETE, e.getType());
  133. }
  134. @Test
  135. public void testCreateFileHeader_Modify() throws Exception {
  136. ObjectId adId = blob("a\nd\n");
  137. ObjectId abcdId = blob("a\nb\nc\nd\n");
  138. String diffHeader = makeDiffHeader(PATH_A, PATH_A, adId, abcdId);
  139. DiffEntry ad = DiffEntry.delete(PATH_A, adId);
  140. DiffEntry abcd = DiffEntry.add(PATH_A, abcdId);
  141. DiffEntry mod = DiffEntry.pair(ChangeType.MODIFY, ad, abcd, 0);
  142. FileHeader fh = df.toFileHeader(mod);
  143. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  144. assertEquals(0, fh.getStartOffset());
  145. assertEquals(fh.getBuffer().length, fh.getEndOffset());
  146. assertEquals(FileHeader.PatchType.UNIFIED, fh.getPatchType());
  147. assertEquals(1, fh.getHunks().size());
  148. HunkHeader hh = fh.getHunks().get(0);
  149. assertEquals(1, hh.toEditList().size());
  150. EditList el = hh.toEditList();
  151. assertEquals(1, el.size());
  152. Edit e = el.get(0);
  153. assertEquals(1, e.getBeginA());
  154. assertEquals(1, e.getEndA());
  155. assertEquals(1, e.getBeginB());
  156. assertEquals(3, e.getEndB());
  157. assertEquals(Edit.Type.INSERT, e.getType());
  158. }
  159. @Test
  160. public void testCreateFileHeader_Binary() throws Exception {
  161. ObjectId adId = blob("a\nd\n");
  162. ObjectId binId = blob("a\nb\nc\n\0\0\0\0d\n");
  163. String diffHeader = makeDiffHeader(PATH_A, PATH_B, adId, binId)
  164. + "Binary files differ\n";
  165. DiffEntry ad = DiffEntry.delete(PATH_A, adId);
  166. DiffEntry abcd = DiffEntry.add(PATH_B, binId);
  167. DiffEntry mod = DiffEntry.pair(ChangeType.MODIFY, ad, abcd, 0);
  168. FileHeader fh = df.toFileHeader(mod);
  169. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  170. assertEquals(FileHeader.PatchType.BINARY, fh.getPatchType());
  171. assertEquals(1, fh.getHunks().size());
  172. HunkHeader hh = fh.getHunks().get(0);
  173. assertEquals(0, hh.toEditList().size());
  174. }
  175. @Test
  176. public void testCreateFileHeader_GitLink() throws Exception {
  177. ObjectId aId = blob("a\n");
  178. ObjectId bId = blob("b\n");
  179. String diffHeader = makeDiffHeaderModeChange(PATH_A, PATH_A, aId, bId,
  180. GITLINK, REGULAR_FILE);
  181. DiffEntry ad = DiffEntry.delete(PATH_A, aId);
  182. ad.oldMode = FileMode.GITLINK;
  183. DiffEntry abcd = DiffEntry.add(PATH_A, bId);
  184. DiffEntry mod = DiffEntry.pair(ChangeType.MODIFY, ad, abcd, 0);
  185. FileHeader fh = df.toFileHeader(mod);
  186. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  187. assertEquals(1, fh.getHunks().size());
  188. HunkHeader hh = fh.getHunks().get(0);
  189. assertEquals(1, hh.toEditList().size());
  190. }
  191. @Test
  192. public void testCreateFileHeader_AddGitLink() throws Exception {
  193. ObjectId adId = blob("a\nd\n");
  194. DiffEntry ent = DiffEntry.add("FOO", adId);
  195. ent.newMode = FileMode.GITLINK;
  196. FileHeader fh = df.toFileHeader(ent);
  197. String diffHeader = "diff --git a/FOO b/FOO\n" //
  198. + "new file mode " + GITLINK + "\n"
  199. + "index "
  200. + ObjectId.zeroId().abbreviate(8).name()
  201. + ".."
  202. + adId.abbreviate(8).name() + "\n" //
  203. + "--- /dev/null\n"//
  204. + "+++ b/FOO\n";
  205. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  206. assertEquals(1, fh.getHunks().size());
  207. HunkHeader hh = fh.getHunks().get(0);
  208. EditList el = hh.toEditList();
  209. assertEquals(1, el.size());
  210. Edit e = el.get(0);
  211. assertEquals(0, e.getBeginA());
  212. assertEquals(0, e.getEndA());
  213. assertEquals(0, e.getBeginB());
  214. assertEquals(1, e.getEndB());
  215. assertEquals(Edit.Type.INSERT, e.getType());
  216. }
  217. @Test
  218. public void testCreateFileHeader_DeleteGitLink() throws Exception {
  219. ObjectId adId = blob("a\nd\n");
  220. DiffEntry ent = DiffEntry.delete("FOO", adId);
  221. ent.oldMode = FileMode.GITLINK;
  222. FileHeader fh = df.toFileHeader(ent);
  223. String diffHeader = "diff --git a/FOO b/FOO\n" //
  224. + "deleted file mode " + GITLINK + "\n"
  225. + "index "
  226. + adId.abbreviate(8).name()
  227. + ".."
  228. + ObjectId.zeroId().abbreviate(8).name() + "\n" //
  229. + "--- a/FOO\n"//
  230. + "+++ /dev/null\n";
  231. assertEquals(diffHeader, RawParseUtils.decode(fh.getBuffer()));
  232. assertEquals(1, fh.getHunks().size());
  233. HunkHeader hh = fh.getHunks().get(0);
  234. EditList el = hh.toEditList();
  235. assertEquals(1, el.size());
  236. Edit e = el.get(0);
  237. assertEquals(0, e.getBeginA());
  238. assertEquals(1, e.getEndA());
  239. assertEquals(0, e.getBeginB());
  240. assertEquals(0, e.getEndB());
  241. assertEquals(Edit.Type.DELETE, e.getType());
  242. }
  243. @Test
  244. public void testCreateFileHeaderWithoutIndexLine() throws Exception {
  245. DiffEntry m = DiffEntry.modify(PATH_A);
  246. m.oldMode = FileMode.REGULAR_FILE;
  247. m.newMode = FileMode.EXECUTABLE_FILE;
  248. FileHeader fh = df.toFileHeader(m);
  249. String expected = DIFF + "a/src/a b/src/a\n" + //
  250. "old mode 100644\n" + //
  251. "new mode 100755\n";
  252. assertEquals(expected, fh.getScriptText());
  253. }
  254. @Test
  255. public void testCreateFileHeaderForRenameWithoutContentChange() throws Exception {
  256. DiffEntry a = DiffEntry.delete(PATH_A, ObjectId.zeroId());
  257. DiffEntry b = DiffEntry.add(PATH_B, ObjectId.zeroId());
  258. DiffEntry m = DiffEntry.pair(ChangeType.RENAME, a, b, 100);
  259. m.oldId = null;
  260. m.newId = null;
  261. FileHeader fh = df.toFileHeader(m);
  262. String expected = DIFF + "a/src/a b/src/b\n" + //
  263. "similarity index 100%\n" + //
  264. "rename from src/a\n" + //
  265. "rename to src/b\n";
  266. assertEquals(expected, fh.getScriptText());
  267. }
  268. @Test
  269. public void testCreateFileHeaderForRenameModeChange()
  270. throws Exception {
  271. DiffEntry a = DiffEntry.delete(PATH_A, ObjectId.zeroId());
  272. DiffEntry b = DiffEntry.add(PATH_B, ObjectId.zeroId());
  273. b.oldMode = FileMode.REGULAR_FILE;
  274. b.newMode = FileMode.EXECUTABLE_FILE;
  275. DiffEntry m = DiffEntry.pair(ChangeType.RENAME, a, b, 100);
  276. m.oldId = null;
  277. m.newId = null;
  278. FileHeader fh = df.toFileHeader(m);
  279. //@formatter:off
  280. String expected = DIFF + "a/src/a b/src/b\n" +
  281. "old mode 100644\n" +
  282. "new mode 100755\n" +
  283. "similarity index 100%\n" +
  284. "rename from src/a\n" +
  285. "rename to src/b\n";
  286. //@formatter:on
  287. assertEquals(expected, fh.getScriptText());
  288. }
  289. @Test
  290. public void testDiff() throws Exception {
  291. write(new File(db.getDirectory().getParent(), "test.txt"), "test");
  292. File folder = new File(db.getDirectory().getParent(), "folder");
  293. FileUtils.mkdir(folder);
  294. write(new File(folder, "folder.txt"), "folder");
  295. try (Git git = new Git(db);
  296. ByteArrayOutputStream os = new ByteArrayOutputStream();
  297. DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
  298. git.add().addFilepattern(".").call();
  299. git.commit().setMessage("Initial commit").call();
  300. write(new File(folder, "folder.txt"), "folder change");
  301. dfmt.setRepository(db);
  302. dfmt.setPathFilter(PathFilter.create("folder"));
  303. DirCacheIterator oldTree = new DirCacheIterator(db.readDirCache());
  304. FileTreeIterator newTree = new FileTreeIterator(db);
  305. dfmt.format(oldTree, newTree);
  306. dfmt.flush();
  307. String actual = os.toString("UTF-8");
  308. String expected =
  309. "diff --git a/folder/folder.txt b/folder/folder.txt\n"
  310. + "index 0119635..95c4c65 100644\n"
  311. + "--- a/folder/folder.txt\n" + "+++ b/folder/folder.txt\n"
  312. + "@@ -1 +1 @@\n" + "-folder\n"
  313. + "\\ No newline at end of file\n" + "+folder change\n"
  314. + "\\ No newline at end of file\n";
  315. assertEquals(expected, actual);
  316. }
  317. }
  318. @Test
  319. public void testDiffRootNullToTree() throws Exception {
  320. write(new File(db.getDirectory().getParent(), "test.txt"), "test");
  321. File folder = new File(db.getDirectory().getParent(), "folder");
  322. FileUtils.mkdir(folder);
  323. write(new File(folder, "folder.txt"), "folder");
  324. try (Git git = new Git(db);
  325. ByteArrayOutputStream os = new ByteArrayOutputStream();
  326. DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
  327. git.add().addFilepattern(".").call();
  328. RevCommit commit = git.commit().setMessage("Initial commit").call();
  329. write(new File(folder, "folder.txt"), "folder change");
  330. dfmt.setRepository(db);
  331. dfmt.setPathFilter(PathFilter.create("folder"));
  332. dfmt.format(null, commit.getTree().getId());
  333. dfmt.flush();
  334. String actual = os.toString("UTF-8");
  335. String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
  336. + "new file mode 100644\n"
  337. + "index 0000000..0119635\n"
  338. + "--- /dev/null\n"
  339. + "+++ b/folder/folder.txt\n"
  340. + "@@ -0,0 +1 @@\n"
  341. + "+folder\n"
  342. + "\\ No newline at end of file\n";
  343. assertEquals(expected, actual);
  344. }
  345. }
  346. @Test
  347. public void testDiffRootTreeToNull() throws Exception {
  348. write(new File(db.getDirectory().getParent(), "test.txt"), "test");
  349. File folder = new File(db.getDirectory().getParent(), "folder");
  350. FileUtils.mkdir(folder);
  351. write(new File(folder, "folder.txt"), "folder");
  352. try (Git git = new Git(db);
  353. ByteArrayOutputStream os = new ByteArrayOutputStream();
  354. DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os));) {
  355. git.add().addFilepattern(".").call();
  356. RevCommit commit = git.commit().setMessage("Initial commit").call();
  357. write(new File(folder, "folder.txt"), "folder change");
  358. dfmt.setRepository(db);
  359. dfmt.setPathFilter(PathFilter.create("folder"));
  360. dfmt.format(commit.getTree().getId(), null);
  361. dfmt.flush();
  362. String actual = os.toString("UTF-8");
  363. String expected = "diff --git a/folder/folder.txt b/folder/folder.txt\n"
  364. + "deleted file mode 100644\n"
  365. + "index 0119635..0000000\n"
  366. + "--- a/folder/folder.txt\n"
  367. + "+++ /dev/null\n"
  368. + "@@ -1 +0,0 @@\n"
  369. + "-folder\n"
  370. + "\\ No newline at end of file\n";
  371. assertEquals(expected, actual);
  372. }
  373. }
  374. @Test
  375. public void testDiffNullToNull() throws Exception {
  376. try (ByteArrayOutputStream os = new ByteArrayOutputStream();
  377. DiffFormatter dfmt = new DiffFormatter(new BufferedOutputStream(os))) {
  378. dfmt.setRepository(db);
  379. dfmt.format((AnyObjectId) null, null);
  380. dfmt.flush();
  381. String actual = os.toString("UTF-8");
  382. String expected = "";
  383. assertEquals(expected, actual);
  384. }
  385. }
  386. @Test
  387. public void testTrackedFileInIgnoredFolderUnchanged()
  388. throws Exception {
  389. commitFile("empty/empty/foo", "", "master");
  390. commitFile(".gitignore", "empty/*", "master");
  391. try (Git git = new Git(db)) {
  392. Status status = git.status().call();
  393. assertTrue(status.isClean());
  394. }
  395. try (ByteArrayOutputStream os = new ByteArrayOutputStream();
  396. DiffFormatter dfmt = new DiffFormatter(os)) {
  397. dfmt.setRepository(db);
  398. dfmt.format(new DirCacheIterator(db.readDirCache()),
  399. new FileTreeIterator(db));
  400. dfmt.flush();
  401. String actual = os.toString("UTF-8");
  402. assertEquals("", actual);
  403. }
  404. }
  405. @Test
  406. public void testTrackedFileInIgnoredFolderChanged()
  407. throws Exception {
  408. String expectedDiff = "diff --git a/empty/empty/foo b/empty/empty/foo\n"
  409. + "index e69de29..5ea2ed4 100644\n" //
  410. + "--- a/empty/empty/foo\n" //
  411. + "+++ b/empty/empty/foo\n" //
  412. + "@@ -0,0 +1 @@\n" //
  413. + "+changed\n";
  414. commitFile("empty/empty/foo", "", "master");
  415. commitFile(".gitignore", "empty/*", "master");
  416. try (Git git = new Git(db)) {
  417. Status status = git.status().call();
  418. assertTrue(status.isClean());
  419. }
  420. try (ByteArrayOutputStream os = new ByteArrayOutputStream();
  421. DiffFormatter dfmt = new DiffFormatter(os)) {
  422. writeTrashFile("empty/empty/foo", "changed\n");
  423. dfmt.setRepository(db);
  424. dfmt.format(new DirCacheIterator(db.readDirCache()),
  425. new FileTreeIterator(db));
  426. dfmt.flush();
  427. String actual = os.toString("UTF-8");
  428. assertEquals(expectedDiff, actual);
  429. }
  430. }
  431. @Test
  432. public void testDiffAutoCrlfSmallFile() throws Exception {
  433. String content = "01234\r\n01234\r\n01234\r\n";
  434. String expectedDiff = "diff --git a/test.txt b/test.txt\n"
  435. + "index fe25983..a44a032 100644\n" //
  436. + "--- a/test.txt\n" //
  437. + "+++ b/test.txt\n" //
  438. + "@@ -1,3 +1,4 @@\n" //
  439. + " 01234\n" //
  440. + "+ABCD\n" //
  441. + " 01234\n" //
  442. + " 01234\n";
  443. doAutoCrLfTest(content, expectedDiff);
  444. }
  445. @Test
  446. public void testDiffAutoCrlfMediumFile() throws Exception {
  447. String content = mediumCrLfString();
  448. String expectedDiff = "diff --git a/test.txt b/test.txt\n"
  449. + "index 215c502..c10f08c 100644\n" //
  450. + "--- a/test.txt\n" //
  451. + "+++ b/test.txt\n" //
  452. + "@@ -1,4 +1,5 @@\n" //
  453. + " 01234567\n" //
  454. + "+ABCD\n" //
  455. + " 01234567\n" //
  456. + " 01234567\n" //
  457. + " 01234567\n";
  458. doAutoCrLfTest(content, expectedDiff);
  459. }
  460. @Test
  461. public void testDiffAutoCrlfLargeFile() throws Exception {
  462. String content = largeCrLfString();
  463. String expectedDiff = "diff --git a/test.txt b/test.txt\n"
  464. + "index 7014942..c0487a7 100644\n" //
  465. + "--- a/test.txt\n" //
  466. + "+++ b/test.txt\n" //
  467. + "@@ -1,4 +1,5 @@\n"
  468. + " 012345678901234567890123456789012345678901234567\n"
  469. + "+ABCD\n"
  470. + " 012345678901234567890123456789012345678901234567\n"
  471. + " 012345678901234567890123456789012345678901234567\n"
  472. + " 012345678901234567890123456789012345678901234567\n";
  473. doAutoCrLfTest(content, expectedDiff);
  474. }
  475. private void doAutoCrLfTest(String content, String expectedDiff)
  476. throws Exception {
  477. FileBasedConfig config = db.getConfig();
  478. config.setString(ConfigConstants.CONFIG_CORE_SECTION, null,
  479. ConfigConstants.CONFIG_KEY_AUTOCRLF, "true");
  480. config.save();
  481. commitFile("test.txt", content, "master");
  482. // Insert a line into content
  483. int i = content.indexOf('\n');
  484. content = content.substring(0, i + 1) + "ABCD\r\n"
  485. + content.substring(i + 1);
  486. writeTrashFile("test.txt", content);
  487. // Create the patch
  488. try (ByteArrayOutputStream os = new ByteArrayOutputStream();
  489. DiffFormatter dfmt = new DiffFormatter(
  490. new BufferedOutputStream(os))) {
  491. dfmt.setRepository(db);
  492. dfmt.format(new DirCacheIterator(db.readDirCache()),
  493. new FileTreeIterator(db));
  494. dfmt.flush();
  495. String actual = os.toString("UTF-8");
  496. assertEquals(expectedDiff, actual);
  497. }
  498. }
  499. private static String largeCrLfString() {
  500. String line = "012345678901234567890123456789012345678901234567\r\n";
  501. StringBuilder builder = new StringBuilder(
  502. 2 * RawText.FIRST_FEW_BYTES);
  503. while (builder.length() < 2 * RawText.FIRST_FEW_BYTES) {
  504. builder.append(line);
  505. }
  506. return builder.toString();
  507. }
  508. private static String mediumCrLfString() {
  509. // Create a CR-LF string longer than RawText.FIRST_FEW_BYTES whose
  510. // canonical representation is shorter than RawText.FIRST_FEW_BYTES.
  511. String line = "01234567\r\n"; // 10 characters
  512. StringBuilder builder = new StringBuilder(
  513. RawText.FIRST_FEW_BYTES + line.length());
  514. while (builder.length() <= RawText.FIRST_FEW_BYTES) {
  515. builder.append(line);
  516. }
  517. return builder.toString();
  518. }
  519. private static String makeDiffHeader(String pathA, String pathB,
  520. ObjectId aId,
  521. ObjectId bId) {
  522. String a = aId.abbreviate(8).name();
  523. String b = bId.abbreviate(8).name();
  524. return DIFF + "a/" + pathA + " " + "b/" + pathB + "\n" + //
  525. "index " + a + ".." + b + " " + REGULAR_FILE + "\n" + //
  526. "--- a/" + pathA + "\n" + //
  527. "+++ b/" + pathB + "\n";
  528. }
  529. private static String makeDiffHeaderModeChange(String pathA, String pathB,
  530. ObjectId aId, ObjectId bId, String modeA, String modeB) {
  531. String a = aId.abbreviate(8).name();
  532. String b = bId.abbreviate(8).name();
  533. return DIFF + "a/" + pathA + " " + "b/" + pathB + "\n" + //
  534. "old mode " + modeA + "\n" + //
  535. "new mode " + modeB + "\n" + //
  536. "index " + a + ".." + b + "\n" + //
  537. "--- a/" + pathA + "\n" + //
  538. "+++ b/" + pathB + "\n";
  539. }
  540. private ObjectId blob(String content) throws Exception {
  541. return testDb.blob(content).copy();
  542. }
  543. }