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