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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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. /**
  71. * Executes specified git command (with arguments), captures exception and
  72. * returns its message as an array of lines. Throws an AssertionError if no
  73. * exception is thrown.
  74. *
  75. * @param command
  76. * a valid git command line, e.g. "git branch -h"
  77. * @return message contained within the exception
  78. */
  79. private String[] executeExpectingException(String command) {
  80. try {
  81. execute(command);
  82. throw new AssertionError("Expected Die");
  83. } catch (Exception e) {
  84. return e.getMessage().split(System.lineSeparator());
  85. }
  86. }
  87. @Test
  88. public void testCheckoutSelf() throws Exception {
  89. try (Git git = new Git(db)) {
  90. git.commit().setMessage("initial commit").call();
  91. assertStringArrayEquals("Already on 'master'",
  92. execute("git checkout master"));
  93. }
  94. }
  95. @Test
  96. public void testCheckoutBranch() throws Exception {
  97. try (Git git = new Git(db)) {
  98. git.commit().setMessage("initial commit").call();
  99. git.branchCreate().setName("side").call();
  100. assertStringArrayEquals("Switched to branch 'side'",
  101. execute("git checkout side"));
  102. }
  103. }
  104. @Test
  105. public void testCheckoutNewBranch() throws Exception {
  106. try (Git git = new Git(db)) {
  107. git.commit().setMessage("initial commit").call();
  108. assertStringArrayEquals("Switched to a new branch 'side'",
  109. execute("git checkout -b side"));
  110. }
  111. }
  112. @Test
  113. public void testCheckoutNonExistingBranch() throws Exception {
  114. assertStringArrayEquals(
  115. "error: pathspec 'side' did not match any file(s) known to git.",
  116. executeExpectingException("git checkout side"));
  117. }
  118. @Test
  119. public void testCheckoutNewBranchThatAlreadyExists() throws Exception {
  120. try (Git git = new Git(db)) {
  121. git.commit().setMessage("initial commit").call();
  122. assertStringArrayEquals(
  123. "fatal: A branch named 'master' already exists.",
  124. executeUnchecked("git checkout -b master"));
  125. }
  126. }
  127. @Test
  128. public void testCheckoutNewBranchOnBranchToBeBorn() throws Exception {
  129. assertStringArrayEquals("fatal: You are on a branch yet to be born",
  130. executeUnchecked("git checkout -b side"));
  131. }
  132. @Test
  133. public void testCheckoutUnresolvedHead() throws Exception {
  134. assertStringArrayEquals(
  135. "error: pathspec 'HEAD' did not match any file(s) known to git.",
  136. executeExpectingException("git checkout HEAD"));
  137. }
  138. @Test
  139. public void testCheckoutHead() throws Exception {
  140. try (Git git = new Git(db)) {
  141. git.commit().setMessage("initial commit").call();
  142. assertStringArrayEquals("", execute("git checkout HEAD"));
  143. }
  144. }
  145. @Test
  146. public void testCheckoutExistingBranchWithConflict() throws Exception {
  147. try (Git git = new Git(db)) {
  148. writeTrashFile("a", "Hello world a");
  149. git.add().addFilepattern(".").call();
  150. git.commit().setMessage("commit file a").call();
  151. git.branchCreate().setName("branch_1").call();
  152. git.rm().addFilepattern("a").call();
  153. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  154. writeTrashFile("a/b", "Hello world b");
  155. git.add().addFilepattern("a/b").call();
  156. git.commit().setMessage("commit folder a").call();
  157. git.rm().addFilepattern("a").call();
  158. writeTrashFile("a", "New Hello world a");
  159. git.add().addFilepattern(".").call();
  160. String[] execute = executeExpectingException(
  161. "git checkout branch_1");
  162. assertEquals(
  163. "error: Your local changes to the following files would be overwritten by checkout:",
  164. execute[0]);
  165. assertEquals("\ta", execute[1]);
  166. }
  167. }
  168. /**
  169. * Steps:
  170. * <ol>
  171. * <li>Add file 'a' and 'b'
  172. * <li>Commit
  173. * <li>Create branch '1'
  174. * <li>modify file 'a'
  175. * <li>Commit
  176. * <li>Delete file 'a' in the working tree
  177. * <li>Checkout branch '1'
  178. * </ol>
  179. * <p>
  180. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  181. * checkout.
  182. *
  183. * @throws Exception
  184. */
  185. @Test
  186. public void testCheckoutWithMissingWorkingTreeFile() throws Exception {
  187. try (Git git = new Git(db)) {
  188. File fileA = writeTrashFile("a", "Hello world a");
  189. writeTrashFile("b", "Hello world b");
  190. git.add().addFilepattern(".").call();
  191. git.commit().setMessage("add files a & b").call();
  192. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  193. writeTrashFile("a", "b");
  194. git.add().addFilepattern("a").call();
  195. git.commit().setMessage("modify file a").call();
  196. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  197. db.getWorkTree(), "a"), db.getFS());
  198. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  199. FileUtils.delete(fileA);
  200. git.checkout().setName(branch_1.getName()).call();
  201. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  202. db.getFS());
  203. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  204. assertEquals("Hello world a", read(fileA));
  205. }
  206. }
  207. @Test
  208. public void testCheckoutOrphan() throws Exception {
  209. try (Git git = new Git(db)) {
  210. git.commit().setMessage("initial commit").call();
  211. assertStringArrayEquals("Switched to a new branch 'new_branch'",
  212. execute("git checkout --orphan new_branch"));
  213. assertEquals("refs/heads/new_branch",
  214. db.exactRef("HEAD").getTarget().getName());
  215. RevCommit commit = git.commit().setMessage("orphan commit").call();
  216. assertEquals(0, commit.getParentCount());
  217. }
  218. }
  219. /**
  220. * Steps:
  221. * <ol>
  222. * <li>Add file 'b'
  223. * <li>Commit
  224. * <li>Create branch '1'
  225. * <li>Add folder 'a'
  226. * <li>Commit
  227. * <li>Replace folder 'a' by file 'a' in the working tree
  228. * <li>Checkout branch '1'
  229. * </ol>
  230. * <p>
  231. * The checkout has to delete folder but the workingtree contains a dirty
  232. * file at this path. The checkout should fail like in native git.
  233. *
  234. * @throws Exception
  235. */
  236. @Test
  237. public void fileModeTestMissingThenFolderWithFileInWorkingTree()
  238. throws Exception {
  239. try (Git git = new Git(db)) {
  240. writeTrashFile("b", "Hello world b");
  241. git.add().addFilepattern(".").call();
  242. git.commit().setMessage("add file b").call();
  243. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  244. File folderA = new File(db.getWorkTree(), "a");
  245. FileUtils.mkdirs(folderA);
  246. writeTrashFile("a/c", "Hello world c");
  247. git.add().addFilepattern(".").call();
  248. git.commit().setMessage("add folder a").call();
  249. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  250. db.getWorkTree(), "a"), db.getFS());
  251. assertEquals(FileMode.TREE, entry.getMode());
  252. FileUtils.delete(folderA, FileUtils.RECURSIVE);
  253. writeTrashFile("a", "b");
  254. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  255. db.getFS());
  256. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  257. try {
  258. git.checkout().setName(branch_1.getName()).call();
  259. fail("Don't get the expected conflict");
  260. } catch (CheckoutConflictException e) {
  261. assertEquals("[a]", e.getConflictingPaths().toString());
  262. entry = new FileTreeIterator.FileEntry(
  263. new File(db.getWorkTree(), "a"), db.getFS());
  264. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  265. }
  266. }
  267. }
  268. /**
  269. * Steps:
  270. * <ol>
  271. * <li>Add file 'a'
  272. * <li>Commit
  273. * <li>Create branch '1'
  274. * <li>Replace file 'a' by folder 'a'
  275. * <li>Commit
  276. * <li>Delete folder 'a' in the working tree
  277. * <li>Checkout branch '1'
  278. * </ol>
  279. * <p>
  280. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  281. * checkout.
  282. *
  283. * @throws Exception
  284. */
  285. @Test
  286. public void fileModeTestFolderWithMissingInWorkingTree() throws Exception {
  287. try (Git git = new Git(db)) {
  288. writeTrashFile("b", "Hello world b");
  289. writeTrashFile("a", "b");
  290. git.add().addFilepattern(".").call();
  291. git.commit().setMessage("add file b & file a").call();
  292. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  293. git.rm().addFilepattern("a").call();
  294. File folderA = new File(db.getWorkTree(), "a");
  295. FileUtils.mkdirs(folderA);
  296. writeTrashFile("a/c", "Hello world c");
  297. git.add().addFilepattern(".").call();
  298. git.commit().setMessage("add folder a").call();
  299. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  300. db.getWorkTree(), "a"), db.getFS());
  301. assertEquals(FileMode.TREE, entry.getMode());
  302. FileUtils.delete(folderA, FileUtils.RECURSIVE);
  303. git.checkout().setName(branch_1.getName()).call();
  304. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  305. db.getFS());
  306. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  307. }
  308. }
  309. /**
  310. * Steps:
  311. * <ol>
  312. * <li>Add file 'a'
  313. * <li>Commit
  314. * <li>Create branch '1'
  315. * <li>Delete file 'a'
  316. * <li>Commit
  317. * <li>Add folder 'a' in the working tree
  318. * <li>Checkout branch '1'
  319. * </ol>
  320. * <p>
  321. * The checkout command should raise an error. The conflicting paths are 'a'
  322. * and 'a/c'.
  323. *
  324. * @throws Exception
  325. */
  326. @Test
  327. public void fileModeTestMissingWithFolderInWorkingTree() throws Exception {
  328. try (Git git = new Git(db)) {
  329. writeTrashFile("b", "Hello world b");
  330. writeTrashFile("a", "b");
  331. git.add().addFilepattern(".").call();
  332. git.commit().setMessage("add file b & file a").call();
  333. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  334. git.rm().addFilepattern("a").call();
  335. git.commit().setMessage("delete file a").call();
  336. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  337. writeTrashFile("a/c", "Hello world c");
  338. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  339. db.getWorkTree(), "a"), db.getFS());
  340. assertEquals(FileMode.TREE, entry.getMode());
  341. CheckoutConflictException exception = null;
  342. try {
  343. git.checkout().setName(branch_1.getName()).call();
  344. } catch (CheckoutConflictException e) {
  345. exception = e;
  346. }
  347. assertNotNull(exception);
  348. assertEquals(2, exception.getConflictingPaths().size());
  349. assertEquals("a", exception.getConflictingPaths().get(0));
  350. assertEquals("a/c", exception.getConflictingPaths().get(1));
  351. }
  352. }
  353. /**
  354. * Steps:
  355. * <ol>
  356. * <li>Add folder 'a'
  357. * <li>Commit
  358. * <li>Create branch '1'
  359. * <li>Delete folder 'a'
  360. * <li>Commit
  361. * <li>Add file 'a' in the working tree
  362. * <li>Checkout branch '1'
  363. * </ol>
  364. * <p>
  365. * The checkout command should raise an error. The conflicting path is 'a'.
  366. *
  367. * @throws Exception
  368. */
  369. @Test
  370. public void fileModeTestFolderThenMissingWithFileInWorkingTree()
  371. throws Exception {
  372. try (Git git = new Git(db)) {
  373. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  374. writeTrashFile("a/c", "Hello world c");
  375. writeTrashFile("b", "Hello world b");
  376. git.add().addFilepattern(".").call();
  377. RevCommit commit1 = git.commit().setMessage("add folder a & file b")
  378. .call();
  379. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  380. git.rm().addFilepattern("a").call();
  381. RevCommit commit2 = git.commit().setMessage("delete folder a").call();
  382. TreeWalk tw = new TreeWalk(db);
  383. tw.addTree(commit1.getTree());
  384. tw.addTree(commit2.getTree());
  385. List<DiffEntry> scan = DiffEntry.scan(tw);
  386. assertEquals(1, scan.size());
  387. assertEquals(FileMode.MISSING, scan.get(0).getNewMode());
  388. assertEquals(FileMode.TREE, scan.get(0).getOldMode());
  389. writeTrashFile("a", "b");
  390. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  391. db.getWorkTree(), "a"), db.getFS());
  392. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  393. CheckoutConflictException exception = null;
  394. try {
  395. git.checkout().setName(branch_1.getName()).call();
  396. } catch (CheckoutConflictException e) {
  397. exception = e;
  398. }
  399. assertNotNull(exception);
  400. assertEquals(1, exception.getConflictingPaths().size());
  401. assertEquals("a", exception.getConflictingPaths().get(0));
  402. }
  403. }
  404. /**
  405. * Steps:
  406. * <ol>
  407. * <li>Add folder 'a'
  408. * <li>Commit
  409. * <li>Create branch '1'
  410. * <li>Replace folder 'a'by file 'a'
  411. * <li>Commit
  412. * <li>Delete file 'a' in the working tree
  413. * <li>Checkout branch '1'
  414. * </ol>
  415. * <p>
  416. * The working tree should contain 'a' with FileMode.TREE after the
  417. * checkout.
  418. *
  419. * @throws Exception
  420. */
  421. @Test
  422. public void fileModeTestFolderThenFileWithMissingInWorkingTree()
  423. throws Exception {
  424. try (Git git = new Git(db)) {
  425. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  426. writeTrashFile("a/c", "Hello world c");
  427. writeTrashFile("b", "Hello world b");
  428. git.add().addFilepattern(".").call();
  429. git.commit().setMessage("add folder a & file b").call();
  430. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  431. git.rm().addFilepattern("a").call();
  432. File fileA = new File(db.getWorkTree(), "a");
  433. writeTrashFile("a", "b");
  434. git.add().addFilepattern("a").call();
  435. git.commit().setMessage("add file a").call();
  436. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  437. db.getWorkTree(), "a"), db.getFS());
  438. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  439. FileUtils.delete(fileA);
  440. git.checkout().setName(branch_1.getName()).call();
  441. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  442. db.getFS());
  443. assertEquals(FileMode.TREE, entry.getMode());
  444. }
  445. }
  446. /**
  447. * Steps:
  448. * <ol>
  449. * <li>Add file 'a'
  450. * <li>Commit
  451. * <li>Create branch '1'
  452. * <li>Modify file 'a'
  453. * <li>Commit
  454. * <li>Delete file 'a' and replace by folder 'a' in the working tree and
  455. * index
  456. * <li>Checkout branch '1'
  457. * </ol>
  458. * <p>
  459. * The checkout command should raise an error. The conflicting path is 'a'.
  460. *
  461. * @throws Exception
  462. */
  463. @Test
  464. public void fileModeTestFileThenFileWithFolderInIndex() throws Exception {
  465. try (Git git = new Git(db)) {
  466. writeTrashFile("a", "Hello world a");
  467. writeTrashFile("b", "Hello world b");
  468. git.add().addFilepattern(".").call();
  469. git.commit().setMessage("add files a & b").call();
  470. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  471. writeTrashFile("a", "b");
  472. git.add().addFilepattern("a").call();
  473. git.commit().setMessage("add file a").call();
  474. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  475. db.getWorkTree(), "a"), db.getFS());
  476. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  477. git.rm().addFilepattern("a").call();
  478. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  479. writeTrashFile("a/c", "Hello world c");
  480. git.add().addFilepattern(".").call();
  481. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  482. db.getFS());
  483. assertEquals(FileMode.TREE, entry.getMode());
  484. CheckoutConflictException exception = null;
  485. try {
  486. git.checkout().setName(branch_1.getName()).call();
  487. } catch (CheckoutConflictException e) {
  488. exception = e;
  489. }
  490. assertNotNull(exception);
  491. assertEquals(1, exception.getConflictingPaths().size());
  492. assertEquals("a", exception.getConflictingPaths().get(0));
  493. }
  494. }
  495. /**
  496. * Steps:
  497. * <ol>
  498. * <li>Add file 'a'
  499. * <li>Commit
  500. * <li>Create branch '1'
  501. * <li>Modify file 'a'
  502. * <li>Commit
  503. * <li>Delete file 'a' and replace by folder 'a' in the working tree and
  504. * index
  505. * <li>Checkout branch '1'
  506. * </ol>
  507. * <p>
  508. * The checkout command should raise an error. The conflicting paths are 'a'
  509. * and 'a/c'.
  510. *
  511. * @throws Exception
  512. */
  513. @Test
  514. public void fileModeTestFileWithFolderInIndex() throws Exception {
  515. try (Git git = new Git(db)) {
  516. writeTrashFile("b", "Hello world b");
  517. writeTrashFile("a", "b");
  518. git.add().addFilepattern(".").call();
  519. git.commit().setMessage("add file b & file a").call();
  520. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  521. git.rm().addFilepattern("a").call();
  522. writeTrashFile("a", "Hello world a");
  523. git.add().addFilepattern("a").call();
  524. git.commit().setMessage("add file a").call();
  525. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  526. db.getWorkTree(), "a"), db.getFS());
  527. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  528. git.rm().addFilepattern("a").call();
  529. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  530. writeTrashFile("a/c", "Hello world c");
  531. git.add().addFilepattern(".").call();
  532. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  533. db.getFS());
  534. assertEquals(FileMode.TREE, entry.getMode());
  535. CheckoutConflictException exception = null;
  536. try {
  537. git.checkout().setName(branch_1.getName()).call();
  538. } catch (CheckoutConflictException e) {
  539. exception = e;
  540. }
  541. assertNotNull(exception);
  542. assertEquals(1, exception.getConflictingPaths().size());
  543. assertEquals("a", exception.getConflictingPaths().get(0));
  544. // TODO: ideally we'd like to get two paths from this exception
  545. // assertEquals(2, exception.getConflictingPaths().size());
  546. // assertEquals("a", exception.getConflictingPaths().get(0));
  547. // assertEquals("a/c", exception.getConflictingPaths().get(1));
  548. }
  549. }
  550. @Test
  551. public void testCheckoutPath() throws Exception {
  552. try (Git git = new Git(db)) {
  553. writeTrashFile("a", "Hello world a");
  554. git.add().addFilepattern(".").call();
  555. git.commit().setMessage("commit file a").call();
  556. git.branchCreate().setName("branch_1").call();
  557. git.checkout().setName("branch_1").call();
  558. File b = writeTrashFile("b", "Hello world b");
  559. git.add().addFilepattern("b").call();
  560. git.commit().setMessage("commit file b").call();
  561. File a = writeTrashFile("a", "New Hello world a");
  562. git.add().addFilepattern(".").call();
  563. git.commit().setMessage("modified a").call();
  564. assertArrayEquals(new String[] { "" },
  565. execute("git checkout HEAD~2 -- a"));
  566. assertEquals("Hello world a", read(a));
  567. assertArrayEquals(new String[] { "* branch_1", " master", "" },
  568. execute("git branch"));
  569. assertEquals("Hello world b", read(b));
  570. }
  571. }
  572. @Test
  573. public void testCheckoutAllPaths() throws Exception {
  574. try (Git git = new Git(db)) {
  575. writeTrashFile("a", "Hello world a");
  576. git.add().addFilepattern(".").call();
  577. git.commit().setMessage("commit file a").call();
  578. git.branchCreate().setName("branch_1").call();
  579. git.checkout().setName("branch_1").call();
  580. File b = writeTrashFile("b", "Hello world b");
  581. git.add().addFilepattern("b").call();
  582. git.commit().setMessage("commit file b").call();
  583. File a = writeTrashFile("a", "New Hello world a");
  584. git.add().addFilepattern(".").call();
  585. git.commit().setMessage("modified a").call();
  586. assertArrayEquals(new String[] { "" },
  587. execute("git checkout HEAD~2 -- ."));
  588. assertEquals("Hello world a", read(a));
  589. assertArrayEquals(new String[] { "* branch_1", " master", "" },
  590. execute("git branch"));
  591. assertEquals("Hello world b", read(b));
  592. }
  593. }
  594. @Test
  595. public void testCheckoutSingleFile() throws Exception {
  596. try (Git git = new Git(db)) {
  597. File a = writeTrashFile("a", "file a");
  598. git.add().addFilepattern(".").call();
  599. git.commit().setMessage("commit file a").call();
  600. writeTrashFile("a", "b");
  601. assertEquals("b", read(a));
  602. assertEquals("[]", Arrays.toString(execute("git checkout -- a")));
  603. assertEquals("file a", read(a));
  604. }
  605. }
  606. @Test
  607. public void testCheckoutLink() throws Exception {
  608. Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
  609. try (Git git = new Git(db)) {
  610. Path path = writeLink("a", "link_a");
  611. assertTrue(Files.isSymbolicLink(path));
  612. git.add().addFilepattern(".").call();
  613. git.commit().setMessage("commit link a").call();
  614. deleteTrashFile("a");
  615. writeTrashFile("a", "Hello world a");
  616. assertFalse(Files.isSymbolicLink(path));
  617. assertEquals("[]", Arrays.toString(execute("git checkout -- a")));
  618. assertEquals("link_a", FileUtils.readSymLink(path.toFile()));
  619. assertTrue(Files.isSymbolicLink(path));
  620. }
  621. }
  622. }