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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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.assertNotNull;
  46. import java.io.File;
  47. import java.util.List;
  48. import org.eclipse.jgit.api.Git;
  49. import org.eclipse.jgit.api.errors.CheckoutConflictException;
  50. import org.eclipse.jgit.diff.DiffEntry;
  51. import org.eclipse.jgit.lib.CLIRepositoryTestCase;
  52. import org.eclipse.jgit.lib.FileMode;
  53. import org.eclipse.jgit.lib.Ref;
  54. import org.eclipse.jgit.revwalk.RevCommit;
  55. import org.eclipse.jgit.treewalk.FileTreeIterator;
  56. import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
  57. import org.eclipse.jgit.treewalk.TreeWalk;
  58. import org.eclipse.jgit.util.FileUtils;
  59. import org.junit.Assert;
  60. import org.junit.Test;
  61. public class CheckoutTest extends CLIRepositoryTestCase {
  62. @Test
  63. public void testCheckoutSelf() throws Exception {
  64. new Git(db).commit().setMessage("initial commit").call();
  65. assertEquals("Already on 'master'", execute("git checkout master"));
  66. }
  67. @Test
  68. public void testCheckoutBranch() throws Exception {
  69. new Git(db).commit().setMessage("initial commit").call();
  70. new Git(db).branchCreate().setName("side").call();
  71. assertEquals("Switched to branch 'side'", execute("git checkout side"));
  72. }
  73. @Test
  74. public void testCheckoutNewBranch() throws Exception {
  75. new Git(db).commit().setMessage("initial commit").call();
  76. assertEquals("Switched to a new branch 'side'",
  77. execute("git checkout -b side"));
  78. }
  79. @Test
  80. public void testCheckoutNonExistingBranch() throws Exception {
  81. assertEquals(
  82. "error: pathspec 'side' did not match any file(s) known to git.",
  83. execute("git checkout side"));
  84. }
  85. @Test
  86. public void testCheckoutNewBranchThatAlreadyExists() throws Exception {
  87. new Git(db).commit().setMessage("initial commit").call();
  88. assertEquals("fatal: A branch named 'master' already exists.",
  89. execute("git checkout -b master"));
  90. }
  91. @Test
  92. public void testCheckoutNewBranchOnBranchToBeBorn() throws Exception {
  93. assertEquals("fatal: You are on a branch yet to be born",
  94. execute("git checkout -b side"));
  95. }
  96. @Test
  97. public void testCheckoutUnresolvedHead() throws Exception {
  98. assertEquals(
  99. "error: pathspec 'HEAD' did not match any file(s) known to git.",
  100. execute("git checkout HEAD"));
  101. }
  102. @Test
  103. public void testCheckoutHead() throws Exception {
  104. new Git(db).commit().setMessage("initial commit").call();
  105. assertEquals("", execute("git checkout HEAD"));
  106. }
  107. @Test
  108. public void testCheckoutExistingBranchWithConflict() throws Exception {
  109. Git git = new Git(db);
  110. writeTrashFile("a", "Hello world a");
  111. git.add().addFilepattern(".").call();
  112. git.commit().setMessage("commit file a").call();
  113. git.branchCreate().setName("branch_1").call();
  114. git.rm().addFilepattern("a").call();
  115. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  116. writeTrashFile("a/b", "Hello world b");
  117. git.add().addFilepattern("a/b").call();
  118. git.commit().setMessage("commit folder a").call();
  119. git.rm().addFilepattern("a").call();
  120. writeTrashFile("a", "New Hello world a");
  121. git.add().addFilepattern(".").call();
  122. String[] execute = execute("git checkout branch_1");
  123. Assert.assertEquals(
  124. "error: Your local changes to the following files would be overwritten by checkout:",
  125. execute[0]);
  126. Assert.assertEquals("\ta", execute[1]);
  127. }
  128. /**
  129. * Steps:
  130. * <ol>
  131. * <li>Add file 'a' and 'b'
  132. * <li>Commit
  133. * <li>Create branch '1'
  134. * <li>modify file 'a'
  135. * <li>Commit
  136. * <li>Delete file 'a' in the working tree
  137. * <li>Checkout branch '1'
  138. * </ol>
  139. * <p>
  140. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  141. * checkout.
  142. *
  143. * @throws Exception
  144. */
  145. @Test
  146. public void testCheckoutWithMissingWorkingTreeFile() throws Exception {
  147. Git git = new Git(db);
  148. File fileA = writeTrashFile("a", "Hello world a");
  149. writeTrashFile("b", "Hello world b");
  150. git.add().addFilepattern(".").call();
  151. git.commit().setMessage("add files a & b").call();
  152. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  153. writeTrashFile("a", "b");
  154. git.add().addFilepattern("a").call();
  155. git.commit().setMessage("modify file a").call();
  156. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  157. db.getWorkTree(), "a"), db.getFS());
  158. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  159. FileUtils.delete(fileA);
  160. git.checkout().setName(branch_1.getName()).call();
  161. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  162. db.getFS());
  163. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  164. assertEquals("Hello world a", read(fileA));
  165. }
  166. /**
  167. * Steps:
  168. * <ol>
  169. * <li>Add file 'b'
  170. * <li>Commit
  171. * <li>Create branch '1'
  172. * <li>Add folder 'a'
  173. * <li>Commit
  174. * <li>Replace folder 'a' by file 'a' in the working tree
  175. * <li>Checkout branch '1'
  176. * </ol>
  177. * <p>
  178. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  179. * checkout.
  180. *
  181. * @throws Exception
  182. */
  183. @Test
  184. public void fileModeTestMissingThenFolderWithFileInWorkingTree()
  185. throws Exception {
  186. Git git = new Git(db);
  187. writeTrashFile("b", "Hello world b");
  188. git.add().addFilepattern(".").call();
  189. git.commit().setMessage("add file b").call();
  190. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  191. File folderA = new File(db.getWorkTree(), "a");
  192. FileUtils.mkdirs(folderA);
  193. writeTrashFile("a/c", "Hello world c");
  194. git.add().addFilepattern(".").call();
  195. git.commit().setMessage("add folder a").call();
  196. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  197. db.getWorkTree(), "a"), db.getFS());
  198. assertEquals(FileMode.TREE, entry.getMode());
  199. FileUtils.delete(folderA, FileUtils.RECURSIVE);
  200. writeTrashFile("a", "b");
  201. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  202. db.getFS());
  203. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  204. git.checkout().setName(branch_1.getName()).call();
  205. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  206. db.getFS());
  207. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  208. }
  209. /**
  210. * Steps:
  211. * <ol>
  212. * <li>Add file 'a'
  213. * <li>Commit
  214. * <li>Create branch '1'
  215. * <li>Replace file 'a' by folder 'a'
  216. * <li>Commit
  217. * <li>Delete folder 'a' in the working tree
  218. * <li>Checkout branch '1'
  219. * </ol>
  220. * <p>
  221. * The working tree should contain 'a' with FileMode.REGULAR_FILE after the
  222. * checkout.
  223. *
  224. * @throws Exception
  225. */
  226. @Test
  227. public void fileModeTestFolderWithMissingInWorkingTree() throws Exception {
  228. Git git = new Git(db);
  229. writeTrashFile("b", "Hello world b");
  230. writeTrashFile("a", "b");
  231. git.add().addFilepattern(".").call();
  232. git.commit().setMessage("add file b & file a").call();
  233. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  234. git.rm().addFilepattern("a").call();
  235. File folderA = new File(db.getWorkTree(), "a");
  236. FileUtils.mkdirs(folderA);
  237. writeTrashFile("a/c", "Hello world c");
  238. git.add().addFilepattern(".").call();
  239. git.commit().setMessage("add folder a").call();
  240. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  241. db.getWorkTree(), "a"), db.getFS());
  242. assertEquals(FileMode.TREE, entry.getMode());
  243. FileUtils.delete(folderA, FileUtils.RECURSIVE);
  244. git.checkout().setName(branch_1.getName()).call();
  245. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  246. db.getFS());
  247. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  248. }
  249. /**
  250. * Steps:
  251. * <ol>
  252. * <li>Add file 'a'
  253. * <li>Commit
  254. * <li>Create branch '1'
  255. * <li>Delete file 'a'
  256. * <li>Commit
  257. * <li>Add folder 'a' in the working tree
  258. * <li>Checkout branch '1'
  259. * </ol>
  260. * <p>
  261. * The checkout command should raise an error. The conflicting paths are 'a'
  262. * and 'a/c'.
  263. *
  264. * @throws Exception
  265. */
  266. @Test
  267. public void fileModeTestMissingWithFolderInWorkingTree() throws Exception {
  268. Git git = new Git(db);
  269. writeTrashFile("b", "Hello world b");
  270. writeTrashFile("a", "b");
  271. git.add().addFilepattern(".").call();
  272. git.commit().setMessage("add file b & file a").call();
  273. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  274. git.rm().addFilepattern("a").call();
  275. git.commit().setMessage("delete file a").call();
  276. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  277. writeTrashFile("a/c", "Hello world c");
  278. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  279. db.getWorkTree(), "a"), db.getFS());
  280. assertEquals(FileMode.TREE, entry.getMode());
  281. CheckoutConflictException exception = null;
  282. try {
  283. git.checkout().setName(branch_1.getName()).call();
  284. } catch (CheckoutConflictException e) {
  285. exception = e;
  286. }
  287. assertNotNull(exception);
  288. assertEquals(2, exception.getConflictingPaths().size());
  289. assertEquals("a", exception.getConflictingPaths().get(0));
  290. assertEquals("a/c", exception.getConflictingPaths().get(1));
  291. }
  292. /**
  293. * Steps:
  294. * <ol>
  295. * <li>Add folder 'a'
  296. * <li>Commit
  297. * <li>Create branch '1'
  298. * <li>Delete folder 'a'
  299. * <li>Commit
  300. * <li>Add file 'a' in the working tree
  301. * <li>Checkout branch '1'
  302. * </ol>
  303. * <p>
  304. * The checkout command should raise an error. The conflicting path is 'a'.
  305. *
  306. * @throws Exception
  307. */
  308. @Test
  309. public void fileModeTestFolderThenMissingWithFileInWorkingTree()
  310. throws Exception {
  311. Git git = new Git(db);
  312. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  313. writeTrashFile("a/c", "Hello world c");
  314. writeTrashFile("b", "Hello world b");
  315. git.add().addFilepattern(".").call();
  316. RevCommit commit1 = git.commit().setMessage("add folder a & file b")
  317. .call();
  318. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  319. git.rm().addFilepattern("a").call();
  320. RevCommit commit2 = git.commit().setMessage("delete folder a").call();
  321. TreeWalk tw = new TreeWalk(db);
  322. tw.addTree(commit1.getTree());
  323. tw.addTree(commit2.getTree());
  324. List<DiffEntry> scan = DiffEntry.scan(tw);
  325. assertEquals(1, scan.size());
  326. assertEquals(FileMode.MISSING, scan.get(0).getNewMode());
  327. assertEquals(FileMode.TREE, scan.get(0).getOldMode());
  328. writeTrashFile("a", "b");
  329. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  330. db.getWorkTree(), "a"), db.getFS());
  331. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  332. CheckoutConflictException exception = null;
  333. try {
  334. git.checkout().setName(branch_1.getName()).call();
  335. } catch (CheckoutConflictException e) {
  336. exception = e;
  337. }
  338. assertNotNull(exception);
  339. assertEquals(1, exception.getConflictingPaths().size());
  340. assertEquals("a", exception.getConflictingPaths().get(0));
  341. }
  342. /**
  343. * Steps:
  344. * <ol>
  345. * <li>Add folder 'a'
  346. * <li>Commit
  347. * <li>Create branch '1'
  348. * <li>Replace folder 'a'by file 'a'
  349. * <li>Commit
  350. * <li>Delete file 'a' in the working tree
  351. * <li>Checkout branch '1'
  352. * </ol>
  353. * <p>
  354. * The working tree should contain 'a' with FileMode.TREE after the
  355. * checkout.
  356. *
  357. * @throws Exception
  358. */
  359. @Test
  360. public void fileModeTestFolderThenFileWithMissingInWorkingTree()
  361. throws Exception {
  362. Git git = new Git(db);
  363. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  364. writeTrashFile("a/c", "Hello world c");
  365. writeTrashFile("b", "Hello world b");
  366. git.add().addFilepattern(".").call();
  367. git.commit().setMessage("add folder a & file b").call();
  368. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  369. git.rm().addFilepattern("a").call();
  370. File fileA = new File(db.getWorkTree(), "a");
  371. writeTrashFile("a", "b");
  372. git.add().addFilepattern("a").call();
  373. git.commit().setMessage("add file a").call();
  374. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  375. db.getWorkTree(), "a"), db.getFS());
  376. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  377. FileUtils.delete(fileA);
  378. git.checkout().setName(branch_1.getName()).call();
  379. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  380. db.getFS());
  381. assertEquals(FileMode.TREE, entry.getMode());
  382. }
  383. /**
  384. * Steps:
  385. * <ol>
  386. * <li>Add file 'a'
  387. * <li>Commit
  388. * <li>Create branch '1'
  389. * <li>Modify file 'a'
  390. * <li>Commit
  391. * <li>Delete file 'a' & replace by folder 'a' in the working tree & index
  392. * <li>Checkout branch '1'
  393. * </ol>
  394. * <p>
  395. * The checkout command should raise an error. The conflicting path is 'a'.
  396. *
  397. * @throws Exception
  398. */
  399. @Test
  400. public void fileModeTestFileThenFileWithFolderInIndex() throws Exception {
  401. Git git = new Git(db);
  402. writeTrashFile("a", "Hello world a");
  403. writeTrashFile("b", "Hello world b");
  404. git.add().addFilepattern(".").call();
  405. git.commit().setMessage("add files a & b").call();
  406. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  407. writeTrashFile("a", "b");
  408. git.add().addFilepattern("a").call();
  409. git.commit().setMessage("add file a").call();
  410. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  411. db.getWorkTree(), "a"), db.getFS());
  412. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  413. git.rm().addFilepattern("a").call();
  414. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  415. writeTrashFile("a/c", "Hello world c");
  416. git.add().addFilepattern(".").call();
  417. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  418. db.getFS());
  419. assertEquals(FileMode.TREE, entry.getMode());
  420. CheckoutConflictException exception = null;
  421. try {
  422. git.checkout().setName(branch_1.getName()).call();
  423. } catch (CheckoutConflictException e) {
  424. exception = e;
  425. }
  426. assertNotNull(exception);
  427. assertEquals(1, exception.getConflictingPaths().size());
  428. assertEquals("a", exception.getConflictingPaths().get(0));
  429. }
  430. /**
  431. * Steps:
  432. * <ol>
  433. * <li>Add file 'a'
  434. * <li>Commit
  435. * <li>Create branch '1'
  436. * <li>Modify file 'a'
  437. * <li>Commit
  438. * <li>Delete file 'a' & replace by folder 'a' in the working tree & index
  439. * <li>Checkout branch '1'
  440. * </ol>
  441. * <p>
  442. * The checkout command should raise an error. The conflicting paths are 'a'
  443. * and 'a/c'.
  444. *
  445. * @throws Exception
  446. */
  447. @Test
  448. public void fileModeTestFileWithFolderInIndex() throws Exception {
  449. Git git = new Git(db);
  450. writeTrashFile("b", "Hello world b");
  451. writeTrashFile("a", "b");
  452. git.add().addFilepattern(".").call();
  453. git.commit().setMessage("add file b & file a").call();
  454. Ref branch_1 = git.branchCreate().setName("branch_1").call();
  455. git.rm().addFilepattern("a").call();
  456. writeTrashFile("a", "Hello world a");
  457. git.add().addFilepattern("a").call();
  458. git.commit().setMessage("add file a").call();
  459. FileEntry entry = new FileTreeIterator.FileEntry(new File(
  460. db.getWorkTree(), "a"), db.getFS());
  461. assertEquals(FileMode.REGULAR_FILE, entry.getMode());
  462. git.rm().addFilepattern("a").call();
  463. FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
  464. writeTrashFile("a/c", "Hello world c");
  465. git.add().addFilepattern(".").call();
  466. entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
  467. db.getFS());
  468. assertEquals(FileMode.TREE, entry.getMode());
  469. CheckoutConflictException exception = null;
  470. try {
  471. git.checkout().setName(branch_1.getName()).call();
  472. } catch (CheckoutConflictException e) {
  473. exception = e;
  474. }
  475. assertNotNull(exception);
  476. assertEquals(1, exception.getConflictingPaths().size());
  477. assertEquals("a", exception.getConflictingPaths().get(0));
  478. // TODO: ideally we'd like to get two paths from this exception
  479. // assertEquals(2, exception.getConflictingPaths().size());
  480. // assertEquals("a", exception.getConflictingPaths().get(0));
  481. // assertEquals("a/c", exception.getConflictingPaths().get(1));
  482. }
  483. static private void assertEquals(Object expected, Object actual) {
  484. Assert.assertEquals(expected, actual);
  485. }
  486. static private void assertEquals(String expected, String[] actual) {
  487. // if there is more than one line, ignore last one if empty
  488. Assert.assertEquals(
  489. 1,
  490. actual.length > 1 && actual[actual.length - 1].equals("") ? actual.length - 1
  491. : actual.length);
  492. Assert.assertEquals(expected, actual[0]);
  493. }
  494. @Test
  495. public void testCheckoutPath() throws Exception {
  496. Git git = new Git(db);
  497. writeTrashFile("a", "Hello world a");
  498. git.add().addFilepattern(".").call();
  499. git.commit().setMessage("commit file a").call();
  500. git.branchCreate().setName("branch_1").call();
  501. git.checkout().setName("branch_1").call();
  502. File b = writeTrashFile("b", "Hello world b");
  503. git.add().addFilepattern("b").call();
  504. git.commit().setMessage("commit file b").call();
  505. File a = writeTrashFile("a", "New Hello world a");
  506. git.add().addFilepattern(".").call();
  507. git.commit().setMessage("modified a").call();
  508. assertArrayEquals(new String[] { "" },
  509. execute("git checkout HEAD~2 -- a"));
  510. assertEquals("Hello world a", read(a));
  511. assertArrayEquals(new String[] { "* branch_1", " master", "" },
  512. execute("git branch"));
  513. assertEquals("Hello world b", read(b));
  514. }
  515. }