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.

FirstParentRevWalkTest.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. * Copyright (C) 2019, Google LLC. 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.revwalk;
  11. import static org.junit.Assert.assertEquals;
  12. import static org.junit.Assert.assertNull;
  13. import org.eclipse.jgit.lib.ObjectId;
  14. import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
  15. import org.eclipse.jgit.revwalk.filter.RevFilter;
  16. import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
  17. import org.junit.Test;
  18. public class FirstParentRevWalkTest extends RevWalkTestCase {
  19. @Test
  20. public void testStringOfPearls() throws Exception {
  21. RevCommit a = commit();
  22. RevCommit b = commit(a);
  23. RevCommit c = commit(b);
  24. rw.reset();
  25. rw.setFirstParent(true);
  26. markStart(c);
  27. assertCommit(c, rw.next());
  28. assertCommit(b, rw.next());
  29. assertCommit(a, rw.next());
  30. assertNull(rw.next());
  31. }
  32. @Test
  33. public void testSideBranch() throws Exception {
  34. RevCommit a = commit();
  35. RevCommit b1 = commit(a);
  36. RevCommit b2 = commit(a);
  37. RevCommit c1 = commit(b1);
  38. RevCommit c2 = commit(b2);
  39. RevCommit d = commit(c1, c2);
  40. rw.reset();
  41. rw.setFirstParent(true);
  42. markStart(d);
  43. assertCommit(d, rw.next());
  44. assertCommit(c1, rw.next());
  45. assertCommit(b1, rw.next());
  46. assertCommit(a, rw.next());
  47. assertNull(rw.next());
  48. }
  49. @Test
  50. public void testSecondParentAncestorOfFirstParent() throws Exception {
  51. RevCommit a = commit();
  52. RevCommit b = commit(a);
  53. RevCommit c = commit(b, a);
  54. rw.reset();
  55. rw.setFirstParent(true);
  56. markStart(c);
  57. assertCommit(c, rw.next());
  58. assertCommit(b, rw.next());
  59. assertCommit(a, rw.next());
  60. assertNull(rw.next());
  61. }
  62. @Test
  63. public void testFirstParentMultipleOccurrences() throws Exception {
  64. RevCommit a = commit();
  65. RevCommit b = commit(a);
  66. RevCommit c = commit(b);
  67. RevCommit d = commit(b);
  68. rw.reset();
  69. rw.setFirstParent(true);
  70. markStart(c);
  71. markStart(d);
  72. assertCommit(d, rw.next());
  73. assertCommit(c, rw.next());
  74. assertCommit(b, rw.next());
  75. assertCommit(a, rw.next());
  76. assertNull(rw.next());
  77. }
  78. @Test
  79. public void testReachableAlongFirstAndLaterParents() throws Exception {
  80. RevCommit a = commit();
  81. RevCommit b1 = commit(a);
  82. RevCommit b2 = commit(a);
  83. RevCommit b3 = commit(a);
  84. RevCommit c = commit(b1, b2);
  85. RevCommit d = commit(b2, b3);
  86. rw.reset();
  87. rw.setFirstParent(true);
  88. markStart(c);
  89. markStart(d);
  90. assertCommit(d, rw.next());
  91. assertCommit(c, rw.next());
  92. // b3 is only reachable from c's second parent.
  93. // b2 is reachable from c's second parent but d's first parent.
  94. assertCommit(b2, rw.next());
  95. assertCommit(b1, rw.next());
  96. assertCommit(a, rw.next());
  97. assertNull(rw.next());
  98. }
  99. @Test
  100. public void testStartCommitReachableOnlyFromLaterParents()
  101. throws Exception {
  102. RevCommit a = commit();
  103. RevCommit b1 = commit(a);
  104. RevCommit b2 = commit(a);
  105. RevCommit c = commit(b1, b2);
  106. rw.reset();
  107. rw.setFirstParent(true);
  108. markStart(c);
  109. markStart(b2);
  110. assertCommit(c, rw.next());
  111. // b2 is only reachable from second parent, but is itself a start
  112. // commit.
  113. assertCommit(b2, rw.next());
  114. assertCommit(b1, rw.next());
  115. assertCommit(a, rw.next());
  116. assertNull(rw.next());
  117. }
  118. @Test
  119. public void testRevFilter() throws Exception {
  120. RevCommit a = commit();
  121. RevCommit b1 = commitBuilder().parent(a).message("commit b1").create();
  122. RevCommit b2 = commitBuilder().parent(a).message("commit b2").create();
  123. RevCommit c = commit(b1, b2);
  124. rw.reset();
  125. rw.setFirstParent(true);
  126. rw.setRevFilter(MessageRevFilter.create("commit b"));
  127. rw.markStart(c);
  128. assertCommit(b1, rw.next());
  129. assertNull(rw.next());
  130. }
  131. @Test
  132. public void testTopoSort() throws Exception {
  133. RevCommit a = commit();
  134. RevCommit b1 = commit(a);
  135. RevCommit b2 = commit(a);
  136. RevCommit c = commit(b1, b2);
  137. rw.reset();
  138. rw.sort(RevSort.TOPO);
  139. rw.setFirstParent(true);
  140. markStart(c);
  141. assertCommit(c, rw.next());
  142. assertCommit(b1, rw.next());
  143. assertCommit(a, rw.next());
  144. assertNull(rw.next());
  145. }
  146. @Test
  147. public void testTopoNonIntermixSort() throws Exception {
  148. RevCommit a = commit();
  149. RevCommit b1 = commit(a);
  150. RevCommit b2 = commit(a);
  151. RevCommit c = commit(b1, b2);
  152. rw.reset();
  153. rw.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER);
  154. rw.setFirstParent(true);
  155. markStart(c);
  156. assertCommit(c, rw.next());
  157. assertCommit(b1, rw.next());
  158. assertCommit(a, rw.next());
  159. assertNull(rw.next());
  160. }
  161. @Test
  162. public void testCommitTimeSort() throws Exception {
  163. RevCommit a = commit();
  164. RevCommit b1 = commit(a);
  165. RevCommit b2 = commit(a);
  166. RevCommit c = commit(b1, b2);
  167. rw.reset();
  168. rw.sort(RevSort.COMMIT_TIME_DESC);
  169. rw.setFirstParent(true);
  170. markStart(c);
  171. assertCommit(c, rw.next());
  172. assertCommit(b1, rw.next());
  173. assertCommit(a, rw.next());
  174. assertNull(rw.next());
  175. }
  176. @Test
  177. public void testReverseSort() throws Exception {
  178. RevCommit a = commit();
  179. RevCommit b1 = commit(a);
  180. RevCommit b2 = commit(a);
  181. RevCommit c = commit(b1, b2);
  182. rw.reset();
  183. rw.sort(RevSort.REVERSE);
  184. rw.setFirstParent(true);
  185. markStart(c);
  186. assertCommit(a, rw.next());
  187. assertCommit(b1, rw.next());
  188. assertCommit(c, rw.next());
  189. assertNull(rw.next());
  190. }
  191. @Test
  192. public void testBoundarySort() throws Exception {
  193. RevCommit a = commit();
  194. RevCommit b = commit(a);
  195. RevCommit c1 = commit(b);
  196. RevCommit c2 = commit(b);
  197. RevCommit d = commit(c1, c2);
  198. rw.reset();
  199. rw.sort(RevSort.BOUNDARY);
  200. rw.setFirstParent(true);
  201. markStart(d);
  202. markUninteresting(a);
  203. assertCommit(d, rw.next());
  204. assertCommit(c1, rw.next());
  205. assertCommit(b, rw.next());
  206. assertCommit(a, rw.next());
  207. assertNull(rw.next());
  208. }
  209. @Test
  210. public void testFirstParentOfFirstParentMarkedUninteresting()
  211. throws Exception {
  212. RevCommit a = commit();
  213. RevCommit b1 = commit(a);
  214. RevCommit b2 = commit(a);
  215. RevCommit c1 = commit(b1);
  216. RevCommit c2 = commit(b2);
  217. RevCommit d = commit(c1, c2);
  218. rw.reset();
  219. rw.setFirstParent(true);
  220. markStart(d);
  221. markUninteresting(b1);
  222. assertCommit(d, rw.next());
  223. assertCommit(c1, rw.next());
  224. assertNull(rw.next());
  225. }
  226. @Test
  227. public void testUnparsedFirstParentOfFirstParentMarkedUninteresting()
  228. throws Exception {
  229. ObjectId a = unparsedCommit();
  230. ObjectId b1 = unparsedCommit(a);
  231. ObjectId b2 = unparsedCommit(a);
  232. ObjectId c1 = unparsedCommit(b1);
  233. ObjectId c2 = unparsedCommit(b2);
  234. ObjectId d = unparsedCommit(c1, c2);
  235. rw.reset();
  236. rw.setFirstParent(true);
  237. RevCommit parsedD = rw.parseCommit(d);
  238. markStart(parsedD);
  239. markUninteresting(rw.parseCommit(b1));
  240. assertCommit(parsedD, rw.next());
  241. assertCommit(rw.parseCommit(c1), rw.next());
  242. assertNull(rw.next());
  243. }
  244. @Test
  245. public void testFirstParentMarkedUninteresting() throws Exception {
  246. RevCommit a = commit();
  247. RevCommit b1 = commit(a);
  248. RevCommit b2 = commit(a);
  249. RevCommit c = commit(b1, b2);
  250. rw.reset();
  251. rw.setFirstParent(true);
  252. markStart(c);
  253. markUninteresting(b1);
  254. assertCommit(c, rw.next());
  255. assertNull(rw.next());
  256. }
  257. @Test
  258. public void testUnparsedFirstParentMarkedUninteresting() throws Exception {
  259. ObjectId a = unparsedCommit();
  260. ObjectId b1 = unparsedCommit(a);
  261. ObjectId b2 = unparsedCommit(a);
  262. ObjectId c = unparsedCommit(b1, b2);
  263. rw.reset();
  264. rw.setFirstParent(true);
  265. RevCommit parsedC = rw.parseCommit(c);
  266. markStart(parsedC);
  267. markUninteresting(rw.parseCommit(b1));
  268. assertCommit(parsedC, rw.next());
  269. assertNull(rw.next());
  270. }
  271. @Test
  272. public void testUninterestingCommitWithTwoParents() throws Exception {
  273. RevCommit a = commit();
  274. RevCommit b = commit(a);
  275. RevCommit c1 = commit(b);
  276. RevCommit c2 = commit(b);
  277. RevCommit d = commit(c1);
  278. RevCommit e = commit(c1, c2);
  279. RevCommit uA = commit(a, b);
  280. RevCommit uB1 = commit(uA, c2);
  281. RevCommit uB2 = commit(uA, d);
  282. RevCommit uninteresting = commit(uB1, uB2);
  283. rw.reset();
  284. rw.setFirstParent(true);
  285. markStart(e);
  286. markUninteresting(uninteresting);
  287. assertCommit(e, rw.next());
  288. assertNull(rw.next());
  289. }
  290. /**
  291. * This fails if we try to propagate flags before parsing commits.
  292. *
  293. * @throws Exception
  294. */
  295. @Test
  296. public void testUnparsedUninterestingCommitWithTwoParents()
  297. throws Exception {
  298. ObjectId a = unparsedCommit();
  299. ObjectId b = unparsedCommit(a);
  300. ObjectId c1 = unparsedCommit(b);
  301. ObjectId c2 = unparsedCommit(b);
  302. ObjectId d = unparsedCommit(c1);
  303. ObjectId e = unparsedCommit(c1, c2);
  304. ObjectId uA = unparsedCommit(a, b);
  305. ObjectId uB1 = unparsedCommit(uA, c2);
  306. ObjectId uB2 = unparsedCommit(uA, d);
  307. ObjectId uninteresting = unparsedCommit(uB1, uB2);
  308. rw.reset();
  309. rw.setFirstParent(true);
  310. RevCommit parsedE = rw.parseCommit(e);
  311. markStart(parsedE);
  312. markUninteresting(rw.parseCommit(uninteresting));
  313. assertCommit(parsedE, rw.next());
  314. assertNull(rw.next());
  315. }
  316. @Test
  317. public void testDepthWalk() throws Exception {
  318. RevCommit a = commit();
  319. RevCommit b1 = commit(a);
  320. RevCommit b2 = commit(a);
  321. RevCommit c = commit(b1, b2);
  322. try (DepthWalk.RevWalk dw = new DepthWalk.RevWalk(db, 1)) {
  323. dw.setFirstParent(true);
  324. dw.markRoot(dw.parseCommit(c));
  325. dw.markStart(dw.parseCommit(c));
  326. assertEquals(c, dw.next());
  327. assertEquals(b1, dw.next());
  328. assertNull(dw.next());
  329. }
  330. }
  331. @Test
  332. public void testDoNotRewriteParents() throws Exception {
  333. RevCommit a = commit();
  334. RevCommit b1 = commit(a);
  335. RevCommit b2 = commit(a);
  336. RevCommit c = commit(b1, b2);
  337. rw.reset();
  338. rw.setFirstParent(true);
  339. rw.setRewriteParents(false);
  340. markStart(c);
  341. assertCommit(c, rw.next());
  342. assertCommit(b1, rw.next());
  343. assertCommit(a, rw.next());
  344. assertNull(rw.next());
  345. }
  346. @Test(expected = IllegalStateException.class)
  347. public void testMarkStartBeforeSetFirstParent() throws Exception {
  348. RevCommit a = commit();
  349. rw.reset();
  350. markStart(a);
  351. rw.setFirstParent(true);
  352. }
  353. @Test(expected = IllegalStateException.class)
  354. public void testMergeBaseWithFirstParentNotAllowed() throws Exception {
  355. RevCommit a = commit();
  356. rw.reset();
  357. rw.setFirstParent(true);
  358. rw.setRevFilter(RevFilter.MERGE_BASE);
  359. markStart(a);
  360. assertNull(rw.next());
  361. }
  362. @Test
  363. public void testWithTopoSortAndTreeFilter() throws Exception {
  364. RevCommit a = commit();
  365. RevCommit b = commit(tree(file("0", blob("b"))), a);
  366. RevCommit c = commit(tree(file("0", blob("c"))), b, a);
  367. RevCommit d = commit(tree(file("0", blob("d"))), c);
  368. rw.reset();
  369. rw.setFirstParent(true);
  370. rw.sort(RevSort.TOPO, true);
  371. rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
  372. markStart(d);
  373. assertCommit(d, rw.next());
  374. assertCommit(c, rw.next());
  375. assertCommit(b, rw.next());
  376. assertNull(rw.next());
  377. }
  378. @Test
  379. public void testWithTopoSortAndTreeFilter2() throws Exception {
  380. RevCommit a = commit();
  381. RevCommit b = commit(tree(file("0", blob("b"))), a);
  382. RevCommit c = commit(tree(file("0", blob("c"))), a, b);
  383. RevCommit d = commit(tree(file("0", blob("d"))), c);
  384. rw.reset();
  385. rw.setFirstParent(true);
  386. rw.sort(RevSort.TOPO, true);
  387. rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
  388. markStart(d);
  389. assertCommit(d, rw.next());
  390. assertCommit(c, rw.next());
  391. assertNull(rw.next());
  392. }
  393. @Test
  394. public void testWithTopoNonIntermixSortAndTreeFilter() throws Exception {
  395. RevCommit a = commit();
  396. RevCommit b = commit(tree(file("0", blob("b"))), a);
  397. RevCommit c = commit(tree(file("0", blob("c"))), b, a);
  398. RevCommit d = commit(tree(file("0", blob("d"))), c);
  399. rw.reset();
  400. rw.setFirstParent(true);
  401. rw.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER, true);
  402. rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
  403. markStart(d);
  404. assertCommit(d, rw.next());
  405. assertCommit(c, rw.next());
  406. assertCommit(b, rw.next());
  407. assertNull(rw.next());
  408. }
  409. @Test
  410. public void testWithTopoNonIntermixSortAndTreeFilter2() throws Exception {
  411. RevCommit a = commit();
  412. RevCommit b = commit(tree(file("0", blob("b"))), a);
  413. RevCommit c = commit(tree(file("0", blob("c"))), a, b);
  414. RevCommit d = commit(tree(file("0", blob("d"))), c);
  415. rw.reset();
  416. rw.setFirstParent(true);
  417. rw.sort(RevSort.TOPO_KEEP_BRANCH_TOGETHER, true);
  418. rw.setTreeFilter(PathFilterGroup.createFromStrings("0"));
  419. markStart(d);
  420. assertCommit(d, rw.next());
  421. assertCommit(c, rw.next());
  422. assertNull(rw.next());
  423. }
  424. }