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

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