Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  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.util.Iterator;
  51. import org.eclipse.jgit.api.MergeResult.MergeStatus;
  52. import org.eclipse.jgit.api.errors.InvalidMergeHeadsException;
  53. import org.eclipse.jgit.lib.Constants;
  54. import org.eclipse.jgit.lib.Ref;
  55. import org.eclipse.jgit.lib.RepositoryState;
  56. import org.eclipse.jgit.lib.RepositoryTestCase;
  57. import org.eclipse.jgit.merge.MergeStrategy;
  58. import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
  59. import org.eclipse.jgit.revwalk.RevCommit;
  60. import org.junit.Test;
  61. public class MergeCommandTest extends RepositoryTestCase {
  62. @Test
  63. public void testMergeInItself() throws Exception {
  64. Git git = new Git(db);
  65. git.commit().setMessage("initial commit").call();
  66. MergeResult result = git.merge().include(db.getRef(Constants.HEAD)).call();
  67. assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
  68. }
  69. @Test
  70. public void testAlreadyUpToDate() throws Exception {
  71. Git git = new Git(db);
  72. RevCommit first = git.commit().setMessage("initial commit").call();
  73. createBranch(first, "refs/heads/branch1");
  74. RevCommit second = git.commit().setMessage("second commit").call();
  75. MergeResult result = git.merge().include(db.getRef("refs/heads/branch1")).call();
  76. assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
  77. assertEquals(second, result.getNewHead());
  78. }
  79. @Test
  80. public void testFastForward() throws Exception {
  81. Git git = new Git(db);
  82. RevCommit first = git.commit().setMessage("initial commit").call();
  83. createBranch(first, "refs/heads/branch1");
  84. RevCommit second = git.commit().setMessage("second commit").call();
  85. checkoutBranch("refs/heads/branch1");
  86. MergeResult result = git.merge().include(db.getRef(Constants.MASTER)).call();
  87. assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
  88. assertEquals(second, result.getNewHead());
  89. }
  90. @Test
  91. public void testFastForwardWithFiles() throws Exception {
  92. Git git = new Git(db);
  93. writeTrashFile("file1", "file1");
  94. git.add().addFilepattern("file1").call();
  95. RevCommit first = git.commit().setMessage("initial commit").call();
  96. assertTrue(new File(db.getWorkTree(), "file1").exists());
  97. createBranch(first, "refs/heads/branch1");
  98. writeTrashFile("file2", "file2");
  99. git.add().addFilepattern("file2").call();
  100. RevCommit second = git.commit().setMessage("second commit").call();
  101. assertTrue(new File(db.getWorkTree(), "file2").exists());
  102. checkoutBranch("refs/heads/branch1");
  103. assertFalse(new File(db.getWorkTree(), "file2").exists());
  104. MergeResult result = git.merge().include(db.getRef(Constants.MASTER)).call();
  105. assertTrue(new File(db.getWorkTree(), "file1").exists());
  106. assertTrue(new File(db.getWorkTree(), "file2").exists());
  107. assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
  108. assertEquals(second, result.getNewHead());
  109. }
  110. @Test
  111. public void testMultipleHeads() throws Exception {
  112. Git git = new Git(db);
  113. writeTrashFile("file1", "file1");
  114. git.add().addFilepattern("file1").call();
  115. RevCommit first = git.commit().setMessage("initial commit").call();
  116. createBranch(first, "refs/heads/branch1");
  117. writeTrashFile("file2", "file2");
  118. git.add().addFilepattern("file2").call();
  119. RevCommit second = git.commit().setMessage("second commit").call();
  120. writeTrashFile("file3", "file3");
  121. git.add().addFilepattern("file3").call();
  122. git.commit().setMessage("third commit").call();
  123. checkoutBranch("refs/heads/branch1");
  124. assertFalse(new File(db.getWorkTree(), "file2").exists());
  125. assertFalse(new File(db.getWorkTree(), "file3").exists());
  126. MergeCommand merge = git.merge();
  127. merge.include(second.getId());
  128. merge.include(db.getRef(Constants.MASTER));
  129. try {
  130. merge.call();
  131. fail("Expected exception not thrown when merging multiple heads");
  132. } catch (InvalidMergeHeadsException e) {
  133. // expected this exception
  134. }
  135. }
  136. @Test
  137. public void testContentMerge() throws Exception {
  138. Git git = new Git(db);
  139. writeTrashFile("a", "1\na\n3\n");
  140. writeTrashFile("b", "1\nb\n3\n");
  141. writeTrashFile("c/c/c", "1\nc\n3\n");
  142. git.add().addFilepattern("a").addFilepattern("b")
  143. .addFilepattern("c/c/c").call();
  144. RevCommit initialCommit = git.commit().setMessage("initial").call();
  145. createBranch(initialCommit, "refs/heads/side");
  146. checkoutBranch("refs/heads/side");
  147. writeTrashFile("a", "1\na(side)\n3\n");
  148. writeTrashFile("b", "1\nb(side)\n3\n");
  149. git.add().addFilepattern("a").addFilepattern("b").call();
  150. RevCommit secondCommit = git.commit().setMessage("side").call();
  151. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  152. checkoutBranch("refs/heads/master");
  153. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  154. writeTrashFile("a", "1\na(main)\n3\n");
  155. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  156. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  157. git.commit().setMessage("main").call();
  158. MergeResult result = git.merge().include(secondCommit.getId())
  159. .setStrategy(MergeStrategy.RESOLVE).call();
  160. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  161. assertEquals(
  162. "1\n<<<<<<< HEAD\na(main)\n=======\na(side)\n>>>>>>> 86503e7e397465588cc267b65d778538bffccb83\n3\n",
  163. read(new File(db.getWorkTree(), "a")));
  164. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  165. assertEquals("1\nc(main)\n3\n",
  166. read(new File(db.getWorkTree(), "c/c/c")));
  167. assertEquals(1, result.getConflicts().size());
  168. assertEquals(3, result.getConflicts().get("a")[0].length);
  169. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  170. }
  171. @Test
  172. public void testMergeMessage() throws Exception {
  173. Git git = new Git(db);
  174. writeTrashFile("a", "1\na\n3\n");
  175. git.add().addFilepattern("a").call();
  176. RevCommit initialCommit = git.commit().setMessage("initial").call();
  177. createBranch(initialCommit, "refs/heads/side");
  178. checkoutBranch("refs/heads/side");
  179. writeTrashFile("a", "1\na(side)\n3\n");
  180. git.add().addFilepattern("a").call();
  181. git.commit().setMessage("side").call();
  182. checkoutBranch("refs/heads/master");
  183. writeTrashFile("a", "1\na(main)\n3\n");
  184. git.add().addFilepattern("a").call();
  185. git.commit().setMessage("main").call();
  186. Ref sideBranch = db.getRef("side");
  187. git.merge().include(sideBranch)
  188. .setStrategy(MergeStrategy.RESOLVE).call();
  189. assertEquals("Merge branch 'side'\n\nConflicts:\n\ta\n",
  190. db.readMergeCommitMsg());
  191. }
  192. @Test
  193. public void testMergeNonVersionedPaths() throws Exception {
  194. Git git = new Git(db);
  195. writeTrashFile("a", "1\na\n3\n");
  196. writeTrashFile("b", "1\nb\n3\n");
  197. writeTrashFile("c/c/c", "1\nc\n3\n");
  198. git.add().addFilepattern("a").addFilepattern("b")
  199. .addFilepattern("c/c/c").call();
  200. RevCommit initialCommit = git.commit().setMessage("initial").call();
  201. createBranch(initialCommit, "refs/heads/side");
  202. checkoutBranch("refs/heads/side");
  203. writeTrashFile("a", "1\na(side)\n3\n");
  204. writeTrashFile("b", "1\nb(side)\n3\n");
  205. git.add().addFilepattern("a").addFilepattern("b").call();
  206. RevCommit secondCommit = git.commit().setMessage("side").call();
  207. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  208. checkoutBranch("refs/heads/master");
  209. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  210. writeTrashFile("a", "1\na(main)\n3\n");
  211. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  212. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  213. git.commit().setMessage("main").call();
  214. writeTrashFile("d", "1\nd\n3\n");
  215. assertTrue(new File(db.getWorkTree(), "e").mkdir());
  216. MergeResult result = git.merge().include(secondCommit.getId())
  217. .setStrategy(MergeStrategy.RESOLVE).call();
  218. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  219. assertEquals(
  220. "1\n<<<<<<< HEAD\na(main)\n=======\na(side)\n>>>>>>> 86503e7e397465588cc267b65d778538bffccb83\n3\n",
  221. read(new File(db.getWorkTree(), "a")));
  222. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  223. assertEquals("1\nc(main)\n3\n",
  224. read(new File(db.getWorkTree(), "c/c/c")));
  225. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  226. File dir = new File(db.getWorkTree(), "e");
  227. assertTrue(dir.isDirectory());
  228. assertEquals(1, result.getConflicts().size());
  229. assertEquals(3, result.getConflicts().get("a")[0].length);
  230. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  231. }
  232. @Test
  233. public void testMultipleCreations() throws Exception {
  234. Git git = new Git(db);
  235. writeTrashFile("a", "1\na\n3\n");
  236. git.add().addFilepattern("a").call();
  237. RevCommit initialCommit = git.commit().setMessage("initial").call();
  238. createBranch(initialCommit, "refs/heads/side");
  239. checkoutBranch("refs/heads/side");
  240. writeTrashFile("b", "1\nb(side)\n3\n");
  241. git.add().addFilepattern("b").call();
  242. RevCommit secondCommit = git.commit().setMessage("side").call();
  243. checkoutBranch("refs/heads/master");
  244. writeTrashFile("b", "1\nb(main)\n3\n");
  245. git.add().addFilepattern("b").call();
  246. git.commit().setMessage("main").call();
  247. MergeResult result = git.merge().include(secondCommit.getId())
  248. .setStrategy(MergeStrategy.RESOLVE).call();
  249. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  250. }
  251. @Test
  252. public void testMultipleCreationsSameContent() throws Exception {
  253. Git git = new Git(db);
  254. writeTrashFile("a", "1\na\n3\n");
  255. git.add().addFilepattern("a").call();
  256. RevCommit initialCommit = git.commit().setMessage("initial").call();
  257. createBranch(initialCommit, "refs/heads/side");
  258. checkoutBranch("refs/heads/side");
  259. writeTrashFile("b", "1\nb(1)\n3\n");
  260. git.add().addFilepattern("b").call();
  261. RevCommit secondCommit = git.commit().setMessage("side").call();
  262. checkoutBranch("refs/heads/master");
  263. writeTrashFile("b", "1\nb(1)\n3\n");
  264. git.add().addFilepattern("b").call();
  265. git.commit().setMessage("main").call();
  266. MergeResult result = git.merge().include(secondCommit.getId())
  267. .setStrategy(MergeStrategy.RESOLVE).call();
  268. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  269. assertEquals("1\nb(1)\n3\n", read(new File(db.getWorkTree(), "b")));
  270. }
  271. @Test
  272. public void testSuccessfulContentMerge() throws Exception {
  273. Git git = new Git(db);
  274. writeTrashFile("a", "1\na\n3\n");
  275. writeTrashFile("b", "1\nb\n3\n");
  276. writeTrashFile("c/c/c", "1\nc\n3\n");
  277. git.add().addFilepattern("a").addFilepattern("b")
  278. .addFilepattern("c/c/c").call();
  279. RevCommit initialCommit = git.commit().setMessage("initial").call();
  280. createBranch(initialCommit, "refs/heads/side");
  281. checkoutBranch("refs/heads/side");
  282. writeTrashFile("a", "1(side)\na\n3\n");
  283. writeTrashFile("b", "1\nb(side)\n3\n");
  284. git.add().addFilepattern("a").addFilepattern("b").call();
  285. RevCommit secondCommit = git.commit().setMessage("side").call();
  286. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  287. checkoutBranch("refs/heads/master");
  288. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  289. writeTrashFile("a", "1\na\n3(main)\n");
  290. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  291. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  292. RevCommit thirdCommit = git.commit().setMessage("main").call();
  293. MergeResult result = git.merge().include(secondCommit.getId())
  294. .setStrategy(MergeStrategy.RESOLVE).call();
  295. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  296. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  297. "a")));
  298. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  299. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
  300. "c/c/c")));
  301. assertEquals(null, result.getConflicts());
  302. assertTrue(2 == result.getMergedCommits().length);
  303. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  304. assertEquals(secondCommit, result.getMergedCommits()[1]);
  305. Iterator<RevCommit> it = git.log().call().iterator();
  306. RevCommit newHead = it.next();
  307. assertEquals(newHead, result.getNewHead());
  308. assertEquals(2, newHead.getParentCount());
  309. assertEquals(thirdCommit, newHead.getParent(0));
  310. assertEquals(secondCommit, newHead.getParent(1));
  311. assertEquals(
  312. "Merge commit '3fa334456d236a92db020289fe0bf481d91777b4'",
  313. newHead.getFullMessage());
  314. // @TODO fix me
  315. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  316. // test index state
  317. }
  318. @Test
  319. public void testSuccessfulContentMergeAndDirtyworkingTree()
  320. throws Exception {
  321. Git git = new Git(db);
  322. writeTrashFile("a", "1\na\n3\n");
  323. writeTrashFile("b", "1\nb\n3\n");
  324. writeTrashFile("d", "1\nd\n3\n");
  325. writeTrashFile("c/c/c", "1\nc\n3\n");
  326. git.add().addFilepattern("a").addFilepattern("b")
  327. .addFilepattern("c/c/c").addFilepattern("d").call();
  328. RevCommit initialCommit = git.commit().setMessage("initial").call();
  329. createBranch(initialCommit, "refs/heads/side");
  330. checkoutBranch("refs/heads/side");
  331. writeTrashFile("a", "1(side)\na\n3\n");
  332. writeTrashFile("b", "1\nb(side)\n3\n");
  333. git.add().addFilepattern("a").addFilepattern("b").call();
  334. RevCommit secondCommit = git.commit().setMessage("side").call();
  335. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  336. checkoutBranch("refs/heads/master");
  337. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  338. writeTrashFile("a", "1\na\n3(main)\n");
  339. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  340. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  341. RevCommit thirdCommit = git.commit().setMessage("main").call();
  342. writeTrashFile("d", "--- dirty ---");
  343. MergeResult result = git.merge().include(secondCommit.getId())
  344. .setStrategy(MergeStrategy.RESOLVE).call();
  345. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  346. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  347. "a")));
  348. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  349. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
  350. "c/c/c")));
  351. assertEquals("--- dirty ---", read(new File(db.getWorkTree(), "d")));
  352. assertEquals(null, result.getConflicts());
  353. assertTrue(2 == result.getMergedCommits().length);
  354. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  355. assertEquals(secondCommit, result.getMergedCommits()[1]);
  356. Iterator<RevCommit> it = git.log().call().iterator();
  357. RevCommit newHead = it.next();
  358. assertEquals(newHead, result.getNewHead());
  359. assertEquals(2, newHead.getParentCount());
  360. assertEquals(thirdCommit, newHead.getParent(0));
  361. assertEquals(secondCommit, newHead.getParent(1));
  362. assertEquals(
  363. "Merge commit '064d54d98a4cdb0fed1802a21c656bfda67fe879'",
  364. newHead.getFullMessage());
  365. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  366. }
  367. @Test
  368. public void testSingleDeletion() throws Exception {
  369. Git git = new Git(db);
  370. writeTrashFile("a", "1\na\n3\n");
  371. writeTrashFile("b", "1\nb\n3\n");
  372. writeTrashFile("d", "1\nd\n3\n");
  373. writeTrashFile("c/c/c", "1\nc\n3\n");
  374. git.add().addFilepattern("a").addFilepattern("b")
  375. .addFilepattern("c/c/c").addFilepattern("d").call();
  376. RevCommit initialCommit = git.commit().setMessage("initial").call();
  377. createBranch(initialCommit, "refs/heads/side");
  378. checkoutBranch("refs/heads/side");
  379. assertTrue(new File(db.getWorkTree(), "b").delete());
  380. git.add().addFilepattern("b").setUpdate(true).call();
  381. RevCommit secondCommit = git.commit().setMessage("side").call();
  382. assertFalse(new File(db.getWorkTree(), "b").exists());
  383. checkoutBranch("refs/heads/master");
  384. assertTrue(new File(db.getWorkTree(), "b").exists());
  385. writeTrashFile("a", "1\na\n3(main)\n");
  386. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  387. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  388. RevCommit thirdCommit = git.commit().setMessage("main").call();
  389. // We are merging a deletion into our branch
  390. MergeResult result = git.merge().include(secondCommit.getId())
  391. .setStrategy(MergeStrategy.RESOLVE).call();
  392. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  393. assertEquals("1\na\n3(main)\n", read(new File(db.getWorkTree(), "a")));
  394. assertFalse(new File(db.getWorkTree(), "b").exists());
  395. assertEquals("1\nc(main)\n3\n",
  396. read(new File(db.getWorkTree(), "c/c/c")));
  397. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  398. // Do the opposite, be on a branch where we have deleted a file and
  399. // merge in a old commit where this file was not deleted
  400. checkoutBranch("refs/heads/side");
  401. assertFalse(new File(db.getWorkTree(), "b").exists());
  402. result = git.merge().include(thirdCommit.getId())
  403. .setStrategy(MergeStrategy.RESOLVE).call();
  404. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  405. assertEquals("1\na\n3(main)\n", read(new File(db.getWorkTree(), "a")));
  406. assertFalse(new File(db.getWorkTree(), "b").exists());
  407. assertEquals("1\nc(main)\n3\n",
  408. read(new File(db.getWorkTree(), "c/c/c")));
  409. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  410. }
  411. @Test
  412. public void testMultipleDeletions() throws Exception {
  413. Git git = new Git(db);
  414. writeTrashFile("a", "1\na\n3\n");
  415. git.add().addFilepattern("a").call();
  416. RevCommit initialCommit = git.commit().setMessage("initial").call();
  417. createBranch(initialCommit, "refs/heads/side");
  418. checkoutBranch("refs/heads/side");
  419. assertTrue(new File(db.getWorkTree(), "a").delete());
  420. git.add().addFilepattern("a").setUpdate(true).call();
  421. RevCommit secondCommit = git.commit().setMessage("side").call();
  422. assertFalse(new File(db.getWorkTree(), "a").exists());
  423. checkoutBranch("refs/heads/master");
  424. assertTrue(new File(db.getWorkTree(), "a").exists());
  425. assertTrue(new File(db.getWorkTree(), "a").delete());
  426. git.add().addFilepattern("a").setUpdate(true).call();
  427. git.commit().setMessage("main").call();
  428. // We are merging a deletion into our branch
  429. MergeResult result = git.merge().include(secondCommit.getId())
  430. .setStrategy(MergeStrategy.RESOLVE).call();
  431. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  432. }
  433. @Test
  434. public void testDeletionAndConflict() throws Exception {
  435. Git git = new Git(db);
  436. writeTrashFile("a", "1\na\n3\n");
  437. writeTrashFile("b", "1\nb\n3\n");
  438. writeTrashFile("d", "1\nd\n3\n");
  439. writeTrashFile("c/c/c", "1\nc\n3\n");
  440. git.add().addFilepattern("a").addFilepattern("b")
  441. .addFilepattern("c/c/c").addFilepattern("d").call();
  442. RevCommit initialCommit = git.commit().setMessage("initial").call();
  443. createBranch(initialCommit, "refs/heads/side");
  444. checkoutBranch("refs/heads/side");
  445. assertTrue(new File(db.getWorkTree(), "b").delete());
  446. writeTrashFile("a", "1\na\n3(side)\n");
  447. git.add().addFilepattern("b").setUpdate(true).call();
  448. git.add().addFilepattern("a").setUpdate(true).call();
  449. RevCommit secondCommit = git.commit().setMessage("side").call();
  450. assertFalse(new File(db.getWorkTree(), "b").exists());
  451. checkoutBranch("refs/heads/master");
  452. assertTrue(new File(db.getWorkTree(), "b").exists());
  453. writeTrashFile("a", "1\na\n3(main)\n");
  454. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  455. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  456. git.commit().setMessage("main").call();
  457. // We are merging a deletion into our branch
  458. MergeResult result = git.merge().include(secondCommit.getId())
  459. .setStrategy(MergeStrategy.RESOLVE).call();
  460. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  461. assertEquals(
  462. "1\na\n<<<<<<< HEAD\n3(main)\n=======\n3(side)\n>>>>>>> 54ffed45d62d252715fc20e41da92d44c48fb0ff\n",
  463. read(new File(db.getWorkTree(), "a")));
  464. assertFalse(new File(db.getWorkTree(), "b").exists());
  465. assertEquals("1\nc(main)\n3\n",
  466. read(new File(db.getWorkTree(), "c/c/c")));
  467. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  468. }
  469. @Test
  470. public void testMergeFailingWithDirtyWorkingTree() throws Exception {
  471. Git git = new Git(db);
  472. writeTrashFile("a", "1\na\n3\n");
  473. writeTrashFile("b", "1\nb\n3\n");
  474. git.add().addFilepattern("a").addFilepattern("b").call();
  475. RevCommit initialCommit = git.commit().setMessage("initial").call();
  476. createBranch(initialCommit, "refs/heads/side");
  477. checkoutBranch("refs/heads/side");
  478. writeTrashFile("a", "1(side)\na\n3\n");
  479. writeTrashFile("b", "1\nb(side)\n3\n");
  480. git.add().addFilepattern("a").addFilepattern("b").call();
  481. RevCommit secondCommit = git.commit().setMessage("side").call();
  482. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  483. checkoutBranch("refs/heads/master");
  484. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  485. writeTrashFile("a", "1\na\n3(main)\n");
  486. git.add().addFilepattern("a").call();
  487. git.commit().setMessage("main").call();
  488. writeTrashFile("a", "--- dirty ---");
  489. MergeResult result = git.merge().include(secondCommit.getId())
  490. .setStrategy(MergeStrategy.RESOLVE).call();
  491. assertEquals(MergeStatus.FAILED, result.getMergeStatus());
  492. assertEquals("--- dirty ---", read(new File(db.getWorkTree(), "a")));
  493. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  494. assertEquals(null, result.getConflicts());
  495. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  496. }
  497. @Test
  498. public void testMergeConflictFileFolder() throws Exception {
  499. Git git = new Git(db);
  500. writeTrashFile("a", "1\na\n3\n");
  501. writeTrashFile("b", "1\nb\n3\n");
  502. git.add().addFilepattern("a").addFilepattern("b").call();
  503. RevCommit initialCommit = git.commit().setMessage("initial").call();
  504. createBranch(initialCommit, "refs/heads/side");
  505. checkoutBranch("refs/heads/side");
  506. writeTrashFile("c/c/c", "1\nc(side)\n3\n");
  507. writeTrashFile("d", "1\nd(side)\n3\n");
  508. git.add().addFilepattern("c/c/c").addFilepattern("d").call();
  509. RevCommit secondCommit = git.commit().setMessage("side").call();
  510. checkoutBranch("refs/heads/master");
  511. writeTrashFile("c", "1\nc(main)\n3\n");
  512. writeTrashFile("d/d/d", "1\nd(main)\n3\n");
  513. git.add().addFilepattern("c").addFilepattern("d/d/d").call();
  514. git.commit().setMessage("main").call();
  515. MergeResult result = git.merge().include(secondCommit.getId())
  516. .setStrategy(MergeStrategy.RESOLVE).call();
  517. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  518. assertEquals("1\na\n3\n", read(new File(db.getWorkTree(), "a")));
  519. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  520. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(), "c")));
  521. assertEquals("1\nd(main)\n3\n", read(new File(db.getWorkTree(), "d/d/d")));
  522. assertEquals(null, result.getConflicts());
  523. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  524. }
  525. @Test
  526. public void testSuccessfulMergeFailsDueToDirtyIndex() throws Exception {
  527. Git git = new Git(db);
  528. File fileA = writeTrashFile("a", "a");
  529. RevCommit initialCommit = addAllAndCommit(git);
  530. // switch branch
  531. createBranch(initialCommit, "refs/heads/side");
  532. checkoutBranch("refs/heads/side");
  533. // modify file a
  534. write(fileA, "a(side)");
  535. writeTrashFile("b", "b");
  536. RevCommit sideCommit = addAllAndCommit(git);
  537. // switch branch
  538. checkoutBranch("refs/heads/master");
  539. writeTrashFile("c", "c");
  540. addAllAndCommit(git);
  541. // modify and add file a
  542. write(fileA, "a(modified)");
  543. git.add().addFilepattern("a").call();
  544. // do not commit
  545. // get current index state
  546. String indexState = indexState(CONTENT);
  547. // merge
  548. MergeResult result = git.merge().include(sideCommit.getId())
  549. .setStrategy(MergeStrategy.RESOLVE).call();
  550. checkMergeFailedResult(result, MergeFailureReason.DIRTY_INDEX,
  551. indexState, fileA);
  552. }
  553. @Test
  554. public void testConflictingMergeFailsDueToDirtyIndex() throws Exception {
  555. Git git = new Git(db);
  556. File fileA = writeTrashFile("a", "a");
  557. RevCommit initialCommit = addAllAndCommit(git);
  558. // switch branch
  559. createBranch(initialCommit, "refs/heads/side");
  560. checkoutBranch("refs/heads/side");
  561. // modify file a
  562. write(fileA, "a(side)");
  563. writeTrashFile("b", "b");
  564. RevCommit sideCommit = addAllAndCommit(git);
  565. // switch branch
  566. checkoutBranch("refs/heads/master");
  567. // modify file a - this will cause a conflict during merge
  568. write(fileA, "a(master)");
  569. writeTrashFile("c", "c");
  570. addAllAndCommit(git);
  571. // modify and add file a
  572. write(fileA, "a(modified)");
  573. git.add().addFilepattern("a").call();
  574. // do not commit
  575. // get current index state
  576. String indexState = indexState(CONTENT);
  577. // merge
  578. MergeResult result = git.merge().include(sideCommit.getId())
  579. .setStrategy(MergeStrategy.RESOLVE).call();
  580. checkMergeFailedResult(result, MergeFailureReason.DIRTY_INDEX,
  581. indexState, fileA);
  582. }
  583. @Test
  584. public void testSuccessfulMergeFailsDueToDirtyWorktree() throws Exception {
  585. Git git = new Git(db);
  586. File fileA = writeTrashFile("a", "a");
  587. RevCommit initialCommit = addAllAndCommit(git);
  588. // switch branch
  589. createBranch(initialCommit, "refs/heads/side");
  590. checkoutBranch("refs/heads/side");
  591. // modify file a
  592. write(fileA, "a(side)");
  593. writeTrashFile("b", "b");
  594. RevCommit sideCommit = addAllAndCommit(git);
  595. // switch branch
  596. checkoutBranch("refs/heads/master");
  597. writeTrashFile("c", "c");
  598. addAllAndCommit(git);
  599. // modify file a
  600. write(fileA, "a(modified)");
  601. // do not add and commit
  602. // get current index state
  603. String indexState = indexState(CONTENT);
  604. // merge
  605. MergeResult result = git.merge().include(sideCommit.getId())
  606. .setStrategy(MergeStrategy.RESOLVE).call();
  607. checkMergeFailedResult(result, MergeFailureReason.DIRTY_WORKTREE,
  608. indexState, fileA);
  609. }
  610. @Test
  611. public void testConflictingMergeFailsDueToDirtyWorktree() throws Exception {
  612. Git git = new Git(db);
  613. File fileA = writeTrashFile("a", "a");
  614. RevCommit initialCommit = addAllAndCommit(git);
  615. // switch branch
  616. createBranch(initialCommit, "refs/heads/side");
  617. checkoutBranch("refs/heads/side");
  618. // modify file a
  619. write(fileA, "a(side)");
  620. writeTrashFile("b", "b");
  621. RevCommit sideCommit = addAllAndCommit(git);
  622. // switch branch
  623. checkoutBranch("refs/heads/master");
  624. // modify file a - this will cause a conflict during merge
  625. write(fileA, "a(master)");
  626. writeTrashFile("c", "c");
  627. addAllAndCommit(git);
  628. // modify file a
  629. write(fileA, "a(modified)");
  630. // do not add and commit
  631. // get current index state
  632. String indexState = indexState(CONTENT);
  633. // merge
  634. MergeResult result = git.merge().include(sideCommit.getId())
  635. .setStrategy(MergeStrategy.RESOLVE).call();
  636. checkMergeFailedResult(result, MergeFailureReason.DIRTY_WORKTREE,
  637. indexState, fileA);
  638. }
  639. private RevCommit addAllAndCommit(final Git git) throws Exception {
  640. git.add().addFilepattern(".").call();
  641. return git.commit().setMessage("message").call();
  642. }
  643. private void checkMergeFailedResult(final MergeResult result,
  644. final MergeFailureReason reason,
  645. final String indexState, final File fileA) throws Exception {
  646. assertEquals(MergeStatus.FAILED, result.getMergeStatus());
  647. assertEquals(reason, result.getFailingPaths().get("a"));
  648. assertEquals("a(modified)", read(fileA));
  649. assertFalse(new File(db.getWorkTree(), "b").exists());
  650. assertEquals("c", read(new File(db.getWorkTree(), "c")));
  651. assertEquals(indexState, indexState(CONTENT));
  652. assertEquals(null, result.getConflicts());
  653. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  654. }
  655. }