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 59KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677
  1. /*
  2. * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com>
  3. * Copyright (C) 2010-2014, 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.eclipse.jgit.lib.Constants.MASTER;
  46. import static org.eclipse.jgit.lib.Constants.R_HEADS;
  47. import static org.junit.Assert.assertEquals;
  48. import static org.junit.Assert.assertFalse;
  49. import static org.junit.Assert.assertNull;
  50. import static org.junit.Assert.assertTrue;
  51. import static org.junit.Assert.fail;
  52. import static org.junit.Assume.assumeTrue;
  53. import java.io.File;
  54. import java.util.Iterator;
  55. import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
  56. import org.eclipse.jgit.api.MergeResult.MergeStatus;
  57. import org.eclipse.jgit.api.errors.InvalidMergeHeadsException;
  58. import org.eclipse.jgit.junit.RepositoryTestCase;
  59. import org.eclipse.jgit.junit.TestRepository;
  60. import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
  61. import org.eclipse.jgit.lib.Constants;
  62. import org.eclipse.jgit.lib.Ref;
  63. import org.eclipse.jgit.lib.Repository;
  64. import org.eclipse.jgit.lib.RepositoryState;
  65. import org.eclipse.jgit.lib.Sets;
  66. import org.eclipse.jgit.merge.MergeStrategy;
  67. import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
  68. import org.eclipse.jgit.revwalk.RevCommit;
  69. import org.eclipse.jgit.util.FS;
  70. import org.eclipse.jgit.util.FileUtils;
  71. import org.eclipse.jgit.util.GitDateFormatter;
  72. import org.eclipse.jgit.util.GitDateFormatter.Format;
  73. import org.junit.Before;
  74. import org.junit.Test;
  75. import org.junit.experimental.theories.DataPoints;
  76. import org.junit.experimental.theories.Theories;
  77. import org.junit.experimental.theories.Theory;
  78. import org.junit.runner.RunWith;
  79. @RunWith(Theories.class)
  80. public class MergeCommandTest extends RepositoryTestCase {
  81. public static @DataPoints
  82. MergeStrategy[] mergeStrategies = MergeStrategy.get();
  83. private GitDateFormatter dateFormatter;
  84. @Override
  85. @Before
  86. public void setUp() throws Exception {
  87. super.setUp();
  88. dateFormatter = new GitDateFormatter(Format.DEFAULT);
  89. }
  90. @Test
  91. public void testMergeInItself() throws Exception {
  92. try (Git git = new Git(db)) {
  93. git.commit().setMessage("initial commit").call();
  94. MergeResult result = git.merge().include(db.exactRef(Constants.HEAD)).call();
  95. assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
  96. }
  97. // no reflog entry written by merge
  98. assertEquals("commit (initial): initial commit",
  99. db
  100. .getReflogReader(Constants.HEAD).getLastEntry().getComment());
  101. assertEquals("commit (initial): initial commit",
  102. db
  103. .getReflogReader(db.getBranch()).getLastEntry().getComment());
  104. }
  105. @Test
  106. public void testAlreadyUpToDate() throws Exception {
  107. try (Git git = new Git(db)) {
  108. RevCommit first = git.commit().setMessage("initial commit").call();
  109. createBranch(first, "refs/heads/branch1");
  110. RevCommit second = git.commit().setMessage("second commit").call();
  111. MergeResult result = git.merge().include(db.exactRef("refs/heads/branch1")).call();
  112. assertEquals(MergeResult.MergeStatus.ALREADY_UP_TO_DATE, result.getMergeStatus());
  113. assertEquals(second, result.getNewHead());
  114. }
  115. // no reflog entry written by merge
  116. assertEquals("commit: second commit", db
  117. .getReflogReader(Constants.HEAD).getLastEntry().getComment());
  118. assertEquals("commit: second commit", db
  119. .getReflogReader(db.getBranch()).getLastEntry().getComment());
  120. }
  121. @Test
  122. public void testFastForward() throws Exception {
  123. try (Git git = new Git(db)) {
  124. RevCommit first = git.commit().setMessage("initial commit").call();
  125. createBranch(first, "refs/heads/branch1");
  126. RevCommit second = git.commit().setMessage("second commit").call();
  127. checkoutBranch("refs/heads/branch1");
  128. MergeResult result = git.merge().include(db.exactRef(R_HEADS + MASTER)).call();
  129. assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
  130. assertEquals(second, result.getNewHead());
  131. }
  132. assertEquals("merge refs/heads/master: Fast-forward",
  133. db.getReflogReader(Constants.HEAD).getLastEntry().getComment());
  134. assertEquals("merge refs/heads/master: Fast-forward",
  135. db.getReflogReader(db.getBranch()).getLastEntry().getComment());
  136. }
  137. @Test
  138. public void testFastForwardNoCommit() throws Exception {
  139. try (Git git = new Git(db)) {
  140. RevCommit first = git.commit().setMessage("initial commit").call();
  141. createBranch(first, "refs/heads/branch1");
  142. RevCommit second = git.commit().setMessage("second commit").call();
  143. checkoutBranch("refs/heads/branch1");
  144. MergeResult result = git.merge().include(db.exactRef(R_HEADS + MASTER))
  145. .setCommit(false).call();
  146. assertEquals(MergeResult.MergeStatus.FAST_FORWARD,
  147. result.getMergeStatus());
  148. assertEquals(second, result.getNewHead());
  149. }
  150. assertEquals("merge refs/heads/master: Fast-forward", db
  151. .getReflogReader(Constants.HEAD).getLastEntry().getComment());
  152. assertEquals("merge refs/heads/master: Fast-forward", db
  153. .getReflogReader(db.getBranch()).getLastEntry().getComment());
  154. }
  155. @Test
  156. public void testFastForwardWithFiles() throws Exception {
  157. try (Git git = new Git(db)) {
  158. writeTrashFile("file1", "file1");
  159. git.add().addFilepattern("file1").call();
  160. RevCommit first = git.commit().setMessage("initial commit").call();
  161. assertTrue(new File(db.getWorkTree(), "file1").exists());
  162. createBranch(first, "refs/heads/branch1");
  163. writeTrashFile("file2", "file2");
  164. git.add().addFilepattern("file2").call();
  165. RevCommit second = git.commit().setMessage("second commit").call();
  166. assertTrue(new File(db.getWorkTree(), "file2").exists());
  167. checkoutBranch("refs/heads/branch1");
  168. assertFalse(new File(db.getWorkTree(), "file2").exists());
  169. MergeResult result = git.merge().include(db.exactRef(R_HEADS + MASTER)).call();
  170. assertTrue(new File(db.getWorkTree(), "file1").exists());
  171. assertTrue(new File(db.getWorkTree(), "file2").exists());
  172. assertEquals(MergeResult.MergeStatus.FAST_FORWARD, result.getMergeStatus());
  173. assertEquals(second, result.getNewHead());
  174. }
  175. assertEquals("merge refs/heads/master: Fast-forward",
  176. db.getReflogReader(Constants.HEAD).getLastEntry().getComment());
  177. assertEquals("merge refs/heads/master: Fast-forward",
  178. db.getReflogReader(db.getBranch()).getLastEntry().getComment());
  179. }
  180. @Test
  181. public void testMultipleHeads() throws Exception {
  182. try (Git git = new Git(db)) {
  183. writeTrashFile("file1", "file1");
  184. git.add().addFilepattern("file1").call();
  185. RevCommit first = git.commit().setMessage("initial commit").call();
  186. createBranch(first, "refs/heads/branch1");
  187. writeTrashFile("file2", "file2");
  188. git.add().addFilepattern("file2").call();
  189. RevCommit second = git.commit().setMessage("second commit").call();
  190. writeTrashFile("file3", "file3");
  191. git.add().addFilepattern("file3").call();
  192. git.commit().setMessage("third commit").call();
  193. checkoutBranch("refs/heads/branch1");
  194. assertFalse(new File(db.getWorkTree(), "file2").exists());
  195. assertFalse(new File(db.getWorkTree(), "file3").exists());
  196. MergeCommand merge = git.merge();
  197. merge.include(second.getId());
  198. merge.include(db.exactRef(R_HEADS + MASTER));
  199. try {
  200. merge.call();
  201. fail("Expected exception not thrown when merging multiple heads");
  202. } catch (InvalidMergeHeadsException e) {
  203. // expected this exception
  204. }
  205. }
  206. }
  207. @Theory
  208. public void testMergeSuccessAllStrategies(MergeStrategy mergeStrategy)
  209. throws Exception {
  210. try (Git git = new Git(db)) {
  211. RevCommit first = git.commit().setMessage("first").call();
  212. createBranch(first, "refs/heads/side");
  213. writeTrashFile("a", "a");
  214. git.add().addFilepattern("a").call();
  215. git.commit().setMessage("second").call();
  216. checkoutBranch("refs/heads/side");
  217. writeTrashFile("b", "b");
  218. git.add().addFilepattern("b").call();
  219. git.commit().setMessage("third").call();
  220. MergeResult result = git.merge().setStrategy(mergeStrategy)
  221. .include(db.exactRef(R_HEADS + MASTER)).call();
  222. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  223. }
  224. assertEquals(
  225. "merge refs/heads/master: Merge made by "
  226. + mergeStrategy.getName() + ".",
  227. db.getReflogReader(Constants.HEAD).getLastEntry().getComment());
  228. assertEquals(
  229. "merge refs/heads/master: Merge made by "
  230. + mergeStrategy.getName() + ".",
  231. db.getReflogReader(db.getBranch()).getLastEntry().getComment());
  232. }
  233. @Theory
  234. public void testMergeSuccessAllStrategiesNoCommit(
  235. MergeStrategy mergeStrategy) throws Exception {
  236. try (Git git = new Git(db)) {
  237. RevCommit first = git.commit().setMessage("first").call();
  238. createBranch(first, "refs/heads/side");
  239. writeTrashFile("a", "a");
  240. git.add().addFilepattern("a").call();
  241. git.commit().setMessage("second").call();
  242. checkoutBranch("refs/heads/side");
  243. writeTrashFile("b", "b");
  244. git.add().addFilepattern("b").call();
  245. RevCommit thirdCommit = git.commit().setMessage("third").call();
  246. MergeResult result = git.merge().setStrategy(mergeStrategy)
  247. .setCommit(false)
  248. .include(db.exactRef(R_HEADS + MASTER)).call();
  249. assertEquals(MergeStatus.MERGED_NOT_COMMITTED, result.getMergeStatus());
  250. assertEquals(db.exactRef(Constants.HEAD).getTarget().getObjectId(),
  251. thirdCommit.getId());
  252. }
  253. }
  254. @Test
  255. public void testContentMerge() throws Exception {
  256. try (Git git = new Git(db)) {
  257. writeTrashFile("a", "1\na\n3\n");
  258. writeTrashFile("b", "1\nb\n3\n");
  259. writeTrashFile("c/c/c", "1\nc\n3\n");
  260. git.add().addFilepattern("a").addFilepattern("b")
  261. .addFilepattern("c/c/c").call();
  262. RevCommit initialCommit = git.commit().setMessage("initial").call();
  263. createBranch(initialCommit, "refs/heads/side");
  264. checkoutBranch("refs/heads/side");
  265. writeTrashFile("a", "1\na(side)\n3\n");
  266. writeTrashFile("b", "1\nb(side)\n3\n");
  267. git.add().addFilepattern("a").addFilepattern("b").call();
  268. RevCommit secondCommit = git.commit().setMessage("side").call();
  269. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  270. checkoutBranch("refs/heads/master");
  271. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  272. writeTrashFile("a", "1\na(main)\n3\n");
  273. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  274. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  275. git.commit().setMessage("main").call();
  276. MergeResult result = git.merge().include(secondCommit.getId())
  277. .setStrategy(MergeStrategy.RESOLVE).call();
  278. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  279. assertEquals(
  280. "1\n<<<<<<< HEAD\na(main)\n=======\na(side)\n>>>>>>> 86503e7e397465588cc267b65d778538bffccb83\n3\n",
  281. read(new File(db.getWorkTree(), "a")));
  282. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  283. assertEquals("1\nc(main)\n3\n",
  284. read(new File(db.getWorkTree(), "c/c/c")));
  285. assertEquals(1, result.getConflicts().size());
  286. assertEquals(3, result.getConflicts().get("a")[0].length);
  287. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  288. }
  289. }
  290. @Test
  291. public void testMergeTag() throws Exception {
  292. try (Git git = new Git(db)) {
  293. writeTrashFile("a", "a");
  294. git.add().addFilepattern("a").call();
  295. RevCommit initialCommit = git.commit().setMessage("initial").call();
  296. createBranch(initialCommit, "refs/heads/side");
  297. checkoutBranch("refs/heads/side");
  298. writeTrashFile("b", "b");
  299. git.add().addFilepattern("b").call();
  300. RevCommit secondCommit = git.commit().setMessage("side").call();
  301. Ref tag = git.tag().setAnnotated(true).setMessage("my tag 01")
  302. .setName("tag01").setObjectId(secondCommit).call();
  303. checkoutBranch("refs/heads/master");
  304. writeTrashFile("a", "a2");
  305. git.add().addFilepattern("a").call();
  306. git.commit().setMessage("main").call();
  307. MergeResult result = git.merge().include(tag).setStrategy(MergeStrategy.RESOLVE).call();
  308. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  309. }
  310. }
  311. @Test
  312. public void testMergeMessage() throws Exception {
  313. try (Git git = new Git(db)) {
  314. writeTrashFile("a", "1\na\n3\n");
  315. git.add().addFilepattern("a").call();
  316. RevCommit initialCommit = git.commit().setMessage("initial").call();
  317. createBranch(initialCommit, "refs/heads/side");
  318. checkoutBranch("refs/heads/side");
  319. writeTrashFile("a", "1\na(side)\n3\n");
  320. git.add().addFilepattern("a").call();
  321. git.commit().setMessage("side").call();
  322. checkoutBranch("refs/heads/master");
  323. writeTrashFile("a", "1\na(main)\n3\n");
  324. git.add().addFilepattern("a").call();
  325. git.commit().setMessage("main").call();
  326. Ref sideBranch = db.exactRef("refs/heads/side");
  327. git.merge().include(sideBranch)
  328. .setStrategy(MergeStrategy.RESOLVE).call();
  329. assertEquals("Merge branch 'side'\n\nConflicts:\n\ta\n",
  330. db.readMergeCommitMsg());
  331. }
  332. }
  333. @Test
  334. public void testMergeNonVersionedPaths() throws Exception {
  335. try (Git git = new Git(db)) {
  336. writeTrashFile("a", "1\na\n3\n");
  337. writeTrashFile("b", "1\nb\n3\n");
  338. writeTrashFile("c/c/c", "1\nc\n3\n");
  339. git.add().addFilepattern("a").addFilepattern("b")
  340. .addFilepattern("c/c/c").call();
  341. RevCommit initialCommit = git.commit().setMessage("initial").call();
  342. createBranch(initialCommit, "refs/heads/side");
  343. checkoutBranch("refs/heads/side");
  344. writeTrashFile("a", "1\na(side)\n3\n");
  345. writeTrashFile("b", "1\nb(side)\n3\n");
  346. git.add().addFilepattern("a").addFilepattern("b").call();
  347. RevCommit secondCommit = git.commit().setMessage("side").call();
  348. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  349. checkoutBranch("refs/heads/master");
  350. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  351. writeTrashFile("a", "1\na(main)\n3\n");
  352. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  353. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  354. git.commit().setMessage("main").call();
  355. writeTrashFile("d", "1\nd\n3\n");
  356. assertTrue(new File(db.getWorkTree(), "e").mkdir());
  357. MergeResult result = git.merge().include(secondCommit.getId())
  358. .setStrategy(MergeStrategy.RESOLVE).call();
  359. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  360. assertEquals(
  361. "1\n<<<<<<< HEAD\na(main)\n=======\na(side)\n>>>>>>> 86503e7e397465588cc267b65d778538bffccb83\n3\n",
  362. read(new File(db.getWorkTree(), "a")));
  363. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  364. assertEquals("1\nc(main)\n3\n",
  365. read(new File(db.getWorkTree(), "c/c/c")));
  366. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  367. File dir = new File(db.getWorkTree(), "e");
  368. assertTrue(dir.isDirectory());
  369. assertEquals(1, result.getConflicts().size());
  370. assertEquals(3, result.getConflicts().get("a")[0].length);
  371. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  372. }
  373. }
  374. @Test
  375. public void testMultipleCreations() throws Exception {
  376. try (Git git = new Git(db)) {
  377. writeTrashFile("a", "1\na\n3\n");
  378. git.add().addFilepattern("a").call();
  379. RevCommit initialCommit = git.commit().setMessage("initial").call();
  380. createBranch(initialCommit, "refs/heads/side");
  381. checkoutBranch("refs/heads/side");
  382. writeTrashFile("b", "1\nb(side)\n3\n");
  383. git.add().addFilepattern("b").call();
  384. RevCommit secondCommit = git.commit().setMessage("side").call();
  385. checkoutBranch("refs/heads/master");
  386. writeTrashFile("b", "1\nb(main)\n3\n");
  387. git.add().addFilepattern("b").call();
  388. git.commit().setMessage("main").call();
  389. MergeResult result = git.merge().include(secondCommit.getId())
  390. .setStrategy(MergeStrategy.RESOLVE).call();
  391. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  392. }
  393. }
  394. @Test
  395. public void testMultipleCreationsSameContent() throws Exception {
  396. try (Git git = new Git(db)) {
  397. writeTrashFile("a", "1\na\n3\n");
  398. git.add().addFilepattern("a").call();
  399. RevCommit initialCommit = git.commit().setMessage("initial").call();
  400. createBranch(initialCommit, "refs/heads/side");
  401. checkoutBranch("refs/heads/side");
  402. writeTrashFile("b", "1\nb(1)\n3\n");
  403. git.add().addFilepattern("b").call();
  404. RevCommit secondCommit = git.commit().setMessage("side").call();
  405. checkoutBranch("refs/heads/master");
  406. writeTrashFile("b", "1\nb(1)\n3\n");
  407. git.add().addFilepattern("b").call();
  408. git.commit().setMessage("main").call();
  409. MergeResult result = git.merge().include(secondCommit.getId())
  410. .setStrategy(MergeStrategy.RESOLVE).call();
  411. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  412. assertEquals("1\nb(1)\n3\n", read(new File(db.getWorkTree(), "b")));
  413. assertEquals("merge " + secondCommit.getId().getName()
  414. + ": Merge made by resolve.", db
  415. .getReflogReader(Constants.HEAD)
  416. .getLastEntry().getComment());
  417. assertEquals("merge " + secondCommit.getId().getName()
  418. + ": Merge made by resolve.", db
  419. .getReflogReader(db.getBranch())
  420. .getLastEntry().getComment());
  421. }
  422. }
  423. @Test
  424. public void testSuccessfulContentMerge() throws Exception {
  425. try (Git git = new Git(db)) {
  426. writeTrashFile("a", "1\na\n3\n");
  427. writeTrashFile("b", "1\nb\n3\n");
  428. writeTrashFile("c/c/c", "1\nc\n3\n");
  429. git.add().addFilepattern("a").addFilepattern("b")
  430. .addFilepattern("c/c/c").call();
  431. RevCommit initialCommit = git.commit().setMessage("initial").call();
  432. createBranch(initialCommit, "refs/heads/side");
  433. checkoutBranch("refs/heads/side");
  434. writeTrashFile("a", "1(side)\na\n3\n");
  435. writeTrashFile("b", "1\nb(side)\n3\n");
  436. git.add().addFilepattern("a").addFilepattern("b").call();
  437. RevCommit secondCommit = git.commit().setMessage("side").call();
  438. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  439. checkoutBranch("refs/heads/master");
  440. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  441. writeTrashFile("a", "1\na\n3(main)\n");
  442. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  443. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  444. RevCommit thirdCommit = git.commit().setMessage("main").call();
  445. MergeResult result = git.merge().include(secondCommit.getId())
  446. .setStrategy(MergeStrategy.RESOLVE).call();
  447. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  448. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  449. "a")));
  450. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  451. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
  452. "c/c/c")));
  453. assertEquals(null, result.getConflicts());
  454. assertEquals(2, result.getMergedCommits().length);
  455. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  456. assertEquals(secondCommit, result.getMergedCommits()[1]);
  457. Iterator<RevCommit> it = git.log().call().iterator();
  458. RevCommit newHead = it.next();
  459. assertEquals(newHead, result.getNewHead());
  460. assertEquals(2, newHead.getParentCount());
  461. assertEquals(thirdCommit, newHead.getParent(0));
  462. assertEquals(secondCommit, newHead.getParent(1));
  463. assertEquals(
  464. "Merge commit '3fa334456d236a92db020289fe0bf481d91777b4'",
  465. newHead.getFullMessage());
  466. // @TODO fix me
  467. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  468. // test index state
  469. }
  470. }
  471. @Test
  472. public void testSuccessfulContentMergeNoCommit() throws Exception {
  473. try (Git git = new Git(db)) {
  474. writeTrashFile("a", "1\na\n3\n");
  475. writeTrashFile("b", "1\nb\n3\n");
  476. writeTrashFile("c/c/c", "1\nc\n3\n");
  477. git.add().addFilepattern("a").addFilepattern("b")
  478. .addFilepattern("c/c/c").call();
  479. RevCommit initialCommit = git.commit().setMessage("initial").call();
  480. createBranch(initialCommit, "refs/heads/side");
  481. checkoutBranch("refs/heads/side");
  482. writeTrashFile("a", "1(side)\na\n3\n");
  483. writeTrashFile("b", "1\nb(side)\n3\n");
  484. git.add().addFilepattern("a").addFilepattern("b").call();
  485. RevCommit secondCommit = git.commit().setMessage("side").call();
  486. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  487. checkoutBranch("refs/heads/master");
  488. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  489. writeTrashFile("a", "1\na\n3(main)\n");
  490. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  491. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  492. RevCommit thirdCommit = git.commit().setMessage("main").call();
  493. MergeResult result = git.merge().include(secondCommit.getId())
  494. .setCommit(false)
  495. .setStrategy(MergeStrategy.RESOLVE).call();
  496. assertEquals(MergeStatus.MERGED_NOT_COMMITTED, result.getMergeStatus());
  497. assertEquals(db.exactRef(Constants.HEAD).getTarget().getObjectId(),
  498. thirdCommit.getId());
  499. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  500. "a")));
  501. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  502. assertEquals("1\nc(main)\n3\n",
  503. read(new File(db.getWorkTree(), "c/c/c")));
  504. assertEquals(null, result.getConflicts());
  505. assertEquals(2, result.getMergedCommits().length);
  506. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  507. assertEquals(secondCommit, result.getMergedCommits()[1]);
  508. assertNull(result.getNewHead());
  509. assertEquals(RepositoryState.MERGING_RESOLVED, db.getRepositoryState());
  510. }
  511. }
  512. @Test
  513. public void testSuccessfulContentMergeAndDirtyworkingTree()
  514. throws Exception {
  515. try (Git git = new Git(db)) {
  516. writeTrashFile("a", "1\na\n3\n");
  517. writeTrashFile("b", "1\nb\n3\n");
  518. writeTrashFile("d", "1\nd\n3\n");
  519. writeTrashFile("c/c/c", "1\nc\n3\n");
  520. git.add().addFilepattern("a").addFilepattern("b")
  521. .addFilepattern("c/c/c").addFilepattern("d").call();
  522. RevCommit initialCommit = git.commit().setMessage("initial").call();
  523. createBranch(initialCommit, "refs/heads/side");
  524. checkoutBranch("refs/heads/side");
  525. writeTrashFile("a", "1(side)\na\n3\n");
  526. writeTrashFile("b", "1\nb(side)\n3\n");
  527. git.add().addFilepattern("a").addFilepattern("b").call();
  528. RevCommit secondCommit = git.commit().setMessage("side").call();
  529. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  530. checkoutBranch("refs/heads/master");
  531. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  532. writeTrashFile("a", "1\na\n3(main)\n");
  533. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  534. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  535. RevCommit thirdCommit = git.commit().setMessage("main").call();
  536. writeTrashFile("d", "--- dirty ---");
  537. MergeResult result = git.merge().include(secondCommit.getId())
  538. .setStrategy(MergeStrategy.RESOLVE).call();
  539. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  540. assertEquals("1(side)\na\n3(main)\n", read(new File(db.getWorkTree(),
  541. "a")));
  542. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  543. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
  544. "c/c/c")));
  545. assertEquals("--- dirty ---", read(new File(db.getWorkTree(), "d")));
  546. assertEquals(null, result.getConflicts());
  547. assertEquals(2, result.getMergedCommits().length);
  548. assertEquals(thirdCommit, result.getMergedCommits()[0]);
  549. assertEquals(secondCommit, result.getMergedCommits()[1]);
  550. Iterator<RevCommit> it = git.log().call().iterator();
  551. RevCommit newHead = it.next();
  552. assertEquals(newHead, result.getNewHead());
  553. assertEquals(2, newHead.getParentCount());
  554. assertEquals(thirdCommit, newHead.getParent(0));
  555. assertEquals(secondCommit, newHead.getParent(1));
  556. assertEquals(
  557. "Merge commit '064d54d98a4cdb0fed1802a21c656bfda67fe879'",
  558. newHead.getFullMessage());
  559. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  560. }
  561. }
  562. @Test
  563. public void testSingleDeletion() throws Exception {
  564. try (Git git = new Git(db)) {
  565. writeTrashFile("a", "1\na\n3\n");
  566. writeTrashFile("b", "1\nb\n3\n");
  567. writeTrashFile("d", "1\nd\n3\n");
  568. writeTrashFile("c/c/c", "1\nc\n3\n");
  569. git.add().addFilepattern("a").addFilepattern("b")
  570. .addFilepattern("c/c/c").addFilepattern("d").call();
  571. RevCommit initialCommit = git.commit().setMessage("initial").call();
  572. createBranch(initialCommit, "refs/heads/side");
  573. checkoutBranch("refs/heads/side");
  574. assertTrue(new File(db.getWorkTree(), "b").delete());
  575. git.add().addFilepattern("b").setUpdate(true).call();
  576. RevCommit secondCommit = git.commit().setMessage("side").call();
  577. assertFalse(new File(db.getWorkTree(), "b").exists());
  578. checkoutBranch("refs/heads/master");
  579. assertTrue(new File(db.getWorkTree(), "b").exists());
  580. writeTrashFile("a", "1\na\n3(main)\n");
  581. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  582. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  583. RevCommit thirdCommit = git.commit().setMessage("main").call();
  584. // We are merging a deletion into our branch
  585. MergeResult result = git.merge().include(secondCommit.getId())
  586. .setStrategy(MergeStrategy.RESOLVE).call();
  587. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  588. assertEquals("1\na\n3(main)\n", read(new File(db.getWorkTree(), "a")));
  589. assertFalse(new File(db.getWorkTree(), "b").exists());
  590. assertEquals("1\nc(main)\n3\n",
  591. read(new File(db.getWorkTree(), "c/c/c")));
  592. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  593. // Do the opposite, be on a branch where we have deleted a file and
  594. // merge in a old commit where this file was not deleted
  595. checkoutBranch("refs/heads/side");
  596. assertFalse(new File(db.getWorkTree(), "b").exists());
  597. result = git.merge().include(thirdCommit.getId())
  598. .setStrategy(MergeStrategy.RESOLVE).call();
  599. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  600. assertEquals("1\na\n3(main)\n", read(new File(db.getWorkTree(), "a")));
  601. assertFalse(new File(db.getWorkTree(), "b").exists());
  602. assertEquals("1\nc(main)\n3\n",
  603. read(new File(db.getWorkTree(), "c/c/c")));
  604. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  605. }
  606. }
  607. @Test
  608. public void testMultipleDeletions() throws Exception {
  609. try (Git git = new Git(db)) {
  610. writeTrashFile("a", "1\na\n3\n");
  611. git.add().addFilepattern("a").call();
  612. RevCommit initialCommit = git.commit().setMessage("initial").call();
  613. createBranch(initialCommit, "refs/heads/side");
  614. checkoutBranch("refs/heads/side");
  615. assertTrue(new File(db.getWorkTree(), "a").delete());
  616. git.add().addFilepattern("a").setUpdate(true).call();
  617. RevCommit secondCommit = git.commit().setMessage("side").call();
  618. assertFalse(new File(db.getWorkTree(), "a").exists());
  619. checkoutBranch("refs/heads/master");
  620. assertTrue(new File(db.getWorkTree(), "a").exists());
  621. assertTrue(new File(db.getWorkTree(), "a").delete());
  622. git.add().addFilepattern("a").setUpdate(true).call();
  623. git.commit().setMessage("main").call();
  624. // We are merging a deletion into our branch
  625. MergeResult result = git.merge().include(secondCommit.getId())
  626. .setStrategy(MergeStrategy.RESOLVE).call();
  627. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  628. }
  629. }
  630. @Test
  631. public void testDeletionAndConflict() throws Exception {
  632. try (Git git = new Git(db)) {
  633. writeTrashFile("a", "1\na\n3\n");
  634. writeTrashFile("b", "1\nb\n3\n");
  635. writeTrashFile("d", "1\nd\n3\n");
  636. writeTrashFile("c/c/c", "1\nc\n3\n");
  637. git.add().addFilepattern("a").addFilepattern("b")
  638. .addFilepattern("c/c/c").addFilepattern("d").call();
  639. RevCommit initialCommit = git.commit().setMessage("initial").call();
  640. createBranch(initialCommit, "refs/heads/side");
  641. checkoutBranch("refs/heads/side");
  642. assertTrue(new File(db.getWorkTree(), "b").delete());
  643. writeTrashFile("a", "1\na\n3(side)\n");
  644. git.add().addFilepattern("b").setUpdate(true).call();
  645. git.add().addFilepattern("a").setUpdate(true).call();
  646. RevCommit secondCommit = git.commit().setMessage("side").call();
  647. assertFalse(new File(db.getWorkTree(), "b").exists());
  648. checkoutBranch("refs/heads/master");
  649. assertTrue(new File(db.getWorkTree(), "b").exists());
  650. writeTrashFile("a", "1\na\n3(main)\n");
  651. writeTrashFile("c/c/c", "1\nc(main)\n3\n");
  652. git.add().addFilepattern("a").addFilepattern("c/c/c").call();
  653. git.commit().setMessage("main").call();
  654. // We are merging a deletion into our branch
  655. MergeResult result = git.merge().include(secondCommit.getId())
  656. .setStrategy(MergeStrategy.RESOLVE).call();
  657. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  658. assertEquals(
  659. "1\na\n<<<<<<< HEAD\n3(main)\n=======\n3(side)\n>>>>>>> 54ffed45d62d252715fc20e41da92d44c48fb0ff\n",
  660. read(new File(db.getWorkTree(), "a")));
  661. assertFalse(new File(db.getWorkTree(), "b").exists());
  662. assertEquals("1\nc(main)\n3\n",
  663. read(new File(db.getWorkTree(), "c/c/c")));
  664. assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
  665. }
  666. }
  667. @Test
  668. public void testDeletionOnMasterConflict() throws Exception {
  669. try (Git git = new Git(db)) {
  670. writeTrashFile("a", "1\na\n3\n");
  671. writeTrashFile("b", "1\nb\n3\n");
  672. git.add().addFilepattern("a").addFilepattern("b").call();
  673. RevCommit initialCommit = git.commit().setMessage("initial").call();
  674. // create side branch and modify "a"
  675. createBranch(initialCommit, "refs/heads/side");
  676. checkoutBranch("refs/heads/side");
  677. writeTrashFile("a", "1\na(side)\n3\n");
  678. git.add().addFilepattern("a").call();
  679. RevCommit secondCommit = git.commit().setMessage("side").call();
  680. // delete a on master to generate conflict
  681. checkoutBranch("refs/heads/master");
  682. git.rm().addFilepattern("a").call();
  683. git.commit().setMessage("main").call();
  684. // merge side with master
  685. MergeResult result = git.merge().include(secondCommit.getId())
  686. .setStrategy(MergeStrategy.RESOLVE).call();
  687. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  688. // result should be 'a' conflicting with workspace content from side
  689. assertTrue(new File(db.getWorkTree(), "a").exists());
  690. assertEquals("1\na(side)\n3\n", read(new File(db.getWorkTree(), "a")));
  691. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  692. }
  693. }
  694. @Test
  695. public void testDeletionOnSideConflict() throws Exception {
  696. try (Git git = new Git(db)) {
  697. writeTrashFile("a", "1\na\n3\n");
  698. writeTrashFile("b", "1\nb\n3\n");
  699. git.add().addFilepattern("a").addFilepattern("b").call();
  700. RevCommit initialCommit = git.commit().setMessage("initial").call();
  701. // create side branch and delete "a"
  702. createBranch(initialCommit, "refs/heads/side");
  703. checkoutBranch("refs/heads/side");
  704. git.rm().addFilepattern("a").call();
  705. RevCommit secondCommit = git.commit().setMessage("side").call();
  706. // update a on master to generate conflict
  707. checkoutBranch("refs/heads/master");
  708. writeTrashFile("a", "1\na(main)\n3\n");
  709. git.add().addFilepattern("a").call();
  710. git.commit().setMessage("main").call();
  711. // merge side with master
  712. MergeResult result = git.merge().include(secondCommit.getId())
  713. .setStrategy(MergeStrategy.RESOLVE).call();
  714. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  715. assertTrue(new File(db.getWorkTree(), "a").exists());
  716. assertEquals("1\na(main)\n3\n", read(new File(db.getWorkTree(), "a")));
  717. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  718. assertEquals(1, result.getConflicts().size());
  719. assertEquals(3, result.getConflicts().get("a")[0].length);
  720. }
  721. }
  722. @Test
  723. public void testModifiedAndRenamed() throws Exception {
  724. // this test is essentially the same as testDeletionOnSideConflict,
  725. // however if once rename support is added this test should result in a
  726. // successful merge instead of a conflict
  727. try (Git git = new Git(db)) {
  728. writeTrashFile("x", "add x");
  729. git.add().addFilepattern("x").call();
  730. RevCommit initial = git.commit().setMessage("add x").call();
  731. createBranch(initial, "refs/heads/d1");
  732. createBranch(initial, "refs/heads/d2");
  733. // rename x to y on d1
  734. checkoutBranch("refs/heads/d1");
  735. new File(db.getWorkTree(), "x")
  736. .renameTo(new File(db.getWorkTree(), "y"));
  737. git.rm().addFilepattern("x").call();
  738. git.add().addFilepattern("y").call();
  739. RevCommit d1Commit = git.commit().setMessage("d1 rename x -> y").call();
  740. checkoutBranch("refs/heads/d2");
  741. writeTrashFile("x", "d2 change");
  742. git.add().addFilepattern("x").call();
  743. RevCommit d2Commit = git.commit().setMessage("d2 change in x").call();
  744. checkoutBranch("refs/heads/master");
  745. MergeResult d1Merge = git.merge().include(d1Commit).call();
  746. assertEquals(MergeResult.MergeStatus.FAST_FORWARD,
  747. d1Merge.getMergeStatus());
  748. MergeResult d2Merge = git.merge().include(d2Commit).call();
  749. assertEquals(MergeResult.MergeStatus.CONFLICTING,
  750. d2Merge.getMergeStatus());
  751. assertEquals(1, d2Merge.getConflicts().size());
  752. assertEquals(3, d2Merge.getConflicts().get("x")[0].length);
  753. }
  754. }
  755. @Test
  756. public void testMergeFailingWithDirtyWorkingTree() throws Exception {
  757. try (Git git = new Git(db)) {
  758. writeTrashFile("a", "1\na\n3\n");
  759. writeTrashFile("b", "1\nb\n3\n");
  760. git.add().addFilepattern("a").addFilepattern("b").call();
  761. RevCommit initialCommit = git.commit().setMessage("initial").call();
  762. createBranch(initialCommit, "refs/heads/side");
  763. checkoutBranch("refs/heads/side");
  764. writeTrashFile("a", "1(side)\na\n3\n");
  765. writeTrashFile("b", "1\nb(side)\n3\n");
  766. git.add().addFilepattern("a").addFilepattern("b").call();
  767. RevCommit secondCommit = git.commit().setMessage("side").call();
  768. assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
  769. checkoutBranch("refs/heads/master");
  770. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  771. writeTrashFile("a", "1\na\n3(main)\n");
  772. git.add().addFilepattern("a").call();
  773. git.commit().setMessage("main").call();
  774. writeTrashFile("a", "--- dirty ---");
  775. MergeResult result = git.merge().include(secondCommit.getId())
  776. .setStrategy(MergeStrategy.RESOLVE).call();
  777. assertEquals(MergeStatus.FAILED, result.getMergeStatus());
  778. assertEquals("--- dirty ---", read(new File(db.getWorkTree(), "a")));
  779. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  780. assertEquals(null, result.getConflicts());
  781. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  782. }
  783. }
  784. @Test
  785. public void testMergeConflictFileFolder() throws Exception {
  786. try (Git git = new Git(db)) {
  787. writeTrashFile("a", "1\na\n3\n");
  788. writeTrashFile("b", "1\nb\n3\n");
  789. git.add().addFilepattern("a").addFilepattern("b").call();
  790. RevCommit initialCommit = git.commit().setMessage("initial").call();
  791. createBranch(initialCommit, "refs/heads/side");
  792. checkoutBranch("refs/heads/side");
  793. writeTrashFile("c/c/c", "1\nc(side)\n3\n");
  794. writeTrashFile("d", "1\nd(side)\n3\n");
  795. git.add().addFilepattern("c/c/c").addFilepattern("d").call();
  796. RevCommit secondCommit = git.commit().setMessage("side").call();
  797. checkoutBranch("refs/heads/master");
  798. writeTrashFile("c", "1\nc(main)\n3\n");
  799. writeTrashFile("d/d/d", "1\nd(main)\n3\n");
  800. git.add().addFilepattern("c").addFilepattern("d/d/d").call();
  801. git.commit().setMessage("main").call();
  802. MergeResult result = git.merge().include(secondCommit.getId())
  803. .setStrategy(MergeStrategy.RESOLVE).call();
  804. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  805. assertEquals("1\na\n3\n", read(new File(db.getWorkTree(), "a")));
  806. assertEquals("1\nb\n3\n", read(new File(db.getWorkTree(), "b")));
  807. assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(), "c")));
  808. assertEquals("1\nd(main)\n3\n", read(new File(db.getWorkTree(), "d/d/d")));
  809. assertEquals(null, result.getConflicts());
  810. assertEquals(RepositoryState.MERGING, db.getRepositoryState());
  811. }
  812. }
  813. @Test
  814. public void testSuccessfulMergeFailsDueToDirtyIndex() throws Exception {
  815. try (Git git = new Git(db)) {
  816. File fileA = writeTrashFile("a", "a");
  817. RevCommit initialCommit = addAllAndCommit(git);
  818. // switch branch
  819. createBranch(initialCommit, "refs/heads/side");
  820. checkoutBranch("refs/heads/side");
  821. // modify file a
  822. write(fileA, "a(side)");
  823. writeTrashFile("b", "b");
  824. RevCommit sideCommit = addAllAndCommit(git);
  825. // switch branch
  826. checkoutBranch("refs/heads/master");
  827. writeTrashFile("c", "c");
  828. addAllAndCommit(git);
  829. // modify and add file a
  830. write(fileA, "a(modified)");
  831. git.add().addFilepattern("a").call();
  832. // do not commit
  833. // get current index state
  834. String indexState = indexState(CONTENT);
  835. // merge
  836. MergeResult result = git.merge().include(sideCommit.getId())
  837. .setStrategy(MergeStrategy.RESOLVE).call();
  838. checkMergeFailedResult(result, MergeFailureReason.DIRTY_INDEX,
  839. indexState, fileA);
  840. }
  841. }
  842. @Test
  843. public void testConflictingMergeFailsDueToDirtyIndex() throws Exception {
  844. try (Git git = new Git(db)) {
  845. File fileA = writeTrashFile("a", "a");
  846. RevCommit initialCommit = addAllAndCommit(git);
  847. // switch branch
  848. createBranch(initialCommit, "refs/heads/side");
  849. checkoutBranch("refs/heads/side");
  850. // modify file a
  851. write(fileA, "a(side)");
  852. writeTrashFile("b", "b");
  853. RevCommit sideCommit = addAllAndCommit(git);
  854. // switch branch
  855. checkoutBranch("refs/heads/master");
  856. // modify file a - this will cause a conflict during merge
  857. write(fileA, "a(master)");
  858. writeTrashFile("c", "c");
  859. addAllAndCommit(git);
  860. // modify and add file a
  861. write(fileA, "a(modified)");
  862. git.add().addFilepattern("a").call();
  863. // do not commit
  864. // get current index state
  865. String indexState = indexState(CONTENT);
  866. // merge
  867. MergeResult result = git.merge().include(sideCommit.getId())
  868. .setStrategy(MergeStrategy.RESOLVE).call();
  869. checkMergeFailedResult(result, MergeFailureReason.DIRTY_INDEX,
  870. indexState, fileA);
  871. }
  872. }
  873. @Test
  874. public void testSuccessfulMergeFailsDueToDirtyWorktree() throws Exception {
  875. try (Git git = new Git(db)) {
  876. File fileA = writeTrashFile("a", "a");
  877. RevCommit initialCommit = addAllAndCommit(git);
  878. // switch branch
  879. createBranch(initialCommit, "refs/heads/side");
  880. checkoutBranch("refs/heads/side");
  881. // modify file a
  882. write(fileA, "a(side)");
  883. writeTrashFile("b", "b");
  884. RevCommit sideCommit = addAllAndCommit(git);
  885. // switch branch
  886. checkoutBranch("refs/heads/master");
  887. writeTrashFile("c", "c");
  888. addAllAndCommit(git);
  889. // modify file a
  890. write(fileA, "a(modified)");
  891. // do not add and commit
  892. // get current index state
  893. String indexState = indexState(CONTENT);
  894. // merge
  895. MergeResult result = git.merge().include(sideCommit.getId())
  896. .setStrategy(MergeStrategy.RESOLVE).call();
  897. checkMergeFailedResult(result, MergeFailureReason.DIRTY_WORKTREE,
  898. indexState, fileA);
  899. }
  900. }
  901. @Test
  902. public void testConflictingMergeFailsDueToDirtyWorktree() throws Exception {
  903. try (Git git = new Git(db)) {
  904. File fileA = writeTrashFile("a", "a");
  905. RevCommit initialCommit = addAllAndCommit(git);
  906. // switch branch
  907. createBranch(initialCommit, "refs/heads/side");
  908. checkoutBranch("refs/heads/side");
  909. // modify file a
  910. write(fileA, "a(side)");
  911. writeTrashFile("b", "b");
  912. RevCommit sideCommit = addAllAndCommit(git);
  913. // switch branch
  914. checkoutBranch("refs/heads/master");
  915. // modify file a - this will cause a conflict during merge
  916. write(fileA, "a(master)");
  917. writeTrashFile("c", "c");
  918. addAllAndCommit(git);
  919. // modify file a
  920. write(fileA, "a(modified)");
  921. // do not add and commit
  922. // get current index state
  923. String indexState = indexState(CONTENT);
  924. // merge
  925. MergeResult result = git.merge().include(sideCommit.getId())
  926. .setStrategy(MergeStrategy.RESOLVE).call();
  927. checkMergeFailedResult(result, MergeFailureReason.DIRTY_WORKTREE,
  928. indexState, fileA);
  929. }
  930. }
  931. @Test
  932. public void testMergeRemovingFolders() throws Exception {
  933. File folder1 = new File(db.getWorkTree(), "folder1");
  934. File folder2 = new File(db.getWorkTree(), "folder2");
  935. FileUtils.mkdir(folder1);
  936. FileUtils.mkdir(folder2);
  937. File file = new File(folder1, "file1.txt");
  938. write(file, "folder1--file1.txt");
  939. file = new File(folder1, "file2.txt");
  940. write(file, "folder1--file2.txt");
  941. file = new File(folder2, "file1.txt");
  942. write(file, "folder--file1.txt");
  943. file = new File(folder2, "file2.txt");
  944. write(file, "folder2--file2.txt");
  945. try (Git git = new Git(db)) {
  946. git.add().addFilepattern(folder1.getName())
  947. .addFilepattern(folder2.getName()).call();
  948. RevCommit commit1 = git.commit().setMessage("adding folders").call();
  949. recursiveDelete(folder1);
  950. recursiveDelete(folder2);
  951. git.rm().addFilepattern("folder1/file1.txt")
  952. .addFilepattern("folder1/file2.txt")
  953. .addFilepattern("folder2/file1.txt")
  954. .addFilepattern("folder2/file2.txt").call();
  955. RevCommit commit2 = git.commit()
  956. .setMessage("removing folders on 'branch'").call();
  957. git.checkout().setName(commit1.name()).call();
  958. MergeResult result = git.merge().include(commit2.getId())
  959. .setStrategy(MergeStrategy.RESOLVE).call();
  960. assertEquals(MergeResult.MergeStatus.FAST_FORWARD,
  961. result.getMergeStatus());
  962. assertEquals(commit2, result.getNewHead());
  963. assertFalse(folder1.exists());
  964. assertFalse(folder2.exists());
  965. }
  966. }
  967. @Test
  968. public void testMergeRemovingFoldersWithoutFastForward() throws Exception {
  969. File folder1 = new File(db.getWorkTree(), "folder1");
  970. File folder2 = new File(db.getWorkTree(), "folder2");
  971. FileUtils.mkdir(folder1);
  972. FileUtils.mkdir(folder2);
  973. File file = new File(folder1, "file1.txt");
  974. write(file, "folder1--file1.txt");
  975. file = new File(folder1, "file2.txt");
  976. write(file, "folder1--file2.txt");
  977. file = new File(folder2, "file1.txt");
  978. write(file, "folder--file1.txt");
  979. file = new File(folder2, "file2.txt");
  980. write(file, "folder2--file2.txt");
  981. try (Git git = new Git(db)) {
  982. git.add().addFilepattern(folder1.getName())
  983. .addFilepattern(folder2.getName()).call();
  984. RevCommit base = git.commit().setMessage("adding folders").call();
  985. recursiveDelete(folder1);
  986. recursiveDelete(folder2);
  987. git.rm().addFilepattern("folder1/file1.txt")
  988. .addFilepattern("folder1/file2.txt")
  989. .addFilepattern("folder2/file1.txt")
  990. .addFilepattern("folder2/file2.txt").call();
  991. RevCommit other = git.commit()
  992. .setMessage("removing folders on 'branch'").call();
  993. git.checkout().setName(base.name()).call();
  994. file = new File(folder2, "file3.txt");
  995. write(file, "folder2--file3.txt");
  996. git.add().addFilepattern(folder2.getName()).call();
  997. git.commit().setMessage("adding another file").call();
  998. MergeResult result = git.merge().include(other.getId())
  999. .setStrategy(MergeStrategy.RESOLVE).call();
  1000. assertEquals(MergeResult.MergeStatus.MERGED,
  1001. result.getMergeStatus());
  1002. assertFalse(folder1.exists());
  1003. }
  1004. }
  1005. @Test
  1006. public void testFileModeMerge() throws Exception {
  1007. // Only Java6
  1008. assumeTrue(FS.DETECTED.supportsExecute());
  1009. try (Git git = new Git(db)) {
  1010. writeTrashFile("mergeableMode", "a");
  1011. setExecutable(git, "mergeableMode", false);
  1012. writeTrashFile("conflictingModeWithBase", "a");
  1013. setExecutable(git, "conflictingModeWithBase", false);
  1014. RevCommit initialCommit = addAllAndCommit(git);
  1015. // switch branch
  1016. createBranch(initialCommit, "refs/heads/side");
  1017. checkoutBranch("refs/heads/side");
  1018. setExecutable(git, "mergeableMode", true);
  1019. writeTrashFile("conflictingModeNoBase", "b");
  1020. setExecutable(git, "conflictingModeNoBase", true);
  1021. RevCommit sideCommit = addAllAndCommit(git);
  1022. // switch branch
  1023. createBranch(initialCommit, "refs/heads/side2");
  1024. checkoutBranch("refs/heads/side2");
  1025. setExecutable(git, "mergeableMode", false);
  1026. assertFalse(new File(git.getRepository().getWorkTree(),
  1027. "conflictingModeNoBase").exists());
  1028. writeTrashFile("conflictingModeNoBase", "b");
  1029. setExecutable(git, "conflictingModeNoBase", false);
  1030. addAllAndCommit(git);
  1031. // merge
  1032. MergeResult result = git.merge().include(sideCommit.getId())
  1033. .setStrategy(MergeStrategy.RESOLVE).call();
  1034. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  1035. assertTrue(canExecute(git, "mergeableMode"));
  1036. assertFalse(canExecute(git, "conflictingModeNoBase"));
  1037. }
  1038. }
  1039. @Test
  1040. public void testFileModeMergeWithDirtyWorkTree() throws Exception {
  1041. // Only Java6 (or set x bit in index)
  1042. assumeTrue(FS.DETECTED.supportsExecute());
  1043. try (Git git = new Git(db)) {
  1044. writeTrashFile("mergeableButDirty", "a");
  1045. setExecutable(git, "mergeableButDirty", false);
  1046. RevCommit initialCommit = addAllAndCommit(git);
  1047. // switch branch
  1048. createBranch(initialCommit, "refs/heads/side");
  1049. checkoutBranch("refs/heads/side");
  1050. setExecutable(git, "mergeableButDirty", true);
  1051. RevCommit sideCommit = addAllAndCommit(git);
  1052. // switch branch
  1053. createBranch(initialCommit, "refs/heads/side2");
  1054. checkoutBranch("refs/heads/side2");
  1055. setExecutable(git, "mergeableButDirty", false);
  1056. addAllAndCommit(git);
  1057. writeTrashFile("mergeableButDirty", "b");
  1058. // merge
  1059. MergeResult result = git.merge().include(sideCommit.getId())
  1060. .setStrategy(MergeStrategy.RESOLVE).call();
  1061. assertEquals(MergeStatus.FAILED, result.getMergeStatus());
  1062. assertFalse(canExecute(git, "mergeableButDirty"));
  1063. }
  1064. }
  1065. @Test
  1066. public void testSquashFastForward() throws Exception {
  1067. try (Git git = new Git(db)) {
  1068. writeTrashFile("file1", "file1");
  1069. git.add().addFilepattern("file1").call();
  1070. RevCommit first = git.commit().setMessage("initial commit").call();
  1071. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1072. createBranch(first, "refs/heads/branch1");
  1073. checkoutBranch("refs/heads/branch1");
  1074. writeTrashFile("file2", "file2");
  1075. git.add().addFilepattern("file2").call();
  1076. RevCommit second = git.commit().setMessage("second commit").call();
  1077. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1078. writeTrashFile("file3", "file3");
  1079. git.add().addFilepattern("file3").call();
  1080. RevCommit third = git.commit().setMessage("third commit").call();
  1081. assertTrue(new File(db.getWorkTree(), "file3").exists());
  1082. checkoutBranch("refs/heads/master");
  1083. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1084. assertFalse(new File(db.getWorkTree(), "file2").exists());
  1085. assertFalse(new File(db.getWorkTree(), "file3").exists());
  1086. MergeResult result = git.merge()
  1087. .include(db.exactRef("refs/heads/branch1"))
  1088. .setSquash(true)
  1089. .call();
  1090. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1091. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1092. assertTrue(new File(db.getWorkTree(), "file3").exists());
  1093. assertEquals(MergeResult.MergeStatus.FAST_FORWARD_SQUASHED,
  1094. result.getMergeStatus());
  1095. assertEquals(first, result.getNewHead()); // HEAD didn't move
  1096. assertEquals(first, db.resolve(Constants.HEAD + "^{commit}"));
  1097. assertEquals(
  1098. "Squashed commit of the following:\n\ncommit "
  1099. + third.getName()
  1100. + "\nAuthor: "
  1101. + third.getAuthorIdent().getName()
  1102. + " <"
  1103. + third.getAuthorIdent().getEmailAddress()
  1104. + ">\nDate: "
  1105. + dateFormatter.formatDate(third
  1106. .getAuthorIdent())
  1107. + "\n\n\tthird commit\n\ncommit "
  1108. + second.getName()
  1109. + "\nAuthor: "
  1110. + second.getAuthorIdent().getName()
  1111. + " <"
  1112. + second.getAuthorIdent().getEmailAddress()
  1113. + ">\nDate: "
  1114. + dateFormatter.formatDate(second
  1115. .getAuthorIdent()) + "\n\n\tsecond commit\n",
  1116. db.readSquashCommitMsg());
  1117. assertNull(db.readMergeCommitMsg());
  1118. Status stat = git.status().call();
  1119. assertEquals(Sets.of("file2", "file3"), stat.getAdded());
  1120. }
  1121. }
  1122. @Test
  1123. public void testSquashMerge() throws Exception {
  1124. try (Git git = new Git(db)) {
  1125. writeTrashFile("file1", "file1");
  1126. git.add().addFilepattern("file1").call();
  1127. RevCommit first = git.commit().setMessage("initial commit").call();
  1128. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1129. createBranch(first, "refs/heads/branch1");
  1130. writeTrashFile("file2", "file2");
  1131. git.add().addFilepattern("file2").call();
  1132. RevCommit second = git.commit().setMessage("second commit").call();
  1133. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1134. checkoutBranch("refs/heads/branch1");
  1135. writeTrashFile("file3", "file3");
  1136. git.add().addFilepattern("file3").call();
  1137. RevCommit third = git.commit().setMessage("third commit").call();
  1138. assertTrue(new File(db.getWorkTree(), "file3").exists());
  1139. checkoutBranch("refs/heads/master");
  1140. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1141. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1142. assertFalse(new File(db.getWorkTree(), "file3").exists());
  1143. MergeResult result = git.merge()
  1144. .include(db.exactRef("refs/heads/branch1"))
  1145. .setSquash(true)
  1146. .call();
  1147. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1148. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1149. assertTrue(new File(db.getWorkTree(), "file3").exists());
  1150. assertEquals(MergeResult.MergeStatus.MERGED_SQUASHED,
  1151. result.getMergeStatus());
  1152. assertEquals(second, result.getNewHead()); // HEAD didn't move
  1153. assertEquals(second, db.resolve(Constants.HEAD + "^{commit}"));
  1154. assertEquals(
  1155. "Squashed commit of the following:\n\ncommit "
  1156. + third.getName()
  1157. + "\nAuthor: "
  1158. + third.getAuthorIdent().getName()
  1159. + " <"
  1160. + third.getAuthorIdent().getEmailAddress()
  1161. + ">\nDate: "
  1162. + dateFormatter.formatDate(third
  1163. .getAuthorIdent()) + "\n\n\tthird commit\n",
  1164. db.readSquashCommitMsg());
  1165. assertNull(db.readMergeCommitMsg());
  1166. Status stat = git.status().call();
  1167. assertEquals(Sets.of("file3"), stat.getAdded());
  1168. }
  1169. }
  1170. @Test
  1171. public void testSquashMergeConflict() throws Exception {
  1172. try (Git git = new Git(db)) {
  1173. writeTrashFile("file1", "file1");
  1174. git.add().addFilepattern("file1").call();
  1175. RevCommit first = git.commit().setMessage("initial commit").call();
  1176. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1177. createBranch(first, "refs/heads/branch1");
  1178. writeTrashFile("file2", "master");
  1179. git.add().addFilepattern("file2").call();
  1180. RevCommit second = git.commit().setMessage("second commit").call();
  1181. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1182. checkoutBranch("refs/heads/branch1");
  1183. writeTrashFile("file2", "branch");
  1184. git.add().addFilepattern("file2").call();
  1185. RevCommit third = git.commit().setMessage("third commit").call();
  1186. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1187. checkoutBranch("refs/heads/master");
  1188. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1189. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1190. MergeResult result = git.merge()
  1191. .include(db.exactRef("refs/heads/branch1"))
  1192. .setSquash(true)
  1193. .call();
  1194. assertTrue(new File(db.getWorkTree(), "file1").exists());
  1195. assertTrue(new File(db.getWorkTree(), "file2").exists());
  1196. assertEquals(MergeResult.MergeStatus.CONFLICTING,
  1197. result.getMergeStatus());
  1198. assertNull(result.getNewHead());
  1199. assertEquals(second, db.resolve(Constants.HEAD + "^{commit}"));
  1200. assertEquals(
  1201. "Squashed commit of the following:\n\ncommit "
  1202. + third.getName()
  1203. + "\nAuthor: "
  1204. + third.getAuthorIdent().getName()
  1205. + " <"
  1206. + third.getAuthorIdent().getEmailAddress()
  1207. + ">\nDate: "
  1208. + dateFormatter.formatDate(third
  1209. .getAuthorIdent()) + "\n\n\tthird commit\n",
  1210. db.readSquashCommitMsg());
  1211. assertEquals("\nConflicts:\n\tfile2\n", db.readMergeCommitMsg());
  1212. Status stat = git.status().call();
  1213. assertEquals(Sets.of("file2"), stat.getConflicting());
  1214. }
  1215. }
  1216. @Test
  1217. public void testFastForwardOnly() throws Exception {
  1218. try (Git git = new Git(db)) {
  1219. RevCommit initialCommit = git.commit().setMessage("initial commit")
  1220. .call();
  1221. createBranch(initialCommit, "refs/heads/branch1");
  1222. git.commit().setMessage("second commit").call();
  1223. checkoutBranch("refs/heads/branch1");
  1224. MergeCommand merge = git.merge();
  1225. merge.setFastForward(FastForwardMode.FF_ONLY);
  1226. merge.include(db.exactRef(R_HEADS + MASTER));
  1227. MergeResult result = merge.call();
  1228. assertEquals(MergeStatus.FAST_FORWARD, result.getMergeStatus());
  1229. }
  1230. }
  1231. @Test
  1232. public void testNoFastForward() throws Exception {
  1233. try (Git git = new Git(db)) {
  1234. RevCommit initialCommit = git.commit().setMessage("initial commit")
  1235. .call();
  1236. createBranch(initialCommit, "refs/heads/branch1");
  1237. git.commit().setMessage("second commit").call();
  1238. checkoutBranch("refs/heads/branch1");
  1239. MergeCommand merge = git.merge();
  1240. merge.setFastForward(FastForwardMode.NO_FF);
  1241. merge.include(db.exactRef(R_HEADS + MASTER));
  1242. MergeResult result = merge.call();
  1243. assertEquals(MergeStatus.MERGED, result.getMergeStatus());
  1244. }
  1245. }
  1246. @Test
  1247. public void testNoFastForwardNoCommit() throws Exception {
  1248. // given
  1249. try (Git git = new Git(db)) {
  1250. RevCommit initialCommit = git.commit().setMessage("initial commit")
  1251. .call();
  1252. createBranch(initialCommit, "refs/heads/branch1");
  1253. RevCommit secondCommit = git.commit().setMessage("second commit")
  1254. .call();
  1255. checkoutBranch("refs/heads/branch1");
  1256. // when
  1257. MergeCommand merge = git.merge();
  1258. merge.setFastForward(FastForwardMode.NO_FF);
  1259. merge.include(db.exactRef(R_HEADS + MASTER));
  1260. merge.setCommit(false);
  1261. MergeResult result = merge.call();
  1262. // then
  1263. assertEquals(MergeStatus.MERGED_NOT_COMMITTED, result.getMergeStatus());
  1264. assertEquals(2, result.getMergedCommits().length);
  1265. assertEquals(initialCommit, result.getMergedCommits()[0]);
  1266. assertEquals(secondCommit, result.getMergedCommits()[1]);
  1267. assertNull(result.getNewHead());
  1268. assertEquals(RepositoryState.MERGING_RESOLVED, db.getRepositoryState());
  1269. }
  1270. }
  1271. @Test
  1272. public void testFastForwardOnlyNotPossible() throws Exception {
  1273. try (Git git = new Git(db)) {
  1274. RevCommit initialCommit = git.commit().setMessage("initial commit")
  1275. .call();
  1276. createBranch(initialCommit, "refs/heads/branch1");
  1277. git.commit().setMessage("second commit").call();
  1278. checkoutBranch("refs/heads/branch1");
  1279. writeTrashFile("file1", "branch1");
  1280. git.add().addFilepattern("file").call();
  1281. git.commit().setMessage("second commit on branch1").call();
  1282. MergeCommand merge = git.merge();
  1283. merge.setFastForward(FastForwardMode.FF_ONLY);
  1284. merge.include(db.exactRef(R_HEADS + MASTER));
  1285. MergeResult result = merge.call();
  1286. assertEquals(MergeStatus.ABORTED, result.getMergeStatus());
  1287. }
  1288. }
  1289. @Test
  1290. public void testRecursiveMergeWithConflict() throws Exception {
  1291. TestRepository<Repository> db_t = new TestRepository<>(db);
  1292. BranchBuilder master = db_t.branch("master");
  1293. RevCommit m0 = master.commit().add("f", "1\n2\n3\n4\n5\n6\n7\n8\n9\n")
  1294. .message("m0").create();
  1295. RevCommit m1 = master.commit()
  1296. .add("f", "1-master\n2\n3\n4\n5\n6\n7\n8\n9\n").message("m1")
  1297. .create();
  1298. db_t.getRevWalk().parseCommit(m1);
  1299. BranchBuilder side = db_t.branch("side");
  1300. RevCommit s1 = side.commit().parent(m0)
  1301. .add("f", "1\n2\n3\n4\n5\n6\n7\n8\n9-side\n").message("s1")
  1302. .create();
  1303. RevCommit s2 = side.commit().parent(m1)
  1304. .add("f", "1-master\n2\n3\n4\n5\n6\n7-res(side)\n8\n9-side\n")
  1305. .message("s2(merge)").create();
  1306. master.commit().parent(s1)
  1307. .add("f", "1-master\n2\n3\n4\n5\n6\n7-conflict\n8\n9-side\n")
  1308. .message("m2(merge)").create();
  1309. Git git = Git.wrap(db);
  1310. git.checkout().setName("master").call();
  1311. MergeResult result = git.merge().setStrategy(MergeStrategy.RECURSIVE)
  1312. .include("side", s2).call();
  1313. assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
  1314. }
  1315. @Test
  1316. public void testMergeWithMessageOption() throws Exception {
  1317. try (Git git = new Git(db)) {
  1318. writeTrashFile("a", "1\na\n3\n");
  1319. git.add().addFilepattern("a").call();
  1320. RevCommit initialCommit = git.commit().setMessage("initial").call();
  1321. createBranch(initialCommit, "refs/heads/side");
  1322. checkoutBranch("refs/heads/side");
  1323. writeTrashFile("b", "1\nb\n3\n");
  1324. git.add().addFilepattern("b").call();
  1325. git.commit().setMessage("side").call();
  1326. checkoutBranch("refs/heads/master");
  1327. writeTrashFile("c", "1\nc\n3\n");
  1328. git.add().addFilepattern("c").call();
  1329. git.commit().setMessage("main").call();
  1330. Ref sideBranch = db.exactRef("refs/heads/side");
  1331. git.merge().include(sideBranch).setStrategy(MergeStrategy.RESOLVE)
  1332. .setMessage("user message").call();
  1333. assertNull(db.readMergeCommitMsg());
  1334. Iterator<RevCommit> it = git.log().call().iterator();
  1335. RevCommit newHead = it.next();
  1336. assertEquals("user message", newHead.getFullMessage());
  1337. }
  1338. }
  1339. @Test
  1340. public void testMergeConflictWithMessageOption() throws Exception {
  1341. try (Git git = new Git(db)) {
  1342. writeTrashFile("a", "1\na\n3\n");
  1343. git.add().addFilepattern("a").call();
  1344. RevCommit initialCommit = git.commit().setMessage("initial").call();
  1345. createBranch(initialCommit, "refs/heads/side");
  1346. checkoutBranch("refs/heads/side");
  1347. writeTrashFile("a", "1\na(side)\n3\n");
  1348. git.add().addFilepattern("a").call();
  1349. git.commit().setMessage("side").call();
  1350. checkoutBranch("refs/heads/master");
  1351. writeTrashFile("a", "1\na(main)\n3\n");
  1352. git.add().addFilepattern("a").call();
  1353. git.commit().setMessage("main").call();
  1354. Ref sideBranch = db.exactRef("refs/heads/side");
  1355. git.merge().include(sideBranch).setStrategy(MergeStrategy.RESOLVE)
  1356. .setMessage("user message").call();
  1357. assertEquals("user message\n\nConflicts:\n\ta\n",
  1358. db.readMergeCommitMsg());
  1359. }
  1360. }
  1361. private static void setExecutable(Git git, String path, boolean executable) {
  1362. FS.DETECTED.setExecute(
  1363. new File(git.getRepository().getWorkTree(), path), executable);
  1364. }
  1365. private static boolean canExecute(Git git, String path) {
  1366. return FS.DETECTED.canExecute(new File(git.getRepository()
  1367. .getWorkTree(), path));
  1368. }
  1369. private static RevCommit addAllAndCommit(final Git git) throws Exception {
  1370. git.add().addFilepattern(".").call();
  1371. return git.commit().setMessage("message").call();
  1372. }
  1373. private void checkMergeFailedResult(final MergeResult result,
  1374. final MergeFailureReason reason,
  1375. final String indexState, final File fileA) throws Exception {
  1376. assertEquals(MergeStatus.FAILED, result.getMergeStatus());
  1377. assertEquals(reason, result.getFailingPaths().get("a"));
  1378. assertEquals("a(modified)", read(fileA));
  1379. assertFalse(new File(db.getWorkTree(), "b").exists());
  1380. assertEquals("c", read(new File(db.getWorkTree(), "c")));
  1381. assertEquals(indexState, indexState(CONTENT));
  1382. assertEquals(null, result.getConflicts());
  1383. assertEquals(RepositoryState.SAFE, db.getRepositoryState());
  1384. }
  1385. }