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