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.

MergeCommandTest.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com>
  3. * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
  4. * and other copyright owners as documented in the project's IP log.
  5. *
  6. * This program and the accompanying materials are made available
  7. * under the terms of the Eclipse Distribution License v1.0 which
  8. * accompanies this distribution, is reproduced below, and is
  9. * available at http://www.eclipse.org/org/documents/edl-v10.php
  10. *
  11. * All rights reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or
  14. * without modification, are permitted provided that the following
  15. * conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. *
  20. * - Redistributions in binary form must reproduce the above
  21. * copyright notice, this list of conditions and the following
  22. * disclaimer in the documentation and/or other materials provided
  23. * with the distribution.
  24. *
  25. * - Neither the name of the Eclipse Foundation, Inc. nor the
  26. * names of its contributors may be used to endorse or promote
  27. * products derived from this software without specific prior
  28. * written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  31. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  32. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  35. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  39. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  42. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  43. */
  44. package org.eclipse.jgit.api;
  45. import static org.junit.Assert.assertEquals;
  46. import static org.junit.Assert.assertFalse;
  47. import static org.junit.Assert.assertTrue;
  48. import static org.junit.Assert.fail;
  49. import java.io.File;
  50. import java.io.IOException;
  51. import java.util.Iterator;
  52. import org.eclipse.jgit.api.MergeResult.MergeStatus;
  53. import org.eclipse.jgit.api.errors.InvalidMergeHeadsException;
  54. import org.eclipse.jgit.dircache.DirCacheCheckout;
  55. import org.eclipse.jgit.lib.Constants;
  56. import org.eclipse.jgit.lib.ObjectId;
  57. import org.eclipse.jgit.lib.RefUpdate;
  58. import org.eclipse.jgit.lib.RepositoryState;
  59. import org.eclipse.jgit.lib.RepositoryTestCase;
  60. import org.eclipse.jgit.merge.MergeStrategy;
  61. import org.eclipse.jgit.revwalk.RevCommit;
  62. import org.eclipse.jgit.revwalk.RevWalk;
  63. import org.junit.Test;
  64. public class MergeCommandTest extends RepositoryTestCase {
  65. @Test
  66. public void testMergeInItself() throws Exception {
  67. Git git = new Git(db);
  68. git.commit().setMessage("initial commit").call();
  69. MergeResult result = git.merge().include(db.getRef(Constants.HEAD)).call();
  70. assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
  71. }
  72. @Test
  73. public void testAlreadyUpToDate() throws Exception {
  74. Git git = new Git(db);
  75. RevCommit first = git.commit().setMessage("initial commit").call();
  76. createBranch(first, "refs/heads/branch1");
  77. RevCommit second = git.commit().setMessage("second commit").call();
  78. MergeResult result = git.merge().include(db.getRef("refs/heads/branch1")).call();
  79. assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
  80. assertEquals(second, result.getNewHead());
  81. }
  82. @Test
  83. public void testFastForward() throws Exception {
  84. Git git = new Git(db);
  85. RevCommit first = git.commit().setMessage("initial commit").call();
  86. createBranch(first, "refs/heads/branch1");
  87. RevCommit second = git.commit().setMessage("second commit").call();
  88. checkoutBranch("refs/heads/branch1");
  89. MergeResult result = git.merge().include(db.getRef(Constants.MASTER)).call();
  90. assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
  91. assertEquals(second, result.getNewHead());
  92. }
  93. @Test
  94. public void testFastForwardWithFiles() throws Exception {
  95. Git git = new Git(db);
  96. writeTrashFile("file1", "file1");
  97. git.add().addFilepattern("file1").call();
  98. RevCommit first = git.commit().setMessage("initial commit").call();
  99. assertTrue(new File(db.getWorkTree(), "file1").exists());
  100. createBranch(first, "refs/heads/branch1");
  101. writeTrashFile("file2", "file2");
  102. git.add().addFilepattern("file2").call();
  103. RevCommit second = git.commit().setMessage("second commit").call();
  104. assertTrue(new File(db.getWorkTree(), "file2").exists());
  105. checkoutBranch("refs/heads/branch1");
  106. assertFalse(new File(db.getWorkTree(), "file2").exists());
  107. MergeResult result = git.merge().include(db.getRef(Constants.MASTER)).call();
  108. assertTrue(new File(db.getWorkTree(), "file1").exists());
  109. assertTrue(new File(db.getWorkTree(), "file2").exists());
  110. assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
  111. assertEquals(second, result.getNewHead());
  112. }
  113. @Test
  114. public void testMultipleHeads() throws Exception {
  115. Git git = new Git(db);
  116. writeTrashFile("file1", "file1");
  117. git.add().addFilepattern("file1").call();
  118. RevCommit first = git.commit().setMessage("initial commit").call();
  119. createBranch(first, "refs/heads/branch1");
  120. writeTrashFile("file2", "file2");
  121. git.add().addFilepattern("file2").call();
  122. RevCommit second = git.commit().setMessage("second commit").call();
  123. writeTrashFile("file3", "file3");
  124. git.add().addFilepattern("file3").call();
  125. git.commit().setMessage("third commit").call();
  126. checkoutBranch("refs/heads/branch1");
  127. assertFalse(new File(db.getWorkTree(), "file2").exists());
  128. assertFalse(new File(db.getWorkTree(), "file3").exists());
  129. MergeCommand merge = git.merge();
  130. merge.include(second.getId());
  131. merge.include(db.getRef(Constants.MASTER));
  132. try {
  133. merge.call();
  134. fail("Expected exception not thrown when merging multiple heads");
  135. } catch (InvalidMergeHeadsException e) {
  136. // expected this exception
  137. }
  138. }
  139. @Test
  140. public void testContentMerge() throws Exception {
  141. Git git = new Git(db);
  142. writeTrashFile("a", "1\na\n3\n");
  143. writeTrashFile("b", "1\nb\n3\n");
  144. writeTrashFile("c/c/c", "1\nc\n3\n");
  145. git.add().addFilepattern("a").addFilepattern("b")
  146. .addFilepattern("c/c/c").call();
  147. RevCommit initialCommit = git.commit().setMessage("initial").call();
  148. createBranch(initialCommit, "refs/heads/side");
  149. checkoutBranch("refs/heads/side");
  150. writeTrashFile("a", "1\na(side)\n3\n");
  151. writeTrashFile("b", "1\nb(side)\n3\n");
  152. git.add().addFilepattern("a").addFilepattern("b").call();
  153. RevCommit secondCommit = git.commit().setMessage("side").call();
  154. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  155. checkoutBranch("refs/heads/master");
  156. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  157. writeTrashFile("a", "1\na(main)\n3\n");
  158. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  159. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  160. git.commit().setMessage("main").call();
  161. MergeResult result = git.merge().include(secondCommit.getId())
  162. .setStrategy(MergeStrategy.RESOLVE).call();
  163. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  164. assertEquals(
  165. "1\n<<<<<<< HEAD\na(main)\n=======\na(side)\n>>>>>>> 86503e7e397465588cc267b65d778538bffccb83\n3\n",
  166. read(new File(db.getWorkTree(), "a")));
  167. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  168. assertEquals("1\nc(main)\n3\n",
  169. read(new File(db.getWorkTree(), "c/c/c")));
  170. assertEquals(1, result.getConflicts().size());
  171. assertEquals(3, result.getConflicts().get("a")[0].length);
  172. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  173. }
  174. @Test
  175. public void testMergeNonVersionedPaths() throws Exception {
  176. Git git = new Git(db);
  177. writeTrashFile("a", "1\na\n3\n");
  178. writeTrashFile("b", "1\nb\n3\n");
  179. writeTrashFile("c/c/c", "1\nc\n3\n");
  180. git.add().addFilepattern("a").addFilepattern("b")
  181. .addFilepattern("c/c/c").call();
  182. RevCommit initialCommit = git.commit().setMessage("initial").call();
  183. createBranch(initialCommit, "refs/heads/side");
  184. checkoutBranch("refs/heads/side");
  185. writeTrashFile("a", "1\na(side)\n3\n");
  186. writeTrashFile("b", "1\nb(side)\n3\n");
  187. git.add().addFilepattern("a").addFilepattern("b").call();
  188. RevCommit secondCommit = git.commit().setMessage("side").call();
  189. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  190. checkoutBranch("refs/heads/master");
  191. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  192. writeTrashFile("a", "1\na(main)\n3\n");
  193. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  194. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  195. git.commit().setMessage("main").call();
  196. writeTrashFile("d", "1\nd\n3\n");
  197. assertTrue(new File(db.getWorkTree(), "e").mkdir());
  198. MergeResult result = git.merge().include(secondCommit.getId())
  199. .setStrategy(MergeStrategy.RESOLVE).call();
  200. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  201. assertEquals(
  202. "1\n<<<<<<< HEAD\na(main)\n=======\na(side)\n>>>>>>> 86503e7e397465588cc267b65d778538bffccb83\n3\n",
  203. read(new File(db.getWorkTree(), "a")));
  204. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  205. assertEquals("1\nc(main)\n3\n",
  206. read(new File(db.getWorkTree(), "c/c/c")));
  207. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  208. File dir = new File(db.getWorkTree(), "e");
  209. assertTrue(dir.isDirectory());
  210. assertEquals(1, result.getConflicts().size());
  211. assertEquals(3, result.getConflicts().get("a")[0].length);
  212. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  213. }
  214. @Test
  215. public void testMultipleCreations() throws Exception {
  216. Git git = new Git(db);
  217. writeTrashFile("a", "1\na\n3\n");
  218. git.add().addFilepattern("a").call();
  219. RevCommit initialCommit = git.commit().setMessage("initial").call();
  220. createBranch(initialCommit, "refs/heads/side");
  221. checkoutBranch("refs/heads/side");
  222. writeTrashFile("b", "1\nb(side)\n3\n");
  223. git.add().addFilepattern("b").call();
  224. RevCommit secondCommit = git.commit().setMessage("side").call();
  225. checkoutBranch("refs/heads/master");
  226. writeTrashFile("b", "1\nb(main)\n3\n");
  227. git.add().addFilepattern("b").call();
  228. git.commit().setMessage("main").call();
  229. MergeResult result = git.merge().include(secondCommit.getId())
  230. .setStrategy(MergeStrategy.RESOLVE).call();
  231. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  232. }
  233. @Test
  234. public void testMultipleCreationsSameContent() throws Exception {
  235. Git git = new Git(db);
  236. writeTrashFile("a", "1\na\n3\n");
  237. git.add().addFilepattern("a").call();
  238. RevCommit initialCommit = git.commit().setMessage("initial").call();
  239. createBranch(initialCommit, "refs/heads/side");
  240. checkoutBranch("refs/heads/side");
  241. writeTrashFile("b", "1\nb(1)\n3\n");
  242. git.add().addFilepattern("b").call();
  243. RevCommit secondCommit = git.commit().setMessage("side").call();
  244. checkoutBranch("refs/heads/master");
  245. writeTrashFile("b", "1\nb(1)\n3\n");
  246. git.add().addFilepattern("b").call();
  247. git.commit().setMessage("main").call();
  248. MergeResult result = git.merge().include(secondCommit.getId())
  249. .setStrategy(MergeStrategy.RESOLVE).call();
  250. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  251. assertEquals("1\nb(1)\n3\n", read(new File(db.getWorkTree(), "b")));
  252. }
  253. @Test
  254. public void testSuccessfulContentMerge() throws Exception {
  255. Git git = new Git(db);
  256. writeTrashFile("a", "1\na\n3\n");
  257. writeTrashFile("b", "1\nb\n3\n");
  258. writeTrashFile("c/c/c", "1\nc\n3\n");
  259. git.add().addFilepattern("a").addFilepattern("b")
  260. .addFilepattern("c/c/c").call();
  261. RevCommit initialCommit = git.commit().setMessage("initial").call();
  262. createBranch(initialCommit, "refs/heads/side");
  263. checkoutBranch("refs/heads/side");
  264. writeTrashFile("a", "1(side)\na\n3\n");
  265. writeTrashFile("b", "1\nb(side)\n3\n");
  266. git.add().addFilepattern("a").addFilepattern("b").call();
  267. RevCommit secondCommit = git.commit().setMessage("side").call();
  268. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  269. checkoutBranch("refs/heads/master");
  270. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  271. writeTrashFile("a", "1\na\n3(main)\n");
  272. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  273. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  274. RevCommit thirdCommit = git.commit().setMessage("main").call();
  275. MergeResult result = git.merge().include(secondCommit.getId())
  276. .setStrategy(MergeStrategy.RESOLVE).call();
  277. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  278. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  279. "a")));
  280. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  281. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
  282. "c/c/c")));
  283. assertEquals(null, result.getConflicts());
  284. assertTrue(2 == result.getMergedCommits().length);
  285. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  286. assertEquals(secondCommit, result.getMergedCommits()[1]);
  287. Iterator<RevCommit> it = git.log().call().iterator();
  288. RevCommit newHead = it.next();
  289. assertEquals(newHead, result.getNewHead());
  290. assertEquals(2, newHead.getParentCount());
  291. assertEquals(thirdCommit, newHead.getParent(0));
  292. assertEquals(secondCommit, newHead.getParent(1));
  293. assertEquals(
  294. "Merge commit '3fa334456d236a92db020289fe0bf481d91777b4' into HEAD",
  295. newHead.getFullMessage());
  296. // @TODO fix me
  297. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  298. // test index state
  299. }
  300. @Test
  301. public void testSuccessfulContentMergeAndDirtyworkingTree()
  302. throws Exception {
  303. Git git = new Git(db);
  304. writeTrashFile("a", "1\na\n3\n");
  305. writeTrashFile("b", "1\nb\n3\n");
  306. writeTrashFile("d", "1\nd\n3\n");
  307. writeTrashFile("c/c/c", "1\nc\n3\n");
  308. git.add().addFilepattern("a").addFilepattern("b")
  309. .addFilepattern("c/c/c").addFilepattern("d").call();
  310. RevCommit initialCommit = git.commit().setMessage("initial").call();
  311. createBranch(initialCommit, "refs/heads/side");
  312. checkoutBranch("refs/heads/side");
  313. writeTrashFile("a", "1(side)\na\n3\n");
  314. writeTrashFile("b", "1\nb(side)\n3\n");
  315. git.add().addFilepattern("a").addFilepattern("b").call();
  316. RevCommit secondCommit = git.commit().setMessage("side").call();
  317. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  318. checkoutBranch("refs/heads/master");
  319. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  320. writeTrashFile("a", "1\na\n3(main)\n");
  321. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  322. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  323. RevCommit thirdCommit = git.commit().setMessage("main").call();
  324. writeTrashFile("d", "--- dirty ---");
  325. MergeResult result = git.merge().include(secondCommit.getId())
  326. .setStrategy(MergeStrategy.RESOLVE).call();
  327. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  328. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  329. "a")));
  330. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  331. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
  332. "c/c/c")));
  333. assertEquals(null, result.getConflicts());
  334. assertTrue(2 == result.getMergedCommits().length);
  335. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  336. assertEquals(secondCommit, result.getMergedCommits()[1]);
  337. Iterator<RevCommit> it = git.log().call().iterator();
  338. RevCommit newHead = it.next();
  339. assertEquals(newHead, result.getNewHead());
  340. assertEquals(2, newHead.getParentCount());
  341. assertEquals(thirdCommit, newHead.getParent(0));
  342. assertEquals(secondCommit, newHead.getParent(1));
  343. assertEquals(
  344. "Merge commit '064d54d98a4cdb0fed1802a21c656bfda67fe879' into HEAD",
  345. newHead.getFullMessage());
  346. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  347. }
  348. @Test
  349. public void testSingleDeletion() throws Exception {
  350. Git git = new Git(db);
  351. writeTrashFile("a", "1\na\n3\n");
  352. writeTrashFile("b", "1\nb\n3\n");
  353. writeTrashFile("d", "1\nd\n3\n");
  354. writeTrashFile("c/c/c", "1\nc\n3\n");
  355. git.add().addFilepattern("a").addFilepattern("b")
  356. .addFilepattern("c/c/c").addFilepattern("d").call();
  357. RevCommit initialCommit = git.commit().setMessage("initial").call();
  358. createBranch(initialCommit, "refs/heads/side");
  359. checkoutBranch("refs/heads/side");
  360. assertTrue(new File(db.getWorkTree(), "b").delete());
  361. git.add().addFilepattern("b").setUpdate(true).call();
  362. RevCommit secondCommit = git.commit().setMessage("side").call();
  363. assertFalse(new File(db.getWorkTree(), "b").exists());
  364. checkoutBranch("refs/heads/master");
  365. assertTrue(new File(db.getWorkTree(), "b").exists());
  366. writeTrashFile("a", "1\na\n3(main)\n");
  367. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  368. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  369. RevCommit thirdCommit = git.commit().setMessage("main").call();
  370. // We are merging a deletion into our branch
  371. MergeResult result = git.merge().include(secondCommit.getId())
  372. .setStrategy(MergeStrategy.RESOLVE).call();
  373. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  374. assertEquals("1\na\n3(main)\n", read(new File(db.getWorkTree(), "a")));
  375. assertFalse(new File(db.getWorkTree(), "b").exists());
  376. assertEquals("1\nc(main)\n3\n",
  377. read(new File(db.getWorkTree(), "c/c/c")));
  378. // Do the opposite, be on a branch where we have deleted a file and
  379. // merge in a old commit where this file was not deleted
  380. checkoutBranch("refs/heads/side");
  381. assertFalse(new File(db.getWorkTree(), "b").exists());
  382. result = git.merge().include(thirdCommit.getId())
  383. .setStrategy(MergeStrategy.RESOLVE).call();
  384. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  385. assertEquals("1\na\n3(main)\n", read(new File(db.getWorkTree(), "a")));
  386. assertFalse(new File(db.getWorkTree(), "b").exists());
  387. assertEquals("1\nc(main)\n3\n",
  388. read(new File(db.getWorkTree(), "c/c/c")));
  389. }
  390. @Test
  391. public void testMultipleDeletions() throws Exception {
  392. Git git = new Git(db);
  393. writeTrashFile("a", "1\na\n3\n");
  394. git.add().addFilepattern("a").call();
  395. RevCommit initialCommit = git.commit().setMessage("initial").call();
  396. createBranch(initialCommit, "refs/heads/side");
  397. checkoutBranch("refs/heads/side");
  398. assertTrue(new File(db.getWorkTree(), "a").delete());
  399. git.add().addFilepattern("a").setUpdate(true).call();
  400. RevCommit secondCommit = git.commit().setMessage("side").call();
  401. assertFalse(new File(db.getWorkTree(), "a").exists());
  402. checkoutBranch("refs/heads/master");
  403. assertTrue(new File(db.getWorkTree(), "a").exists());
  404. assertTrue(new File(db.getWorkTree(), "a").delete());
  405. git.add().addFilepattern("a").setUpdate(true).call();
  406. git.commit().setMessage("main").call();
  407. // We are merging a deletion into our branch
  408. MergeResult result = git.merge().include(secondCommit.getId())
  409. .setStrategy(MergeStrategy.RESOLVE).call();
  410. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  411. }
  412. @Test
  413. public void testDeletionAndConflict() throws Exception {
  414. Git git = new Git(db);
  415. writeTrashFile("a", "1\na\n3\n");
  416. writeTrashFile("b", "1\nb\n3\n");
  417. writeTrashFile("d", "1\nd\n3\n");
  418. writeTrashFile("c/c/c", "1\nc\n3\n");
  419. git.add().addFilepattern("a").addFilepattern("b")
  420. .addFilepattern("c/c/c").addFilepattern("d").call();
  421. RevCommit initialCommit = git.commit().setMessage("initial").call();
  422. createBranch(initialCommit, "refs/heads/side");
  423. checkoutBranch("refs/heads/side");
  424. assertTrue(new File(db.getWorkTree(), "b").delete());
  425. writeTrashFile("a", "1\na\n3(side)\n");
  426. git.add().addFilepattern("b").setUpdate(true).call();
  427. git.add().addFilepattern("a").setUpdate(true).call();
  428. RevCommit secondCommit = git.commit().setMessage("side").call();
  429. assertFalse(new File(db.getWorkTree(), "b").exists());
  430. checkoutBranch("refs/heads/master");
  431. assertTrue(new File(db.getWorkTree(), "b").exists());
  432. writeTrashFile("a", "1\na\n3(main)\n");
  433. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  434. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  435. git.commit().setMessage("main").call();
  436. // We are merging a deletion into our branch
  437. MergeResult result = git.merge().include(secondCommit.getId())
  438. .setStrategy(MergeStrategy.RESOLVE).call();
  439. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  440. assertEquals(
  441. "1\na\n<<<<<<< HEAD\n3(main)\n=======\n3(side)\n>>>>>>> 54ffed45d62d252715fc20e41da92d44c48fb0ff\n",
  442. read(new File(db.getWorkTree(), "a")));
  443. assertFalse(new File(db.getWorkTree(), "b").exists());
  444. assertEquals("1\nc(main)\n3\n",
  445. read(new File(db.getWorkTree(), "c/c/c")));
  446. }
  447. @Test
  448. public void testMergeFailingWithDirtyWorkingTree() throws Exception {
  449. Git git = new Git(db);
  450. writeTrashFile("a", "1\na\n3\n");
  451. writeTrashFile("b", "1\nb\n3\n");
  452. git.add().addFilepattern("a").addFilepattern("b").call();
  453. RevCommit initialCommit = git.commit().setMessage("initial").call();
  454. createBranch(initialCommit, "refs/heads/side");
  455. checkoutBranch("refs/heads/side");
  456. writeTrashFile("a", "1(side)\na\n3\n");
  457. writeTrashFile("b", "1\nb(side)\n3\n");
  458. git.add().addFilepattern("a").addFilepattern("b").call();
  459. RevCommit secondCommit = git.commit().setMessage("side").call();
  460. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  461. checkoutBranch("refs/heads/master");
  462. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  463. writeTrashFile("a", "1\na\n3(main)\n");
  464. git.add().addFilepattern("a").call();
  465. git.commit().setMessage("main").call();
  466. writeTrashFile("a", "--- dirty ---");
  467. MergeResult result = git.merge().include(secondCommit.getId())
  468. .setStrategy(MergeStrategy.RESOLVE).call();
  469. assertEquals(MergeStatus.FAILED, result.getMergeStatus());
  470. assertEquals("--- dirty ---", read(new File(db.getWorkTree(), "a")));
  471. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  472. assertEquals(null, result.getConflicts());
  473. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  474. }
  475. @Test
  476. public void testMergeConflictFileFolder() throws Exception {
  477. Git git = new Git(db);
  478. writeTrashFile("a", "1\na\n3\n");
  479. writeTrashFile("b", "1\nb\n3\n");
  480. git.add().addFilepattern("a").addFilepattern("b").call();
  481. RevCommit initialCommit = git.commit().setMessage("initial").call();
  482. createBranch(initialCommit, "refs/heads/side");
  483. checkoutBranch("refs/heads/side");
  484. writeTrashFile("c/c/c", "1\nc(side)\n3\n");
  485. writeTrashFile("d", "1\nd(side)\n3\n");
  486. git.add().addFilepattern("c/c/c").addFilepattern("d").call();
  487. RevCommit secondCommit = git.commit().setMessage("side").call();
  488. checkoutBranch("refs/heads/master");
  489. writeTrashFile("c", "1\nc(main)\n3\n");
  490. writeTrashFile("d/d/d", "1\nd(main)\n3\n");
  491. git.add().addFilepattern("c").addFilepattern("d/d/d").call();
  492. git.commit().setMessage("main").call();
  493. MergeResult result = git.merge().include(secondCommit.getId())
  494. .setStrategy(MergeStrategy.RESOLVE).call();
  495. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  496. assertEquals("1\na\n3\n", read(new File(db.getWorkTree(), "a")));
  497. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  498. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(), "c")));
  499. assertEquals("1\nd(main)\n3\n", read(new File(db.getWorkTree(), "d/d/d")));
  500. assertEquals(null, result.getConflicts());
  501. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  502. }
  503. private void createBranch(ObjectId objectId, String branchName) throws IOException {
  504. RefUpdate updateRef = db.updateRef(branchName);
  505. updateRef.setNewObjectId(objectId);
  506. updateRef.update();
  507. }
  508. private void checkoutBranch(String branchName) throws IllegalStateException, IOException {
  509. RevWalk walk = new RevWalk(db);
  510. RevCommit head = walk.parseCommit(db.resolve(Constants.HEAD));
  511. RevCommit branch = walk.parseCommit(db.resolve(branchName));
  512. DirCacheCheckout dco = new DirCacheCheckout(db,
  513. head.getTree().getId(), db.lockDirCache(),
  514. branch.getTree().getId());
  515. dco.setFailOnConflict(true);
  516. dco.checkout();
  517. walk.release();
  518. // update the HEAD
  519. RefUpdate refUpdate = db.updateRef(Constants.HEAD);
  520. refUpdate.link(branchName);
  521. }
  522. }