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.

DiffEntryTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Copyright (C) 2011, 2013 Dariusz Luksza <dariusz@luksza.org>
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.diff;
  44. import static org.eclipse.jgit.diff.DiffEntry.DEV_NULL;
  45. import static org.eclipse.jgit.util.FileUtils.delete;
  46. import static org.hamcrest.CoreMatchers.is;
  47. import static org.hamcrest.CoreMatchers.notNullValue;
  48. import static org.junit.Assert.assertEquals;
  49. import static org.junit.Assert.assertFalse;
  50. import static org.junit.Assert.assertThat;
  51. import static org.junit.Assert.assertTrue;
  52. import java.io.File;
  53. import java.util.List;
  54. import org.eclipse.jgit.api.Git;
  55. import org.eclipse.jgit.diff.DiffEntry.ChangeType;
  56. import org.eclipse.jgit.dircache.DirCache;
  57. import org.eclipse.jgit.dircache.DirCacheEditor;
  58. import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
  59. import org.eclipse.jgit.dircache.DirCacheEntry;
  60. import org.eclipse.jgit.junit.RepositoryTestCase;
  61. import org.eclipse.jgit.lib.FileMode;
  62. import org.eclipse.jgit.revwalk.RevCommit;
  63. import org.eclipse.jgit.treewalk.EmptyTreeIterator;
  64. import org.eclipse.jgit.treewalk.FileTreeIterator;
  65. import org.eclipse.jgit.treewalk.TreeWalk;
  66. import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
  67. import org.eclipse.jgit.treewalk.filter.TreeFilter;
  68. import org.eclipse.jgit.util.FileUtils;
  69. import org.junit.Test;
  70. public class DiffEntryTest extends RepositoryTestCase {
  71. @Test
  72. public void shouldListAddedFileInInitialCommit() throws Exception {
  73. // given
  74. writeTrashFile("a.txt", "content");
  75. try (Git git = new Git(db);
  76. TreeWalk walk = new TreeWalk(db)) {
  77. git.add().addFilepattern("a.txt").call();
  78. RevCommit c = git.commit().setMessage("initial commit").call();
  79. // when
  80. walk.addTree(new EmptyTreeIterator());
  81. walk.addTree(c.getTree());
  82. List<DiffEntry> result = DiffEntry.scan(walk);
  83. // then
  84. assertThat(result, notNullValue());
  85. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
  86. DiffEntry entry = result.get(0);
  87. assertThat(entry.getChangeType(), is(ChangeType.ADD));
  88. assertThat(entry.getNewPath(), is("a.txt"));
  89. assertThat(entry.getOldPath(), is(DEV_NULL));
  90. }
  91. }
  92. @Test
  93. public void shouldListAddedFileBetweenTwoCommits() throws Exception {
  94. // given
  95. try (Git git = new Git(db);
  96. TreeWalk walk = new TreeWalk(db)) {
  97. RevCommit c1 = git.commit().setMessage("initial commit").call();
  98. writeTrashFile("a.txt", "content");
  99. git.add().addFilepattern("a.txt").call();
  100. RevCommit c2 = git.commit().setMessage("second commit").call();
  101. // when
  102. walk.addTree(c1.getTree());
  103. walk.addTree(c2.getTree());
  104. List<DiffEntry> result = DiffEntry.scan(walk);
  105. // then
  106. assertThat(result, notNullValue());
  107. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
  108. DiffEntry entry = result.get(0);
  109. assertThat(entry.getChangeType(), is(ChangeType.ADD));
  110. assertThat(entry.getNewPath(), is("a.txt"));
  111. assertThat(entry.getOldPath(), is(DEV_NULL));
  112. }
  113. }
  114. @Test
  115. public void shouldListModificationBetweenTwoCommits() throws Exception {
  116. // given
  117. try (Git git = new Git(db);
  118. TreeWalk walk = new TreeWalk(db)) {
  119. File file = writeTrashFile("a.txt", "content");
  120. git.add().addFilepattern("a.txt").call();
  121. RevCommit c1 = git.commit().setMessage("initial commit").call();
  122. write(file, "new content");
  123. RevCommit c2 = git.commit().setAll(true).setMessage("second commit")
  124. .call();
  125. // when
  126. walk.addTree(c1.getTree());
  127. walk.addTree(c2.getTree());
  128. List<DiffEntry> result = DiffEntry.scan(walk);
  129. // then
  130. assertThat(result, notNullValue());
  131. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
  132. DiffEntry entry = result.get(0);
  133. assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
  134. assertThat(entry.getNewPath(), is("a.txt"));
  135. }
  136. }
  137. @Test
  138. public void shouldListDeletionBetweenTwoCommits() throws Exception {
  139. // given
  140. try (Git git = new Git(db);
  141. TreeWalk walk = new TreeWalk(db)) {
  142. File file = writeTrashFile("a.txt", "content");
  143. git.add().addFilepattern("a.txt").call();
  144. RevCommit c1 = git.commit().setMessage("initial commit").call();
  145. delete(file);
  146. RevCommit c2 = git.commit().setAll(true).setMessage("delete a.txt")
  147. .call();
  148. // when
  149. walk.addTree(c1.getTree());
  150. walk.addTree(c2.getTree());
  151. List<DiffEntry> result = DiffEntry.scan(walk);
  152. // then
  153. assertThat(result, notNullValue());
  154. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
  155. DiffEntry entry = result.get(0);
  156. assertThat(entry.getOldPath(), is("a.txt"));
  157. assertThat(entry.getNewPath(), is(DEV_NULL));
  158. assertThat(entry.getChangeType(), is(ChangeType.DELETE));
  159. }
  160. }
  161. @Test
  162. public void shouldListModificationInDirWithoutModifiedTrees()
  163. throws Exception {
  164. // given
  165. try (Git git = new Git(db);
  166. TreeWalk walk = new TreeWalk(db)) {
  167. File tree = new File(new File(db.getWorkTree(), "a"), "b");
  168. FileUtils.mkdirs(tree);
  169. File file = new File(tree, "c.txt");
  170. FileUtils.createNewFile(file);
  171. write(file, "content");
  172. git.add().addFilepattern("a").call();
  173. RevCommit c1 = git.commit().setMessage("initial commit").call();
  174. write(file, "new line");
  175. RevCommit c2 = git.commit().setAll(true).setMessage("second commit")
  176. .call();
  177. // when
  178. walk.addTree(c1.getTree());
  179. walk.addTree(c2.getTree());
  180. walk.setRecursive(true);
  181. List<DiffEntry> result = DiffEntry.scan(walk);
  182. // then
  183. assertThat(result, notNullValue());
  184. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
  185. DiffEntry entry = result.get(0);
  186. assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
  187. assertThat(entry.getNewPath(), is("a/b/c.txt"));
  188. }
  189. }
  190. @Test
  191. public void shouldListModificationInDirWithModifiedTrees() throws Exception {
  192. // given
  193. try (Git git = new Git(db);
  194. TreeWalk walk = new TreeWalk(db)) {
  195. File tree = new File(new File(db.getWorkTree(), "a"), "b");
  196. FileUtils.mkdirs(tree);
  197. File file = new File(tree, "c.txt");
  198. FileUtils.createNewFile(file);
  199. write(file, "content");
  200. git.add().addFilepattern("a").call();
  201. RevCommit c1 = git.commit().setMessage("initial commit").call();
  202. write(file, "new line");
  203. RevCommit c2 = git.commit().setAll(true).setMessage("second commit")
  204. .call();
  205. // when
  206. walk.addTree(c1.getTree());
  207. walk.addTree(c2.getTree());
  208. List<DiffEntry> result = DiffEntry.scan(walk, true);
  209. // then
  210. assertThat(result, notNullValue());
  211. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(3)));
  212. DiffEntry entry = result.get(0);
  213. assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
  214. assertThat(entry.getNewPath(), is("a"));
  215. entry = result.get(1);
  216. assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
  217. assertThat(entry.getNewPath(), is("a/b"));
  218. entry = result.get(2);
  219. assertThat(entry.getChangeType(), is(ChangeType.MODIFY));
  220. assertThat(entry.getNewPath(), is("a/b/c.txt"));
  221. }
  222. }
  223. @Test
  224. public void shouldListChangesInWorkingTree() throws Exception {
  225. // given
  226. writeTrashFile("a.txt", "content");
  227. try (Git git = new Git(db);
  228. TreeWalk walk = new TreeWalk(db)) {
  229. git.add().addFilepattern("a.txt").call();
  230. RevCommit c = git.commit().setMessage("initial commit").call();
  231. writeTrashFile("b.txt", "new line");
  232. // when
  233. walk.addTree(c.getTree());
  234. walk.addTree(new FileTreeIterator(db));
  235. List<DiffEntry> result = DiffEntry.scan(walk, true);
  236. // then
  237. assertThat(Integer.valueOf(result.size()), is(Integer.valueOf(1)));
  238. DiffEntry entry = result.get(0);
  239. assertThat(entry.getChangeType(), is(ChangeType.ADD));
  240. assertThat(entry.getNewPath(), is("b.txt"));
  241. }
  242. }
  243. @Test
  244. public void shouldMarkEntriesWhenGivenMarkTreeFilter() throws Exception {
  245. // given
  246. try (Git git = new Git(db);
  247. TreeWalk walk = new TreeWalk(db)) {
  248. RevCommit c1 = git.commit().setMessage("initial commit").call();
  249. FileUtils.mkdir(new File(db.getWorkTree(), "b"));
  250. writeTrashFile("a.txt", "a");
  251. writeTrashFile("b/1.txt", "b1");
  252. writeTrashFile("b/2.txt", "b2");
  253. writeTrashFile("c.txt", "c");
  254. git.add().addFilepattern("a.txt").addFilepattern("b")
  255. .addFilepattern("c.txt").call();
  256. RevCommit c2 = git.commit().setMessage("second commit").call();
  257. TreeFilter filterA = PathFilterGroup.createFromStrings("a.txt");
  258. TreeFilter filterB = PathFilterGroup.createFromStrings("b");
  259. TreeFilter filterB2 = PathFilterGroup.createFromStrings("b/2.txt");
  260. // when
  261. walk.addTree(c1.getTree());
  262. walk.addTree(c2.getTree());
  263. List<DiffEntry> result = DiffEntry.scan(walk, true, new TreeFilter[] {
  264. filterA, filterB, filterB2 });
  265. // then
  266. assertThat(result, notNullValue());
  267. assertEquals(5, result.size());
  268. DiffEntry entryA = result.get(0);
  269. DiffEntry entryB = result.get(1);
  270. DiffEntry entryB1 = result.get(2);
  271. DiffEntry entryB2 = result.get(3);
  272. DiffEntry entryC = result.get(4);
  273. assertThat(entryA.getNewPath(), is("a.txt"));
  274. assertTrue(entryA.isMarked(0));
  275. assertFalse(entryA.isMarked(1));
  276. assertFalse(entryA.isMarked(2));
  277. assertEquals(1, entryA.getTreeFilterMarks());
  278. assertThat(entryB.getNewPath(), is("b"));
  279. assertFalse(entryB.isMarked(0));
  280. assertTrue(entryB.isMarked(1));
  281. assertTrue(entryB.isMarked(2));
  282. assertEquals(6, entryB.getTreeFilterMarks());
  283. assertThat(entryB1.getNewPath(), is("b/1.txt"));
  284. assertFalse(entryB1.isMarked(0));
  285. assertTrue(entryB1.isMarked(1));
  286. assertFalse(entryB1.isMarked(2));
  287. assertEquals(2, entryB1.getTreeFilterMarks());
  288. assertThat(entryB2.getNewPath(), is("b/2.txt"));
  289. assertFalse(entryB2.isMarked(0));
  290. assertTrue(entryB2.isMarked(1));
  291. assertTrue(entryB2.isMarked(2));
  292. assertEquals(6, entryB2.getTreeFilterMarks());
  293. assertThat(entryC.getNewPath(), is("c.txt"));
  294. assertFalse(entryC.isMarked(0));
  295. assertFalse(entryC.isMarked(1));
  296. assertFalse(entryC.isMarked(2));
  297. assertEquals(0, entryC.getTreeFilterMarks());
  298. }
  299. }
  300. @Test(expected = IllegalArgumentException.class)
  301. public void shouldThrowIAEWhenTreeWalkHasLessThanTwoTrees()
  302. throws Exception {
  303. // given - we don't need anything here
  304. // when
  305. try (TreeWalk walk = new TreeWalk(db)) {
  306. walk.addTree(new EmptyTreeIterator());
  307. DiffEntry.scan(walk);
  308. }
  309. }
  310. @Test(expected = IllegalArgumentException.class)
  311. public void shouldThrowIAEWhenTreeWalkHasMoreThanTwoTrees()
  312. throws Exception {
  313. // given - we don't need anything here
  314. // when
  315. try (TreeWalk walk = new TreeWalk(db)) {
  316. walk.addTree(new EmptyTreeIterator());
  317. walk.addTree(new EmptyTreeIterator());
  318. walk.addTree(new EmptyTreeIterator());
  319. DiffEntry.scan(walk);
  320. }
  321. }
  322. @Test(expected = IllegalArgumentException.class)
  323. public void shouldThrowIAEWhenScanShouldIncludeTreesAndWalkIsRecursive()
  324. throws Exception {
  325. // given - we don't need anything here
  326. // when
  327. try (TreeWalk walk = new TreeWalk(db)) {
  328. walk.addTree(new EmptyTreeIterator());
  329. walk.addTree(new EmptyTreeIterator());
  330. walk.setRecursive(true);
  331. DiffEntry.scan(walk, true);
  332. }
  333. }
  334. @Test
  335. public void shouldReportFileModeChange() throws Exception {
  336. writeTrashFile("a.txt", "content");
  337. try (Git git = new Git(db);
  338. TreeWalk walk = new TreeWalk(db)) {
  339. git.add().addFilepattern("a.txt").call();
  340. RevCommit c1 = git.commit().setMessage("initial commit").call();
  341. DirCache cache = db.lockDirCache();
  342. DirCacheEditor editor = cache.editor();
  343. walk.addTree(c1.getTree());
  344. walk.setRecursive(true);
  345. assertTrue(walk.next());
  346. editor.add(new PathEdit("a.txt") {
  347. public void apply(DirCacheEntry ent) {
  348. ent.setFileMode(FileMode.EXECUTABLE_FILE);
  349. ent.setObjectId(walk.getObjectId(0));
  350. }
  351. });
  352. assertTrue(editor.commit());
  353. RevCommit c2 = git.commit().setMessage("second commit").call();
  354. walk.reset();
  355. walk.addTree(c1.getTree());
  356. walk.addTree(c2.getTree());
  357. List<DiffEntry> diffs = DiffEntry.scan(walk, false);
  358. assertEquals(1, diffs.size());
  359. DiffEntry diff = diffs.get(0);
  360. assertEquals(ChangeType.MODIFY,diff.getChangeType());
  361. assertEquals(diff.getOldId(), diff.getNewId());
  362. assertEquals("a.txt", diff.getOldPath());
  363. assertEquals(diff.getOldPath(), diff.getNewPath());
  364. assertEquals(FileMode.EXECUTABLE_FILE, diff.getNewMode());
  365. assertEquals(FileMode.REGULAR_FILE, diff.getOldMode());
  366. }
  367. }
  368. }