1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.pgm;
44
45 import static org.junit.Assert.assertArrayEquals;
46 import static org.junit.Assert.assertEquals;
47 import static org.junit.Assert.assertFalse;
48 import static org.junit.Assert.assertNotNull;
49 import static org.junit.Assert.assertTrue;
50 import static org.junit.Assert.fail;
51
52 import java.io.File;
53 import java.nio.file.Files;
54 import java.nio.file.Path;
55 import java.util.Arrays;
56 import java.util.List;
57
58 import org.eclipse.jgit.api.Git;
59 import org.eclipse.jgit.api.errors.CheckoutConflictException;
60 import org.eclipse.jgit.diff.DiffEntry;
61 import org.eclipse.jgit.lib.CLIRepositoryTestCase;
62 import org.eclipse.jgit.lib.FileMode;
63 import org.eclipse.jgit.lib.Ref;
64 import org.eclipse.jgit.revwalk.RevCommit;
65 import org.eclipse.jgit.treewalk.FileTreeIterator;
66 import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
67 import org.eclipse.jgit.treewalk.TreeWalk;
68 import org.eclipse.jgit.util.FS;
69 import org.eclipse.jgit.util.FileUtils;
70 import org.junit.Assume;
71 import org.junit.Test;
72
73 public class CheckoutTest extends CLIRepositoryTestCase {
74
75 @Test
76 public void testCheckoutSelf() throws Exception {
77 try (Git git = new Git(db)) {
78 git.commit().setMessage("initial commit").call();
79
80 assertStringArrayEquals("Already on 'master'",
81 execute("git checkout master"));
82 }
83 }
84
85 @Test
86 public void testCheckoutBranch() throws Exception {
87 try (Git git = new Git(db)) {
88 git.commit().setMessage("initial commit").call();
89 git.branchCreate().setName("side").call();
90
91 assertStringArrayEquals("Switched to branch 'side'",
92 execute("git checkout side"));
93 }
94 }
95
96 @Test
97 public void testCheckoutNewBranch() throws Exception {
98 try (Git git = new Git(db)) {
99 git.commit().setMessage("initial commit").call();
100
101 assertStringArrayEquals("Switched to a new branch 'side'",
102 execute("git checkout -b side"));
103 }
104 }
105
106 @Test
107 public void testCheckoutNonExistingBranch() throws Exception {
108 assertStringArrayEquals(
109 "error: pathspec 'side' did not match any file(s) known to git.",
110 execute("git checkout side"));
111 }
112
113 @Test
114 public void testCheckoutNewBranchThatAlreadyExists() throws Exception {
115 try (Git git = new Git(db)) {
116 git.commit().setMessage("initial commit").call();
117
118 assertStringArrayEquals(
119 "fatal: A branch named 'master' already exists.",
120 executeUnchecked("git checkout -b master"));
121 }
122 }
123
124 @Test
125 public void testCheckoutNewBranchOnBranchToBeBorn() throws Exception {
126 assertStringArrayEquals("fatal: You are on a branch yet to be born",
127 executeUnchecked("git checkout -b side"));
128 }
129
130 @Test
131 public void testCheckoutUnresolvedHead() throws Exception {
132 assertStringArrayEquals(
133 "error: pathspec 'HEAD' did not match any file(s) known to git.",
134 execute("git checkout HEAD"));
135 }
136
137 @Test
138 public void testCheckoutHead() throws Exception {
139 try (Git git = new Git(db)) {
140 git.commit().setMessage("initial commit").call();
141
142 assertStringArrayEquals("", execute("git checkout HEAD"));
143 }
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
162 String[] execute = execute("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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 @Test
188 public void testCheckoutWithMissingWorkingTreeFile() throws Exception {
189 try (Git git = new Git(db)) {
190 File fileA = writeTrashFile("a", "Hello world a");
191 writeTrashFile("b", "Hello world b");
192 git.add().addFilepattern(".").call();
193 git.commit().setMessage("add files a & b").call();
194 Ref branch_1 = git.branchCreate().setName("branch_1").call();
195 writeTrashFile("a", "b");
196 git.add().addFilepattern("a").call();
197 git.commit().setMessage("modify file a").call();
198
199 FileEntry entry = new FileTreeIterator.FileEntry(new File(
200 db.getWorkTree(), "a"), db.getFS());
201 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
202
203 FileUtils.delete(fileA);
204
205 git.checkout().setName(branch_1.getName()).call();
206
207 entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
208 db.getFS());
209 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
210 assertEquals("Hello world a", read(fileA));
211 }
212 }
213
214 @Test
215 public void testCheckoutOrphan() throws Exception {
216 try (Git git = new Git(db)) {
217 git.commit().setMessage("initial commit").call();
218
219 assertStringArrayEquals("Switched to a new branch 'new_branch'",
220 execute("git checkout --orphan new_branch"));
221 assertEquals("refs/heads/new_branch",
222 db.exactRef("HEAD").getTarget().getName());
223 RevCommit commit = git.commit().setMessage("orphan commit").call();
224 assertEquals(0, commit.getParentCount());
225 }
226 }
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 @Test
246 public void fileModeTestMissingThenFolderWithFileInWorkingTree()
247 throws Exception {
248 try (Git git = new Git(db)) {
249 writeTrashFile("b", "Hello world b");
250 git.add().addFilepattern(".").call();
251 git.commit().setMessage("add file b").call();
252 Ref branch_1 = git.branchCreate().setName("branch_1").call();
253 File folderA = new File(db.getWorkTree(), "a");
254 FileUtils.mkdirs(folderA);
255 writeTrashFile("a/c", "Hello world c");
256 git.add().addFilepattern(".").call();
257 git.commit().setMessage("add folder a").call();
258
259 FileEntry entry = new FileTreeIterator.FileEntry(new File(
260 db.getWorkTree(), "a"), db.getFS());
261 assertEquals(FileMode.TREE, entry.getMode());
262
263 FileUtils.delete(folderA, FileUtils.RECURSIVE);
264 writeTrashFile("a", "b");
265
266 entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
267 db.getFS());
268 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
269
270 try {
271 git.checkout().setName(branch_1.getName()).call();
272 fail("Don't get the expected conflict");
273 } catch (CheckoutConflictException e) {
274 assertEquals("[a]", e.getConflictingPaths().toString());
275 entry = new FileTreeIterator.FileEntry(
276 new File(db.getWorkTree(), "a"), db.getFS());
277 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
278 }
279 }
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299 @Test
300 public void fileModeTestFolderWithMissingInWorkingTree() throws Exception {
301 try (Git git = new Git(db)) {
302 writeTrashFile("b", "Hello world b");
303 writeTrashFile("a", "b");
304 git.add().addFilepattern(".").call();
305 git.commit().setMessage("add file b & file a").call();
306 Ref branch_1 = git.branchCreate().setName("branch_1").call();
307 git.rm().addFilepattern("a").call();
308 File folderA = new File(db.getWorkTree(), "a");
309 FileUtils.mkdirs(folderA);
310 writeTrashFile("a/c", "Hello world c");
311 git.add().addFilepattern(".").call();
312 git.commit().setMessage("add folder a").call();
313
314 FileEntry entry = new FileTreeIterator.FileEntry(new File(
315 db.getWorkTree(), "a"), db.getFS());
316 assertEquals(FileMode.TREE, entry.getMode());
317
318 FileUtils.delete(folderA, FileUtils.RECURSIVE);
319
320 git.checkout().setName(branch_1.getName()).call();
321
322 entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
323 db.getFS());
324 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
325 }
326 }
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345 @Test
346 public void fileModeTestMissingWithFolderInWorkingTree() throws Exception {
347 try (Git git = new Git(db)) {
348 writeTrashFile("b", "Hello world b");
349 writeTrashFile("a", "b");
350 git.add().addFilepattern(".").call();
351 git.commit().setMessage("add file b & file a").call();
352 Ref branch_1 = git.branchCreate().setName("branch_1").call();
353 git.rm().addFilepattern("a").call();
354 git.commit().setMessage("delete file a").call();
355
356 FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
357 writeTrashFile("a/c", "Hello world c");
358
359 FileEntry entry = new FileTreeIterator.FileEntry(new File(
360 db.getWorkTree(), "a"), db.getFS());
361 assertEquals(FileMode.TREE, entry.getMode());
362
363 CheckoutConflictException exception = null;
364 try {
365 git.checkout().setName(branch_1.getName()).call();
366 } catch (CheckoutConflictException e) {
367 exception = e;
368 }
369 assertNotNull(exception);
370 assertEquals(2, exception.getConflictingPaths().size());
371 assertEquals("a", exception.getConflictingPaths().get(0));
372 assertEquals("a/c", exception.getConflictingPaths().get(1));
373 }
374 }
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392 @Test
393 public void fileModeTestFolderThenMissingWithFileInWorkingTree()
394 throws Exception {
395 try (Git git = new Git(db)) {
396 FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
397 writeTrashFile("a/c", "Hello world c");
398 writeTrashFile("b", "Hello world b");
399 git.add().addFilepattern(".").call();
400 RevCommit commit1 = git.commit().setMessage("add folder a & file b")
401 .call();
402 Ref branch_1 = git.branchCreate().setName("branch_1").call();
403 git.rm().addFilepattern("a").call();
404 RevCommit commit2 = git.commit().setMessage("delete folder a").call();
405
406 TreeWalk tw = new TreeWalk(db);
407 tw.addTree(commit1.getTree());
408 tw.addTree(commit2.getTree());
409 List<DiffEntry> scan = DiffEntry.scan(tw);
410 assertEquals(1, scan.size());
411 assertEquals(FileMode.MISSING, scan.get(0).getNewMode());
412 assertEquals(FileMode.TREE, scan.get(0).getOldMode());
413
414 writeTrashFile("a", "b");
415
416 FileEntry entry = new FileTreeIterator.FileEntry(new File(
417 db.getWorkTree(), "a"), db.getFS());
418 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
419
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
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 @Test
450 public void fileModeTestFolderThenFileWithMissingInWorkingTree()
451 throws Exception {
452 try (Git git = new Git(db)) {
453 FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
454 writeTrashFile("a/c", "Hello world c");
455 writeTrashFile("b", "Hello world b");
456 git.add().addFilepattern(".").call();
457 git.commit().setMessage("add folder a & file b").call();
458 Ref branch_1 = git.branchCreate().setName("branch_1").call();
459 git.rm().addFilepattern("a").call();
460 File fileA = new File(db.getWorkTree(), "a");
461 writeTrashFile("a", "b");
462 git.add().addFilepattern("a").call();
463 git.commit().setMessage("add file a").call();
464
465 FileEntry entry = new FileTreeIterator.FileEntry(new File(
466 db.getWorkTree(), "a"), db.getFS());
467 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
468
469 FileUtils.delete(fileA);
470
471 git.checkout().setName(branch_1.getName()).call();
472
473 entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
474 db.getFS());
475 assertEquals(FileMode.TREE, entry.getMode());
476 }
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495 @Test
496 public void fileModeTestFileThenFileWithFolderInIndex() throws Exception {
497 try (Git git = new Git(db)) {
498 writeTrashFile("a", "Hello world a");
499 writeTrashFile("b", "Hello world b");
500 git.add().addFilepattern(".").call();
501 git.commit().setMessage("add files a & b").call();
502 Ref branch_1 = git.branchCreate().setName("branch_1").call();
503 writeTrashFile("a", "b");
504 git.add().addFilepattern("a").call();
505 git.commit().setMessage("add file a").call();
506
507 FileEntry entry = new FileTreeIterator.FileEntry(new File(
508 db.getWorkTree(), "a"), db.getFS());
509 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
510
511 git.rm().addFilepattern("a").call();
512 FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
513 writeTrashFile("a/c", "Hello world c");
514 git.add().addFilepattern(".").call();
515
516 entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
517 db.getFS());
518 assertEquals(FileMode.TREE, entry.getMode());
519
520 CheckoutConflictException exception = null;
521 try {
522 git.checkout().setName(branch_1.getName()).call();
523 } catch (CheckoutConflictException e) {
524 exception = e;
525 }
526 assertNotNull(exception);
527 assertEquals(1, exception.getConflictingPaths().size());
528 assertEquals("a", exception.getConflictingPaths().get(0));
529 }
530 }
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549 @Test
550 public void fileModeTestFileWithFolderInIndex() throws Exception {
551 try (Git git = new Git(db)) {
552 writeTrashFile("b", "Hello world b");
553 writeTrashFile("a", "b");
554 git.add().addFilepattern(".").call();
555 git.commit().setMessage("add file b & file a").call();
556 Ref branch_1 = git.branchCreate().setName("branch_1").call();
557 git.rm().addFilepattern("a").call();
558 writeTrashFile("a", "Hello world a");
559 git.add().addFilepattern("a").call();
560 git.commit().setMessage("add file a").call();
561
562 FileEntry entry = new FileTreeIterator.FileEntry(new File(
563 db.getWorkTree(), "a"), db.getFS());
564 assertEquals(FileMode.REGULAR_FILE, entry.getMode());
565
566 git.rm().addFilepattern("a").call();
567 FileUtils.mkdirs(new File(db.getWorkTree(), "a"));
568 writeTrashFile("a/c", "Hello world c");
569 git.add().addFilepattern(".").call();
570
571 entry = new FileTreeIterator.FileEntry(new File(db.getWorkTree(), "a"),
572 db.getFS());
573 assertEquals(FileMode.TREE, entry.getMode());
574
575 CheckoutConflictException exception = null;
576 try {
577 git.checkout().setName(branch_1.getName()).call();
578 } catch (CheckoutConflictException e) {
579 exception = e;
580 }
581 assertNotNull(exception);
582 assertEquals(1, exception.getConflictingPaths().size());
583 assertEquals("a", exception.getConflictingPaths().get(0));
584
585
586
587
588
589 }
590 }
591
592 @Test
593 public void testCheckoutPath() throws Exception {
594 try (Git git = new Git(db)) {
595 writeTrashFile("a", "Hello world a");
596 git.add().addFilepattern(".").call();
597 git.commit().setMessage("commit file a").call();
598 git.branchCreate().setName("branch_1").call();
599 git.checkout().setName("branch_1").call();
600 File b = writeTrashFile("b", "Hello world b");
601 git.add().addFilepattern("b").call();
602 git.commit().setMessage("commit file b").call();
603 File a = writeTrashFile("a", "New Hello world a");
604 git.add().addFilepattern(".").call();
605 git.commit().setMessage("modified a").call();
606 assertArrayEquals(new String[] { "" },
607 execute("git checkout HEAD~2 -- a"));
608 assertEquals("Hello world a", read(a));
609 assertArrayEquals(new String[] { "* branch_1", " master", "" },
610 execute("git branch"));
611 assertEquals("Hello world b", read(b));
612 }
613 }
614
615 @Test
616 public void testCheckoutAllPaths() throws Exception {
617 try (Git git = new Git(db)) {
618 writeTrashFile("a", "Hello world a");
619 git.add().addFilepattern(".").call();
620 git.commit().setMessage("commit file a").call();
621 git.branchCreate().setName("branch_1").call();
622 git.checkout().setName("branch_1").call();
623 File b = writeTrashFile("b", "Hello world b");
624 git.add().addFilepattern("b").call();
625 git.commit().setMessage("commit file b").call();
626 File a = writeTrashFile("a", "New Hello world a");
627 git.add().addFilepattern(".").call();
628 git.commit().setMessage("modified a").call();
629 assertArrayEquals(new String[] { "" },
630 execute("git checkout HEAD~2 -- ."));
631 assertEquals("Hello world a", read(a));
632 assertArrayEquals(new String[] { "* branch_1", " master", "" },
633 execute("git branch"));
634 assertEquals("Hello world b", read(b));
635 }
636 }
637
638 @Test
639 public void testCheckoutSingleFile() throws Exception {
640 try (Git git = new Git(db)) {
641 File a = writeTrashFile("a", "file a");
642 git.add().addFilepattern(".").call();
643 git.commit().setMessage("commit file a").call();
644 writeTrashFile("a", "b");
645 assertEquals("b", read(a));
646 assertEquals("[]", Arrays.toString(execute("git checkout -- a")));
647 assertEquals("file a", read(a));
648 }
649 }
650
651 @Test
652 public void testCheckoutLink() throws Exception {
653 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
654 try (Git git = new Git(db)) {
655 Path path = writeLink("a", "link_a");
656 assertTrue(Files.isSymbolicLink(path));
657 git.add().addFilepattern(".").call();
658 git.commit().setMessage("commit link a").call();
659 deleteTrashFile("a");
660 writeTrashFile("a", "Hello world a");
661 assertFalse(Files.isSymbolicLink(path));
662 assertEquals("[]", Arrays.toString(execute("git checkout -- a")));
663 assertEquals("link_a", FileUtils.readSymLink(path.toFile()));
664 assertTrue(Files.isSymbolicLink(path));
665 }
666 }
667 }