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
44 package org.eclipse.jgit.api;
45
46 import static org.eclipse.jgit.lib.Constants.MASTER;
47 import static org.eclipse.jgit.lib.Constants.R_HEADS;
48 import static org.hamcrest.CoreMatchers.is;
49 import static org.hamcrest.MatcherAssert.assertThat;
50 import static org.junit.Assert.assertEquals;
51 import static org.junit.Assert.assertFalse;
52 import static org.junit.Assert.assertNotNull;
53 import static org.junit.Assert.assertNull;
54 import static org.junit.Assert.assertSame;
55 import static org.junit.Assert.assertTrue;
56 import static org.junit.Assert.fail;
57
58 import java.io.File;
59 import java.io.FileInputStream;
60 import java.io.IOException;
61 import java.net.MalformedURLException;
62 import java.net.URISyntaxException;
63
64 import org.eclipse.jgit.api.CheckoutResult.Status;
65 import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
66 import org.eclipse.jgit.api.errors.GitAPIException;
67 import org.eclipse.jgit.api.errors.InvalidRefNameException;
68 import org.eclipse.jgit.api.errors.InvalidRemoteException;
69 import org.eclipse.jgit.api.errors.JGitInternalException;
70 import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
71 import org.eclipse.jgit.api.errors.RefNotFoundException;
72 import org.eclipse.jgit.api.errors.TransportException;
73 import org.eclipse.jgit.dircache.DirCache;
74 import org.eclipse.jgit.dircache.DirCacheEntry;
75 import org.eclipse.jgit.junit.JGitTestUtil;
76 import org.eclipse.jgit.junit.RepositoryTestCase;
77 import org.eclipse.jgit.lfs.BuiltinLFS;
78 import org.eclipse.jgit.lib.ConfigConstants;
79 import org.eclipse.jgit.lib.Constants;
80 import org.eclipse.jgit.lib.Ref;
81 import org.eclipse.jgit.lib.RefUpdate;
82 import org.eclipse.jgit.lib.Repository;
83 import org.eclipse.jgit.lib.Sets;
84 import org.eclipse.jgit.lib.StoredConfig;
85 import org.eclipse.jgit.revwalk.RevCommit;
86 import org.eclipse.jgit.storage.file.FileBasedConfig;
87 import org.eclipse.jgit.transport.RemoteConfig;
88 import org.eclipse.jgit.transport.URIish;
89 import org.eclipse.jgit.util.FileUtils;
90 import org.eclipse.jgit.util.SystemReader;
91 import org.junit.Before;
92 import org.junit.Test;
93
94 public class CheckoutCommandTest extends RepositoryTestCase {
95 private Git git;
96
97 RevCommit initialCommit;
98
99 RevCommit secondCommit;
100
101 @Override
102 @Before
103 public void setUp() throws Exception {
104 BuiltinLFS.register();
105 super.setUp();
106 git = new Git(db);
107
108 writeTrashFile("Test.txt", "Hello world");
109 git.add().addFilepattern("Test.txt").call();
110 initialCommit = git.commit().setMessage("Initial commit").call();
111
112
113 git.branchCreate().setName("test").call();
114 RefUpdate rup = db.updateRef(Constants.HEAD);
115 rup.link("refs/heads/test");
116
117
118 writeTrashFile("Test.txt", "Some change");
119 git.add().addFilepattern("Test.txt").call();
120 secondCommit = git.commit().setMessage("Second commit").call();
121 }
122
123 @Test
124 public void testSimpleCheckout() throws Exception {
125 git.checkout().setName("test").call();
126 }
127
128 @Test
129 public void testCheckout() throws Exception {
130 git.checkout().setName("test").call();
131 assertEquals("[Test.txt, mode:100644, content:Some change]",
132 indexState(CONTENT));
133 Ref result = git.checkout().setName("master").call();
134 assertEquals("[Test.txt, mode:100644, content:Hello world]",
135 indexState(CONTENT));
136 assertEquals("refs/heads/master", result.getName());
137 assertEquals("refs/heads/master", git.getRepository().getFullBranch());
138 }
139
140 @Test
141 public void testCreateBranchOnCheckout() throws Exception {
142 git.checkout().setCreateBranch(true).setName("test2").call();
143 assertNotNull(db.exactRef("refs/heads/test2"));
144 }
145
146 @Test
147 public void testCheckoutToNonExistingBranch() throws GitAPIException {
148 try {
149 git.checkout().setName("badbranch").call();
150 fail("Should have failed");
151 } catch (RefNotFoundException e) {
152
153 }
154 }
155
156 @Test
157 public void testCheckoutWithConflict() {
158 CheckoutCommand co = git.checkout();
159 try {
160 writeTrashFile("Test.txt", "Another change");
161 assertEquals(Status.NOT_TRIED, co.getResult().getStatus());
162 co.setName("master").call();
163 fail("Should have failed");
164 } catch (Exception e) {
165 assertEquals(Status.CONFLICTS, co.getResult().getStatus());
166 assertTrue(co.getResult().getConflictList().contains("Test.txt"));
167 }
168 }
169
170 @Test
171 public void testCheckoutWithNonDeletedFiles() throws Exception {
172 File testFile = writeTrashFile("temp", "");
173 try (FileInputStream fis = new FileInputStream(testFile)) {
174 FileUtils.delete(testFile);
175 return;
176 } catch (IOException e) {
177
178
179 }
180 FileUtils.delete(testFile);
181 CheckoutCommand co = git.checkout();
182
183 testFile = new File(db.getWorkTree(), "Test.txt");
184 assertTrue(testFile.exists());
185 FileUtils.delete(testFile);
186 assertFalse(testFile.exists());
187 git.add().addFilepattern("Test.txt");
188 git.commit().setMessage("Delete Test.txt").setAll(true).call();
189 git.checkout().setName("master").call();
190 assertTrue(testFile.exists());
191
192 try (FileInputStream fis = new FileInputStream(testFile)) {
193 assertEquals(Status.NOT_TRIED, co.getResult().getStatus());
194 co.setName("test").call();
195 assertTrue(testFile.exists());
196 assertEquals(Status.NONDELETED, co.getResult().getStatus());
197 assertTrue(co.getResult().getUndeletedList().contains("Test.txt"));
198 }
199 }
200
201 @Test
202 public void testCheckoutCommit() throws Exception {
203 Ref result = git.checkout().setName(initialCommit.name()).call();
204 assertEquals("[Test.txt, mode:100644, content:Hello world]",
205 indexState(CONTENT));
206 assertNull(result);
207 assertEquals(initialCommit.name(), git.getRepository().getFullBranch());
208 }
209
210 @Test
211 public void testCheckoutLightweightTag() throws Exception {
212 git.tag().setAnnotated(false).setName("test-tag")
213 .setObjectId(initialCommit).call();
214 Ref result = git.checkout().setName("test-tag").call();
215
216 assertNull(result);
217 assertEquals(initialCommit.getId(), db.resolve(Constants.HEAD));
218 assertHeadDetached();
219 }
220
221 @Test
222 public void testCheckoutAnnotatedTag() throws Exception {
223 git.tag().setAnnotated(true).setName("test-tag")
224 .setObjectId(initialCommit).call();
225 Ref result = git.checkout().setName("test-tag").call();
226
227 assertNull(result);
228 assertEquals(initialCommit.getId(), db.resolve(Constants.HEAD));
229 assertHeadDetached();
230 }
231
232 @Test
233 public void testCheckoutRemoteTrackingWithUpstream() throws Exception {
234 Repository db2 = createRepositoryWithRemote();
235
236 Git.wrap(db2).checkout().setCreateBranch(true).setName("test")
237 .setStartPoint("origin/test")
238 .setUpstreamMode(SetupUpstreamMode.TRACK).call();
239
240 assertEquals("refs/heads/test",
241 db2.exactRef(Constants.HEAD).getTarget().getName());
242 StoredConfig config = db2.getConfig();
243 assertEquals("origin", config.getString(
244 ConfigConstants.CONFIG_BRANCH_SECTION, "test",
245 ConfigConstants.CONFIG_KEY_REMOTE));
246 assertEquals("refs/heads/test", config.getString(
247 ConfigConstants.CONFIG_BRANCH_SECTION, "test",
248 ConfigConstants.CONFIG_KEY_MERGE));
249 }
250
251 @Test
252 public void testCheckoutRemoteTrackingWithoutLocalBranch() throws Exception {
253 Repository db2 = createRepositoryWithRemote();
254
255
256
257 Git.wrap(db2).checkout().setName("remotes/origin/test").call();
258 assertEquals("[Test.txt, mode:100644, content:Some change]",
259 indexState(db2, CONTENT));
260 }
261
262
263
264 @Test
265 public void testCheckoutOfFileWithInexistentParentDir() throws Exception {
266 File a = writeTrashFile("dir/a.txt", "A");
267 writeTrashFile("dir/b.txt", "A");
268 git.add().addFilepattern("dir/a.txt").addFilepattern("dir/b.txt")
269 .call();
270 git.commit().setMessage("Added dir").call();
271
272 File dir = new File(db.getWorkTree(), "dir");
273 FileUtils.delete(dir, FileUtils.RECURSIVE);
274
275 git.checkout().addPath("dir/a.txt").call();
276 assertTrue(a.exists());
277 }
278
279 @Test
280 public void testCheckoutOfDirectoryShouldBeRecursive() throws Exception {
281 File a = writeTrashFile("dir/a.txt", "A");
282 File b = writeTrashFile("dir/sub/b.txt", "B");
283 git.add().addFilepattern("dir").call();
284 git.commit().setMessage("Added dir").call();
285
286 write(a, "modified");
287 write(b, "modified");
288 git.checkout().addPath("dir").call();
289
290 assertThat(read(a), is("A"));
291 assertThat(read(b), is("B"));
292 }
293
294 @Test
295 public void testCheckoutAllPaths() throws Exception {
296 File a = writeTrashFile("dir/a.txt", "A");
297 File b = writeTrashFile("dir/sub/b.txt", "B");
298 git.add().addFilepattern("dir").call();
299 git.commit().setMessage("Added dir").call();
300
301 write(a, "modified");
302 write(b, "modified");
303 git.checkout().setAllPaths(true).call();
304
305 assertThat(read(a), is("A"));
306 assertThat(read(b), is("B"));
307 }
308
309 @Test
310 public void testCheckoutWithStartPoint() throws Exception {
311 File a = writeTrashFile("a.txt", "A");
312 git.add().addFilepattern("a.txt").call();
313 RevCommit first = git.commit().setMessage("Added a").call();
314
315 write(a, "other");
316 git.commit().setAll(true).setMessage("Other").call();
317
318 git.checkout().setCreateBranch(true).setName("a")
319 .setStartPoint(first.getId().getName()).call();
320
321 assertThat(read(a), is("A"));
322 }
323
324 @Test
325 public void testCheckoutWithStartPointOnlyCertainFiles() throws Exception {
326 File a = writeTrashFile("a.txt", "A");
327 File b = writeTrashFile("b.txt", "B");
328 git.add().addFilepattern("a.txt").addFilepattern("b.txt").call();
329 RevCommit first = git.commit().setMessage("First").call();
330
331 write(a, "other");
332 write(b, "other");
333 git.commit().setAll(true).setMessage("Other").call();
334
335 git.checkout().setCreateBranch(true).setName("a")
336 .setStartPoint(first.getId().getName()).addPath("a.txt").call();
337
338 assertThat(read(a), is("A"));
339 assertThat(read(b), is("other"));
340 }
341
342 @Test
343 public void testDetachedHeadOnCheckout() throws JGitInternalException,
344 IOException, GitAPIException {
345 CheckoutCommand co = git.checkout();
346 co.setName("master").call();
347
348 String commitId = db.exactRef(R_HEADS + MASTER).getObjectId().name();
349 co = git.checkout();
350 co.setName(commitId).call();
351
352 assertHeadDetached();
353 }
354
355 @Test
356 public void testUpdateSmudgedEntries() throws Exception {
357 git.branchCreate().setName("test2").call();
358 RefUpdate rup = db.updateRef(Constants.HEAD);
359 rup.link("refs/heads/test2");
360
361 File file = new File(db.getWorkTree(), "Test.txt");
362 long size = file.length();
363 long mTime = file.lastModified() - 5000L;
364 assertTrue(file.setLastModified(mTime));
365
366 DirCache cache = DirCache.lock(db.getIndexFile(), db.getFS());
367 DirCacheEntry entry = cache.getEntry("Test.txt");
368 assertNotNull(entry);
369 entry.setLength(0);
370 entry.setLastModified(0);
371 cache.write();
372 assertTrue(cache.commit());
373
374 cache = DirCache.read(db.getIndexFile(), db.getFS());
375 entry = cache.getEntry("Test.txt");
376 assertNotNull(entry);
377 assertEquals(0, entry.getLength());
378 assertEquals(0, entry.getLastModified());
379
380 db.getIndexFile().setLastModified(
381 db.getIndexFile().lastModified() - 5000);
382
383 assertNotNull(git.checkout().setName("test").call());
384
385 cache = DirCache.read(db.getIndexFile(), db.getFS());
386 entry = cache.getEntry("Test.txt");
387 assertNotNull(entry);
388 assertEquals(size, entry.getLength());
389 assertEquals(mTime, entry.getLastModified());
390 }
391
392 @Test
393 public void testCheckoutOrphanBranch() throws Exception {
394 CheckoutCommand co = newOrphanBranchCommand();
395 assertCheckoutRef(co.call());
396
397 File HEAD = new File(trash, ".git/HEAD");
398 String headRef = read(HEAD);
399 assertEquals("ref: refs/heads/orphanbranch\n", headRef);
400 assertEquals(2, trash.list().length);
401
402 File heads = new File(trash, ".git/refs/heads");
403 assertEquals(2, heads.listFiles().length);
404
405 this.assertNoHead();
406 this.assertRepositoryCondition(1);
407 assertEquals(CheckoutResult.NOT_TRIED_RESULT, co.getResult());
408 }
409
410 private Repository createRepositoryWithRemote() throws IOException,
411 URISyntaxException, MalformedURLException, GitAPIException,
412 InvalidRemoteException, TransportException {
413
414 Repository db2 = createWorkRepository();
415 try (Git git2 = new Git(db2)) {
416
417 final StoredConfig config = db2.getConfig();
418 RemoteConfig remoteConfig = new RemoteConfig(config, "origin");
419 URIish uri = new URIish(db.getDirectory().toURI().toURL());
420 remoteConfig.addURI(uri);
421 remoteConfig.update(config);
422 config.save();
423
424
425 git2.fetch().setRemote("origin")
426 .setRefSpecs("+refs/heads/*:refs/remotes/origin/*").call();
427 return db2;
428 }
429 }
430
431 private CheckoutCommand newOrphanBranchCommand() {
432 return git.checkout().setOrphan(true)
433 .setName("orphanbranch");
434 }
435
436 private static void assertCheckoutRef(Ref ref) {
437 assertNotNull(ref);
438 assertEquals("refs/heads/orphanbranch", ref.getTarget().getName());
439 }
440
441 private void assertNoHead() throws IOException {
442 assertNull(db.resolve("HEAD"));
443 }
444
445 private void assertHeadDetached() throws IOException {
446 Ref head = db.exactRef(Constants.HEAD);
447 assertFalse(head.isSymbolic());
448 assertSame(head, head.getTarget());
449 }
450
451 private void assertRepositoryCondition(int files) throws GitAPIException {
452 org.eclipse.jgit.api.Status status = this.git.status().call();
453 assertFalse(status.isClean());
454 assertEquals(files, status.getAdded().size());
455 }
456
457 @Test
458 public void testCreateOrphanBranchWithStartCommit() throws Exception {
459 CheckoutCommand co = newOrphanBranchCommand();
460 Ref ref = co.setStartPoint(initialCommit).call();
461 assertCheckoutRef(ref);
462 assertEquals(2, trash.list().length);
463 this.assertNoHead();
464 this.assertRepositoryCondition(1);
465 }
466
467 @Test
468 public void testCreateOrphanBranchWithStartPoint() throws Exception {
469 CheckoutCommand co = newOrphanBranchCommand();
470 Ref ref = co.setStartPoint("HEAD^").call();
471 assertCheckoutRef(ref);
472
473 assertEquals(2, trash.list().length);
474 this.assertNoHead();
475 this.assertRepositoryCondition(1);
476 }
477
478 @Test
479 public void testInvalidRefName() throws Exception {
480 try {
481 git.checkout().setOrphan(true).setName("../invalidname").call();
482 fail("Should have failed");
483 } catch (InvalidRefNameException e) {
484
485 }
486 }
487
488 @Test
489 public void testNullRefName() throws Exception {
490 try {
491 git.checkout().setOrphan(true).setName(null).call();
492 fail("Should have failed");
493 } catch (InvalidRefNameException e) {
494
495 }
496 }
497
498 @Test
499 public void testAlreadyExists() throws Exception {
500 this.git.checkout().setCreateBranch(true).setName("orphanbranch")
501 .call();
502 this.git.checkout().setName("master").call();
503
504 try {
505 newOrphanBranchCommand().call();
506 fail("Should have failed");
507 } catch (RefAlreadyExistsException e) {
508
509 }
510 }
511
512
513
514 @Test
515 public void testCheckoutAutoCrlfTrue() throws Exception {
516 int nrOfAutoCrlfTestFiles = 200;
517
518 FileBasedConfig c = db.getConfig();
519 c.setString("core", null, "autocrlf", "true");
520 c.save();
521
522 AddCommand add = git.add();
523 for (int i = 100; i < 100 + nrOfAutoCrlfTestFiles; i++) {
524 writeTrashFile("Test_" + i + ".txt", "Hello " + i
525 + " world\nX\nYU\nJK\n");
526 add.addFilepattern("Test_" + i + ".txt");
527 }
528 fsTick(null);
529 add.call();
530 RevCommit c1 = git.commit().setMessage("add some lines").call();
531
532 add = git.add();
533 for (int i = 100; i < 100 + nrOfAutoCrlfTestFiles; i++) {
534 writeTrashFile("Test_" + i + ".txt", "Hello " + i
535 + " world\nX\nY\n");
536 add.addFilepattern("Test_" + i + ".txt");
537 }
538 fsTick(null);
539 add.call();
540 git.commit().setMessage("add more").call();
541
542 git.checkout().setName(c1.getName()).call();
543
544 boolean foundUnsmudged = false;
545 DirCache dc = db.readDirCache();
546 for (int i = 100; i < 100 + nrOfAutoCrlfTestFiles; i++) {
547 DirCacheEntry entry = dc.getEntry(
548 "Test_" + i + ".txt");
549 if (!entry.isSmudged()) {
550 foundUnsmudged = true;
551 assertEquals("unexpected file length in git index", 28,
552 entry.getLength());
553 }
554 }
555 org.junit.Assume.assumeTrue(foundUnsmudged);
556 }
557
558 @Test
559 public void testSmudgeFilter_modifyExisting() throws IOException, GitAPIException {
560 File script = writeTempFile("sed s/o/e/g");
561 StoredConfig config = git.getRepository().getConfig();
562 config.setString("filter", "lfs", "smudge",
563 "sh " + slashify(script.getPath()));
564 config.save();
565
566 writeTrashFile(".gitattributes", "*.txt filter=lfs");
567 git.add().addFilepattern(".gitattributes").call();
568 git.commit().setMessage("add filter").call();
569
570 writeTrashFile("src/a.tmp", "x");
571
572
573 writeTrashFile("src/a.txt", "x\n");
574 git.add().addFilepattern("src/a.tmp").addFilepattern("src/a.txt")
575 .call();
576 RevCommit content1 = git.commit().setMessage("add content").call();
577
578 writeTrashFile("src/a.tmp", "foo");
579 writeTrashFile("src/a.txt", "foo\n");
580 git.add().addFilepattern("src/a.tmp").addFilepattern("src/a.txt")
581 .call();
582 RevCommit content2 = git.commit().setMessage("changed content").call();
583
584 git.checkout().setName(content1.getName()).call();
585 git.checkout().setName(content2.getName()).call();
586
587 assertEquals(
588 "[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
589 indexState(CONTENT));
590 assertEquals(Sets.of("src/a.txt"), git.status().call().getModified());
591 assertEquals("foo", read("src/a.tmp"));
592 assertEquals("fee\n", read("src/a.txt"));
593 }
594
595 @Test
596 public void testSmudgeFilter_createNew()
597 throws IOException, GitAPIException {
598 File script = writeTempFile("sed s/o/e/g");
599 StoredConfig config = git.getRepository().getConfig();
600 config.setString("filter", "lfs", "smudge",
601 "sh " + slashify(script.getPath()));
602 config.save();
603
604 writeTrashFile("foo", "foo");
605 git.add().addFilepattern("foo").call();
606 RevCommit initial = git.commit().setMessage("initial").call();
607
608 writeTrashFile(".gitattributes", "*.txt filter=lfs");
609 git.add().addFilepattern(".gitattributes").call();
610 git.commit().setMessage("add filter").call();
611
612 writeTrashFile("src/a.tmp", "foo");
613
614
615 writeTrashFile("src/a.txt", "foo\n");
616 git.add().addFilepattern("src/a.tmp").addFilepattern("src/a.txt")
617 .call();
618 RevCommit content = git.commit().setMessage("added content").call();
619
620 git.checkout().setName(initial.getName()).call();
621 git.checkout().setName(content.getName()).call();
622
623 assertEquals(
624 "[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
625 indexState(CONTENT));
626 assertEquals("foo", read("src/a.tmp"));
627 assertEquals("fee\n", read("src/a.txt"));
628 }
629
630 @Test
631 public void testSmudgeFilter_deleteFileAndRestoreFromCommit()
632 throws IOException, GitAPIException {
633 File script = writeTempFile("sed s/o/e/g");
634 StoredConfig config = git.getRepository().getConfig();
635 config.setString("filter", "lfs", "smudge",
636 "sh " + slashify(script.getPath()));
637 config.save();
638
639 writeTrashFile("foo", "foo");
640 git.add().addFilepattern("foo").call();
641 git.commit().setMessage("initial").call();
642
643 writeTrashFile(".gitattributes", "*.txt filter=lfs");
644 git.add().addFilepattern(".gitattributes").call();
645 git.commit().setMessage("add filter").call();
646
647 writeTrashFile("src/a.tmp", "foo");
648
649
650 writeTrashFile("src/a.txt", "foo\n");
651 git.add().addFilepattern("src/a.tmp").addFilepattern("src/a.txt")
652 .call();
653 RevCommit content = git.commit().setMessage("added content").call();
654
655 deleteTrashFile("src/a.txt");
656 git.checkout().setStartPoint(content.getName()).addPath("src/a.txt")
657 .call();
658
659 assertEquals(
660 "[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
661 indexState(CONTENT));
662 assertEquals("foo", read("src/a.tmp"));
663 assertEquals("fee\n", read("src/a.txt"));
664 }
665
666 @Test
667 public void testSmudgeFilter_deleteFileAndRestoreFromIndex()
668 throws IOException, GitAPIException {
669 File script = writeTempFile("sed s/o/e/g");
670 StoredConfig config = git.getRepository().getConfig();
671 config.setString("filter", "lfs", "smudge",
672 "sh " + slashify(script.getPath()));
673 config.save();
674
675 writeTrashFile("foo", "foo");
676 git.add().addFilepattern("foo").call();
677 git.commit().setMessage("initial").call();
678
679 writeTrashFile(".gitattributes", "*.txt filter=lfs");
680 git.add().addFilepattern(".gitattributes").call();
681 git.commit().setMessage("add filter").call();
682
683 writeTrashFile("src/a.tmp", "foo");
684
685
686 writeTrashFile("src/a.txt", "foo\n");
687 git.add().addFilepattern("src/a.tmp").addFilepattern("src/a.txt")
688 .call();
689 git.commit().setMessage("added content").call();
690
691 deleteTrashFile("src/a.txt");
692 git.checkout().addPath("src/a.txt").call();
693
694 assertEquals(
695 "[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
696 indexState(CONTENT));
697 assertEquals("foo", read("src/a.tmp"));
698 assertEquals("fee\n", read("src/a.txt"));
699 }
700
701 @Test
702 public void testSmudgeFilter_deleteFileAndCreateBranchAndRestoreFromCommit()
703 throws IOException, GitAPIException {
704 File script = writeTempFile("sed s/o/e/g");
705 StoredConfig config = git.getRepository().getConfig();
706 config.setString("filter", "lfs", "smudge",
707 "sh " + slashify(script.getPath()));
708 config.save();
709
710 writeTrashFile("foo", "foo");
711 git.add().addFilepattern("foo").call();
712 git.commit().setMessage("initial").call();
713
714 writeTrashFile(".gitattributes", "*.txt filter=lfs");
715 git.add().addFilepattern(".gitattributes").call();
716 git.commit().setMessage("add filter").call();
717
718 writeTrashFile("src/a.tmp", "foo");
719
720
721 writeTrashFile("src/a.txt", "foo\n");
722 git.add().addFilepattern("src/a.tmp").addFilepattern("src/a.txt")
723 .call();
724 RevCommit content = git.commit().setMessage("added content").call();
725
726 deleteTrashFile("src/a.txt");
727 git.checkout().setName("newBranch").setCreateBranch(true)
728 .setStartPoint(content).addPath("src/a.txt").call();
729
730 assertEquals(
731 "[.gitattributes, mode:100644, content:*.txt filter=lfs][Test.txt, mode:100644, content:Some change][foo, mode:100644, content:foo][src/a.tmp, mode:100644, content:foo][src/a.txt, mode:100644, content:foo\n]",
732 indexState(CONTENT));
733 assertEquals("foo", read("src/a.tmp"));
734 assertEquals("fee\n", read("src/a.txt"));
735 }
736
737 @Test
738 public void testSmudgeAndClean() throws Exception {
739 File clean_filter = writeTempFile("sed s/V1/@version/g");
740 File smudge_filter = writeTempFile("sed s/@version/V1/g");
741
742 try (Git git2 = new Git(db)) {
743 StoredConfig config = git.getRepository().getConfig();
744 config.setString("filter", "lfs", "smudge",
745 "sh " + slashify(smudge_filter.getPath()));
746 config.setString("filter", "lfs", "clean",
747 "sh " + slashify(clean_filter.getPath()));
748 config.setBoolean("filter", "lfs", "useJGitBuiltin", true);
749 config.save();
750 writeTrashFile(".gitattributes", "filterTest.txt filter=lfs");
751 git2.add().addFilepattern(".gitattributes").call();
752 git2.commit().setMessage("add attributes").call();
753
754 fsTick(writeTrashFile("filterTest.txt", "hello world, V1\n"));
755 git2.add().addFilepattern("filterTest.txt").call();
756 RevCommit one = git2.commit().setMessage("add filterText.txt").call();
757 assertEquals(
758 "[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:7bd5d32e5c494354aa4c2473a1306d0ce7b52cc3bffeb342c03cd517ef8cf8da\nsize 16\n]",
759 indexState(CONTENT));
760
761 fsTick(writeTrashFile("filterTest.txt", "bon giorno world, V1\n"));
762 git2.add().addFilepattern("filterTest.txt").call();
763 RevCommit two = git2.commit().setMessage("modified filterTest.txt").call();
764
765 assertTrue(git2.status().call().isClean());
766 assertEquals(
767 "[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:087148cccf53b0049c56475c1595113c9da4b638997c3489af8ac7108d51ef13\nsize 21\n]",
768 indexState(CONTENT));
769
770 git2.checkout().setName(one.getName()).call();
771 assertTrue(git2.status().call().isClean());
772 assertEquals(
773 "[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:7bd5d32e5c494354aa4c2473a1306d0ce7b52cc3bffeb342c03cd517ef8cf8da\nsize 16\n]",
774 indexState(CONTENT));
775 assertEquals("hello world, V1\n", read("filterTest.txt"));
776
777 git2.checkout().setName(two.getName()).call();
778 assertTrue(git2.status().call().isClean());
779 assertEquals(
780 "[.gitattributes, mode:100644, content:filterTest.txt filter=lfs][Test.txt, mode:100644, content:Some change][filterTest.txt, mode:100644, content:version https://git-lfs.github.com/spec/v1\noid sha256:087148cccf53b0049c56475c1595113c9da4b638997c3489af8ac7108d51ef13\nsize 21\n]",
781 indexState(CONTENT));
782 assertEquals("bon giorno world, V1\n", read("filterTest.txt"));
783 }
784 }
785
786 @Test
787 public void testNonDeletableFilesOnWindows()
788 throws GitAPIException, IOException {
789
790 org.junit.Assume.assumeTrue(SystemReader.getInstance().isWindows());
791 writeTrashFile("toBeModified.txt", "a");
792 writeTrashFile("toBeDeleted.txt", "a");
793 git.add().addFilepattern(".").call();
794 RevCommit addFiles = git.commit().setMessage("add more files").call();
795
796 git.rm().setCached(false).addFilepattern("Test.txt")
797 .addFilepattern("toBeDeleted.txt").call();
798 writeTrashFile("toBeModified.txt", "b");
799 writeTrashFile("toBeCreated.txt", "a");
800 git.add().addFilepattern(".").call();
801 RevCommit crudCommit = git.commit().setMessage("delete, modify, add")
802 .call();
803 git.checkout().setName(addFiles.getName()).call();
804 try ( FileInputStream fis=new FileInputStream(new File(db.getWorkTree(), "Test.txt")) ) {
805 CheckoutCommand coCommand = git.checkout();
806 coCommand.setName(crudCommit.getName()).call();
807 CheckoutResult result = coCommand.getResult();
808 assertEquals(Status.NONDELETED, result.getStatus());
809 assertEquals("[Test.txt, toBeDeleted.txt]",
810 result.getRemovedList().toString());
811 assertEquals("[toBeCreated.txt, toBeModified.txt]",
812 result.getModifiedList().toString());
813 assertEquals("[Test.txt]", result.getUndeletedList().toString());
814 assertTrue(result.getConflictList().isEmpty());
815 }
816 }
817
818 private File writeTempFile(String body) throws IOException {
819 File f = File.createTempFile("CheckoutCommandTest_", "");
820 JGitTestUtil.write(f, body);
821 return f;
822 }
823 }