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.

CheckoutTest.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /*
  2. * Copyright (C) 2012, IBM Corporation
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.pgm;
  44. import static org.junit.Assert.assertArrayEquals;
  45. import static org.junit.Assert.assertEquals;
  46. import static org.junit.Assert.assertFalse;
  47. import static org.junit.Assert.assertNotNull;
  48. import static org.junit.Assert.assertTrue;
  49. import static org.junit.Assert.fail;
  50. import java.io.File;
  51. import java.nio.file.Files;
  52. import java.nio.file.Path;
  53. import java.util.Arrays;
  54. import java.util.List;
  55. import org.eclipse.jgit.api.Git;
  56. import org.eclipse.jgit.api.errors.CheckoutConflictException;
  57. import org.eclipse.jgit.diff.DiffEntry;
  58. import org.eclipse.jgit.lib.CLIRepositoryTestCase;
  59. import org.eclipse.jgit.lib.FileMode;
  60. import org.eclipse.jgit.lib.Ref;
  61. import org.eclipse.jgit.revwalk.RevCommit;
  62. import org.eclipse.jgit.treewalk.FileTreeIterator;
  63. import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
  64. import org.eclipse.jgit.treewalk.TreeWalk;
  65. import org.eclipse.jgit.util.FS;
  66. import org.eclipse.jgit.util.FileUtils;
  67. import org.junit.Assume;
  68. import org.junit.Test;
  69. public class CheckoutTest extends CLIRepositoryTestCase {
  70. @Test
  71. public void testCheckoutSelf() throws Exception {
  72. try (Git git = new Git(db)) {
  73. git.commit().setMessage("initial commit").call();
  74. assertStringArrayEquals("Already on 'master'",
  75. execute("git checkout master"));
  76. }
  77. }
  78. @Test
  79. public void testCheckoutBranch() throws Exception {
  80. try (Git git = new Git(db)) {
  81. git.commit().setMessage("initial commit").call();
  82. git.branchCreate().setName("side").call();
  83. assertStringArrayEquals("Switched to branch 'side'",
  84. execute("git checkout side"));
  85. }
  86. }
  87. @Test
  88. public void testCheckoutNewBranch() throws Exception {
  89. try (Git git = new Git(db)) {
  90. git.commit().setMessage("initial commit").call();
  91. assertStringArrayEquals("Switched to a new branch 'side'",
  92. execute("git checkout -b side"));
  93. }
  94. }
  95. @Test
  96. public void testCheckoutNonExistingBranch() throws Exception {
  97. assertStringArrayEquals(
  98. "error: pathspec 'side' did not match any file(s) known to git.",
  99. execute("git checkout side"));
  100. }
  101. @Test
  102. public void testCheckoutNewBranchThatAlreadyExists() throws Exception {
  103. try (Git git = new Git(db)) {
  104. git.commit().setMessage("initial commit").call();
  105. assertStringArrayEquals(
  106. "fatal: A branch named 'master' already exists.",
  107. executeUnchecked("git checkout -b master"));
  108. }
  109. }
  110. @Test
  111. public void testCheckoutNewBranchOnBranchToBeBorn() throws Exception {
  112. assertStringArrayEquals("fatal: You are on a branch yet to be born",
  113. executeUnchecked("git checkout -b side"));
  114. }
  115. @Test
  116. public void testCheckoutUnresolvedHead() throws Exception {
  117. assertStringArrayEquals(
  118. "error: pathspec 'HEAD' did not match any file(s) known to git.",
  119. execute("git checkout HEAD"));
  120. }
  121. @Test
  122. public void testCheckoutHead() throws Exception {
  123. try (Git git = new Git(db)) {
  124. git.commit().setMessage("initial commit").call();
  125. assertStringArrayEquals("", execute("git checkout HEAD"));
  126. }
  127. }
  128. @Test
  129. public void testCheckoutExistingBranchWithConflict() throws Exception {
  130. try (Git git = new Git(db)) {
  131. writeTrashFile("a", "Hello world a");
  132. git.add().addFilepattern(".").call();
  133. git.commit().setMessage("commit file a").call();
  134. git.branchCreate().setName("branch_1").call();
  135. git.rm().addFilepattern("a").call();
  136. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  137. writeTrashFile("a/b", "Hello world b");
  138. git.add().addFilepattern("a/b").call();
  139. git.commit().setMessage("commit folder a").call();
  140. git.rm().addFilepattern("a").call();
  141. writeTrashFile("a", "New Hello world a");
  142. git.add().addFilepattern(".").call();
  143. String[] execute = execute("git checkout branch_1");
  144. assertEquals(
  145. "error: Your local changes to the following files would be overwritten by checkout:",
  146. execute[0]);
  147. assertEquals("\ta", execute[1]);
  148. }
  149. }
  150. /**
  151. * Steps:
  152. * <ol>
  153. * <li>Add file 'a' and 'b'
  154. * <li>Commit
  155. * <li>Create branch '1'
  156. * <li>modify file 'a'
  157. * <li>Commit
  158. * <li>Delete file 'a' in the working tree
  159. * <li>Checkout branch '1'
  160. * </ol>
  161. * <p>
  162. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  163. * checkout.
  164. *
  165. * @throws Exception
  166. */
  167. @Test
  168. public void testCheckoutWithMissingWorkingTreeFile() throws Exception {
  169. try (Git git = new Git(db)) {
  170. File fileA = writeTrashFile("a", "Hello world a");
  171. writeTrashFile("b", "Hello world b");
  172. git.add().addFilepattern(".").call();
  173. git.commit().setMessage("add files a & b").call();
  174. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  175. writeTrashFile("a", "b");
  176. git.add().addFilepattern("a").call();
  177. git.commit().setMessage("modify file a").call();
  178. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  179. db.getWorkTree(), "a"), db.getFS());
  180. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  181. FileUtils.delete(fileA);
  182. git.checkout().setName(branch_1.getName()).call();
  183. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  184. db.getFS());
  185. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  186. assertEquals("Hello world a", read(fileA));
  187. }
  188. }
  189. @Test
  190. public void testCheckoutOrphan() throws Exception {
  191. try (Git git = new Git(db)) {
  192. git.commit().setMessage("initial commit").call();
  193. assertStringArrayEquals("Switched to a new branch 'new_branch'",
  194. execute("git checkout --orphan new_branch"));
  195. assertEquals("refs/heads/new_branch",
  196. db.exactRef("HEAD").getTarget().getName());
  197. RevCommit commit = git.commit().setMessage("orphan commit").call();
  198. assertEquals(0, commit.getParentCount());
  199. }
  200. }
  201. /**
  202. * Steps:
  203. * <ol>
  204. * <li>Add file 'b'
  205. * <li>Commit
  206. * <li>Create branch '1'
  207. * <li>Add folder 'a'
  208. * <li>Commit
  209. * <li>Replace folder 'a' by file 'a' in the working tree
  210. * <li>Checkout branch '1'
  211. * </ol>
  212. * <p>
  213. * The checkout has to delete folder but the workingtree contains a dirty
  214. * file at this path. The checkout should fail like in native git.
  215. *
  216. * @throws Exception
  217. */
  218. @Test
  219. public void fileModeTestMissingThenFolderWithFileInWorkingTree()
  220. throws Exception {
  221. try (Git git = new Git(db)) {
  222. writeTrashFile("b", "Hello world b");
  223. git.add().addFilepattern(".").call();
  224. git.commit().setMessage("add file b").call();
  225. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  226. File folderA = new File(db.getWorkTree(), "a");
  227. FileUtils.mkdirs(folderA);
  228. writeTrashFile("a/c", "Hello world c");
  229. git.add().addFilepattern(".").call();
  230. git.commit().setMessage("add folder a").call();
  231. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  232. db.getWorkTree(), "a"), db.getFS());
  233. assertEquals(FileMode.TREE, entry.getMode());
  234. FileUtils.delete(folderA, FileUtils.RECURSIVE);
  235. writeTrashFile("a", "b");
  236. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  237. db.getFS());
  238. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  239. try {
  240. git.checkout().setName(branch_1.getName()).call();
  241. fail("Don't get the expected conflict");
  242. } catch (CheckoutConflictException e) {
  243. assertEquals("[a]", e.getConflictingPaths().toString());
  244. entry = new FileTreeIterator.FileEntry(
  245. new File(db.getWorkTree(), "a"), db.getFS());
  246. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  247. }
  248. }
  249. }
  250. /**
  251. * Steps:
  252. * <ol>
  253. * <li>Add file 'a'
  254. * <li>Commit
  255. * <li>Create branch '1'
  256. * <li>Replace file 'a' by folder 'a'
  257. * <li>Commit
  258. * <li>Delete folder 'a' in the working tree
  259. * <li>Checkout branch '1'
  260. * </ol>
  261. * <p>
  262. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  263. * checkout.
  264. *
  265. * @throws Exception
  266. */
  267. @Test
  268. public void fileModeTestFolderWithMissingInWorkingTree() throws Exception {
  269. try (Git git = new Git(db)) {
  270. writeTrashFile("b", "Hello world b");
  271. writeTrashFile("a", "b");
  272. git.add().addFilepattern(".").call();
  273. git.commit().setMessage("add file b & file a").call();
  274. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  275. git.rm().addFilepattern("a").call();
  276. File folderA = new File(db.getWorkTree(), "a");
  277. FileUtils.mkdirs(folderA);
  278. writeTrashFile("a/c", "Hello world c");
  279. git.add().addFilepattern(".").call();
  280. git.commit().setMessage("add folder a").call();
  281. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  282. db.getWorkTree(), "a"), db.getFS());
  283. assertEquals(FileMode.TREE, entry.getMode());
  284. FileUtils.delete(folderA, FileUtils.RECURSIVE);
  285. git.checkout().setName(branch_1.getName()).call();
  286. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  287. db.getFS());
  288. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  289. }
  290. }
  291. /**
  292. * Steps:
  293. * <ol>
  294. * <li>Add file 'a'
  295. * <li>Commit
  296. * <li>Create branch '1'
  297. * <li>Delete file 'a'
  298. * <li>Commit
  299. * <li>Add folder 'a' in the working tree
  300. * <li>Checkout branch '1'
  301. * </ol>
  302. * <p>
  303. * The checkout command should raise an error. The conflicting paths are 'a'
  304. * and 'a/c'.
  305. *
  306. * @throws Exception
  307. */
  308. @Test
  309. public void fileModeTestMissingWithFolderInWorkingTree() throws Exception {
  310. try (Git git = new Git(db)) {
  311. writeTrashFile("b", "Hello world b");
  312. writeTrashFile("a", "b");
  313. git.add().addFilepattern(".").call();
  314. git.commit().setMessage("add file b & file a").call();
  315. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  316. git.rm().addFilepattern("a").call();
  317. git.commit().setMessage("delete file a").call();
  318. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  319. writeTrashFile("a/c", "Hello world c");
  320. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  321. db.getWorkTree(), "a"), db.getFS());
  322. assertEquals(FileMode.TREE, entry.getMode());
  323. CheckoutConflictException exception = null;
  324. try {
  325. git.checkout().setName(branch_1.getName()).call();
  326. } catch (CheckoutConflictException e) {
  327. exception = e;
  328. }
  329. assertNotNull(exception);
  330. assertEquals(2, exception.getConflictingPaths().size());
  331. assertEquals("a", exception.getConflictingPaths().get(0));
  332. assertEquals("a/c", exception.getConflictingPaths().get(1));
  333. }
  334. }
  335. /**
  336. * Steps:
  337. * <ol>
  338. * <li>Add folder 'a'
  339. * <li>Commit
  340. * <li>Create branch '1'
  341. * <li>Delete folder 'a'
  342. * <li>Commit
  343. * <li>Add file 'a' in the working tree
  344. * <li>Checkout branch '1'
  345. * </ol>
  346. * <p>
  347. * The checkout command should raise an error. The conflicting path is 'a'.
  348. *
  349. * @throws Exception
  350. */
  351. @Test
  352. public void fileModeTestFolderThenMissingWithFileInWorkingTree()
  353. throws Exception {
  354. try (Git git = new Git(db)) {
  355. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  356. writeTrashFile("a/c", "Hello world c");
  357. writeTrashFile("b", "Hello world b");
  358. git.add().addFilepattern(".").call();
  359. RevCommit commit1 = git.commit().setMessage("add folder a & file b")
  360. .call();
  361. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  362. git.rm().addFilepattern("a").call();
  363. RevCommit commit2 = git.commit().setMessage("delete folder a").call();
  364. TreeWalk tw = new TreeWalk(db);
  365. tw.addTree(commit1.getTree());
  366. tw.addTree(commit2.getTree());
  367. List<DiffEntry> scan = DiffEntry.scan(tw);
  368. assertEquals(1, scan.size());
  369. assertEquals(FileMode.MISSING, scan.get(0).getNewMode());
  370. assertEquals(FileMode.TREE, scan.get(0).getOldMode());
  371. writeTrashFile("a", "b");
  372. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  373. db.getWorkTree(), "a"), db.getFS());
  374. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  375. CheckoutConflictException exception = null;
  376. try {
  377. git.checkout().setName(branch_1.getName()).call();
  378. } catch (CheckoutConflictException e) {
  379. exception = e;
  380. }
  381. assertNotNull(exception);
  382. assertEquals(1, exception.getConflictingPaths().size());
  383. assertEquals("a", exception.getConflictingPaths().get(0));
  384. }
  385. }
  386. /**
  387. * Steps:
  388. * <ol>
  389. * <li>Add folder 'a'
  390. * <li>Commit
  391. * <li>Create branch '1'
  392. * <li>Replace folder 'a'by file 'a'
  393. * <li>Commit
  394. * <li>Delete file 'a' in the working tree
  395. * <li>Checkout branch '1'
  396. * </ol>
  397. * <p>
  398. * The working tree should contain 'a' with FileMode.TREE after the
  399. * checkout.
  400. *
  401. * @throws Exception
  402. */
  403. @Test
  404. public void fileModeTestFolderThenFileWithMissingInWorkingTree()
  405. throws Exception {
  406. try (Git git = new Git(db)) {
  407. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  408. writeTrashFile("a/c", "Hello world c");
  409. writeTrashFile("b", "Hello world b");
  410. git.add().addFilepattern(".").call();
  411. git.commit().setMessage("add folder a & file b").call();
  412. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  413. git.rm().addFilepattern("a").call();
  414. File fileA = new File(db.getWorkTree(), "a");
  415. writeTrashFile("a", "b");
  416. git.add().addFilepattern("a").call();
  417. git.commit().setMessage("add file a").call();
  418. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  419. db.getWorkTree(), "a"), db.getFS());
  420. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  421. FileUtils.delete(fileA);
  422. git.checkout().setName(branch_1.getName()).call();
  423. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  424. db.getFS());
  425. assertEquals(FileMode.TREE, entry.getMode());
  426. }
  427. }
  428. /**
  429. * Steps:
  430. * <ol>
  431. * <li>Add file 'a'
  432. * <li>Commit
  433. * <li>Create branch '1'
  434. * <li>Modify file 'a'
  435. * <li>Commit
  436. * <li>Delete file 'a' & replace by folder 'a' in the working tree & index
  437. * <li>Checkout branch '1'
  438. * </ol>
  439. * <p>
  440. * The checkout command should raise an error. The conflicting path is 'a'.
  441. *
  442. * @throws Exception
  443. */
  444. @Test
  445. public void fileModeTestFileThenFileWithFolderInIndex() throws Exception {
  446. try (Git git = new Git(db)) {
  447. writeTrashFile("a", "Hello world a");
  448. writeTrashFile("b", "Hello world b");
  449. git.add().addFilepattern(".").call();
  450. git.commit().setMessage("add files a & b").call();
  451. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  452. writeTrashFile("a", "b");
  453. git.add().addFilepattern("a").call();
  454. git.commit().setMessage("add file a").call();
  455. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  456. db.getWorkTree(), "a"), db.getFS());
  457. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  458. git.rm().addFilepattern("a").call();
  459. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  460. writeTrashFile("a/c", "Hello world c");
  461. git.add().addFilepattern(".").call();
  462. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  463. db.getFS());
  464. assertEquals(FileMode.TREE, entry.getMode());
  465. CheckoutConflictException exception = null;
  466. try {
  467. git.checkout().setName(branch_1.getName()).call();
  468. } catch (CheckoutConflictException e) {
  469. exception = e;
  470. }
  471. assertNotNull(exception);
  472. assertEquals(1, exception.getConflictingPaths().size());
  473. assertEquals("a", exception.getConflictingPaths().get(0));
  474. }
  475. }
  476. /**
  477. * Steps:
  478. * <ol>
  479. * <li>Add file 'a'
  480. * <li>Commit
  481. * <li>Create branch '1'
  482. * <li>Modify file 'a'
  483. * <li>Commit
  484. * <li>Delete file 'a' & replace by folder 'a' in the working tree & index
  485. * <li>Checkout branch '1'
  486. * </ol>
  487. * <p>
  488. * The checkout command should raise an error. The conflicting paths are 'a'
  489. * and 'a/c'.
  490. *
  491. * @throws Exception
  492. */
  493. @Test
  494. public void fileModeTestFileWithFolderInIndex() throws Exception {
  495. try (Git git = new Git(db)) {
  496. writeTrashFile("b", "Hello world b");
  497. writeTrashFile("a", "b");
  498. git.add().addFilepattern(".").call();
  499. git.commit().setMessage("add file b & file a").call();
  500. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  501. git.rm().addFilepattern("a").call();
  502. writeTrashFile("a", "Hello world a");
  503. git.add().addFilepattern("a").call();
  504. git.commit().setMessage("add file a").call();
  505. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  506. db.getWorkTree(), "a"), db.getFS());
  507. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  508. git.rm().addFilepattern("a").call();
  509. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  510. writeTrashFile("a/c", "Hello world c");
  511. git.add().addFilepattern(".").call();
  512. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  513. db.getFS());
  514. assertEquals(FileMode.TREE, entry.getMode());
  515. CheckoutConflictException exception = null;
  516. try {
  517. git.checkout().setName(branch_1.getName()).call();
  518. } catch (CheckoutConflictException e) {
  519. exception = e;
  520. }
  521. assertNotNull(exception);
  522. assertEquals(1, exception.getConflictingPaths().size());
  523. assertEquals("a", exception.getConflictingPaths().get(0));
  524. // TODO: ideally we'd like to get two paths from this exception
  525. // assertEquals(2, exception.getConflictingPaths().size());
  526. // assertEquals("a", exception.getConflictingPaths().get(0));
  527. // assertEquals("a/c", exception.getConflictingPaths().get(1));
  528. }
  529. }
  530. @Test
  531. public void testCheckoutPath() throws Exception {
  532. try (Git git = new Git(db)) {
  533. writeTrashFile("a", "Hello world a");
  534. git.add().addFilepattern(".").call();
  535. git.commit().setMessage("commit file a").call();
  536. git.branchCreate().setName("branch_1").call();
  537. git.checkout().setName("branch_1").call();
  538. File b = writeTrashFile("b", "Hello world b");
  539. git.add().addFilepattern("b").call();
  540. git.commit().setMessage("commit file b").call();
  541. File a = writeTrashFile("a", "New Hello world a");
  542. git.add().addFilepattern(".").call();
  543. git.commit().setMessage("modified a").call();
  544. assertArrayEquals(new String[] { "" },
  545. execute("git checkout HEAD~2 -- a"));
  546. assertEquals("Hello world a", read(a));
  547. assertArrayEquals(new String[] { "* branch_1", " master", "" },
  548. execute("git branch"));
  549. assertEquals("Hello world b", read(b));
  550. }
  551. }
  552. @Test
  553. public void testCheckoutAllPaths() throws Exception {
  554. try (Git git = new Git(db)) {
  555. writeTrashFile("a", "Hello world a");
  556. git.add().addFilepattern(".").call();
  557. git.commit().setMessage("commit file a").call();
  558. git.branchCreate().setName("branch_1").call();
  559. git.checkout().setName("branch_1").call();
  560. File b = writeTrashFile("b", "Hello world b");
  561. git.add().addFilepattern("b").call();
  562. git.commit().setMessage("commit file b").call();
  563. File a = writeTrashFile("a", "New Hello world a");
  564. git.add().addFilepattern(".").call();
  565. git.commit().setMessage("modified a").call();
  566. assertArrayEquals(new String[] { "" },
  567. execute("git checkout HEAD~2 -- ."));
  568. assertEquals("Hello world a", read(a));
  569. assertArrayEquals(new String[] { "* branch_1", " master", "" },
  570. execute("git branch"));
  571. assertEquals("Hello world b", read(b));
  572. }
  573. }
  574. @Test
  575. public void testCheckoutSingleFile() throws Exception {
  576. try (Git git = new Git(db)) {
  577. File a = writeTrashFile("a", "file a");
  578. git.add().addFilepattern(".").call();
  579. git.commit().setMessage("commit file a").call();
  580. writeTrashFile("a", "b");
  581. assertEquals("b", read(a));
  582. assertEquals("[]", Arrays.toString(execute("git checkout -- a")));
  583. assertEquals("file a", read(a));
  584. }
  585. }
  586. @Test
  587. public void testCheckoutLink() throws Exception {
  588. Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
  589. try (Git git = new Git(db)) {
  590. Path path = writeLink("a", "link_a");
  591. assertTrue(Files.isSymbolicLink(path));
  592. git.add().addFilepattern(".").call();
  593. git.commit().setMessage("commit link a").call();
  594. deleteTrashFile("a");
  595. writeTrashFile("a", "Hello world a");
  596. assertFalse(Files.isSymbolicLink(path));
  597. assertEquals("[]", Arrays.toString(execute("git checkout -- a")));
  598. assertEquals("link_a", FileUtils.readSymLink(path.toFile()));
  599. assertTrue(Files.isSymbolicLink(path));
  600. }
  601. }
  602. }