1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jgit.lib;
14
15 import static java.nio.charset.StandardCharsets.UTF_8;
16 import static org.junit.Assert.assertArrayEquals;
17 import static org.junit.Assert.assertEquals;
18 import static org.junit.Assert.assertFalse;
19 import static org.junit.Assert.assertNotNull;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 import org.eclipse.jgit.api.CheckoutCommand;
32 import org.eclipse.jgit.api.CheckoutResult;
33 import org.eclipse.jgit.api.Git;
34 import org.eclipse.jgit.api.MergeResult.MergeStatus;
35 import org.eclipse.jgit.api.ResetCommand.ResetType;
36 import org.eclipse.jgit.api.Status;
37 import org.eclipse.jgit.api.errors.GitAPIException;
38 import org.eclipse.jgit.api.errors.NoFilepatternException;
39 import org.eclipse.jgit.dircache.DirCache;
40 import org.eclipse.jgit.dircache.DirCacheCheckout;
41 import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
42 import org.eclipse.jgit.dircache.DirCacheEditor;
43 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
44 import org.eclipse.jgit.dircache.DirCacheEntry;
45 import org.eclipse.jgit.errors.CheckoutConflictException;
46 import org.eclipse.jgit.errors.CorruptObjectException;
47 import org.eclipse.jgit.errors.NoWorkTreeException;
48 import org.eclipse.jgit.events.ChangeRecorder;
49 import org.eclipse.jgit.events.ListenerHandle;
50 import org.eclipse.jgit.junit.RepositoryTestCase;
51 import org.eclipse.jgit.junit.TestRepository;
52 import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
53 import org.eclipse.jgit.revwalk.RevCommit;
54 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
55 import org.eclipse.jgit.treewalk.FileTreeIterator;
56 import org.eclipse.jgit.treewalk.TreeWalk;
57 import org.eclipse.jgit.treewalk.WorkingTreeIterator;
58 import org.eclipse.jgit.util.FS;
59 import org.eclipse.jgit.util.FileUtils;
60 import org.eclipse.jgit.util.StringUtils;
61 import org.junit.Assume;
62 import org.junit.Test;
63
64 public class DirCacheCheckoutTest extends RepositoryTestCase {
65 private DirCacheCheckout dco;
66 protected ObjectId theHead;
67 protected ObjectId theMerge;
68 private DirCache dirCache;
69
70 private void prescanTwoTrees(ObjectId head, ObjectId merge)
71 throws IllegalStateException, IOException {
72 DirCache dc = db.lockDirCache();
73 try {
74 dco = new DirCacheCheckout(db, head, dc, merge);
75 dco.preScanTwoTrees();
76 } finally {
77 dc.unlock();
78 }
79 }
80
81 private void checkout() throws IOException {
82 DirCache dc = db.lockDirCache();
83 try {
84 dco = new DirCacheCheckout(db, theHead, dc, theMerge);
85 dco.checkout();
86 } finally {
87 dc.unlock();
88 }
89 }
90
91 private List<String> getRemoved() {
92 return dco.getRemoved();
93 }
94
95 private Map<String, CheckoutMetadata> getUpdated() {
96 return dco.getUpdated();
97 }
98
99 private List<String> getConflicts() {
100 return dco.getConflicts();
101 }
102
103 private static HashMap<String, String> mk(String a) {
104 return mkmap(a, a);
105 }
106
107 private static HashMap<String, String> mkmap(String... args) {
108 if ((args.length % 2) > 0)
109 throw new IllegalArgumentException("needs to be pairs");
110
111 HashMap<String, String> map = new HashMap<>();
112 for (int i = 0; i < args.length; i += 2) {
113 map.put(args[i], args[i + 1]);
114 }
115
116 return map;
117 }
118
119 @Test
120 public void testResetHard() throws IOException, NoFilepatternException,
121 GitAPIException {
122 ChangeRecorder recorder = new ChangeRecorder();
123 ListenerHandle handle = null;
124 try (Git git = new Git(db)) {
125 handle = db.getListenerList()
126 .addWorkingTreeModifiedListener(recorder);
127 writeTrashFile("f", "f()");
128 writeTrashFile("D/g", "g()");
129 git.add().addFilepattern(".").call();
130 git.commit().setMessage("inital").call();
131 assertIndex(mkmap("f", "f()", "D/g", "g()"));
132 recorder.assertNoEvent();
133 git.branchCreate().setName("topic").call();
134 recorder.assertNoEvent();
135
136 writeTrashFile("f", "f()\nmaster");
137 writeTrashFile("D/g", "g()\ng2()");
138 writeTrashFile("E/h", "h()");
139 git.add().addFilepattern(".").call();
140 RevCommit master = git.commit().setMessage("master-1").call();
141 assertIndex(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h", "h()"));
142 recorder.assertNoEvent();
143
144 checkoutBranch("refs/heads/topic");
145 assertIndex(mkmap("f", "f()", "D/g", "g()"));
146 recorder.assertEvent(new String[] { "f", "D/g" },
147 new String[] { "E/h" });
148
149 writeTrashFile("f", "f()\nside");
150 assertTrue(new File(db.getWorkTree(), "D/g").delete());
151 writeTrashFile("G/i", "i()");
152 git.add().addFilepattern(".").call();
153 git.add().addFilepattern(".").setUpdate(true).call();
154 RevCommit topic = git.commit().setMessage("topic-1").call();
155 assertIndex(mkmap("f", "f()\nside", "G/i", "i()"));
156 recorder.assertNoEvent();
157
158 writeTrashFile("untracked", "untracked");
159
160 resetHard(master);
161 assertIndex(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h", "h()"));
162 recorder.assertEvent(new String[] { "f", "D/g", "E/h" },
163 new String[] { "G", "G/i" });
164
165 resetHard(topic);
166 assertIndex(mkmap("f", "f()\nside", "G/i", "i()"));
167 assertWorkDir(mkmap("f", "f()\nside", "G/i", "i()", "untracked",
168 "untracked"));
169 recorder.assertEvent(new String[] { "f", "G/i" },
170 new String[] { "D", "D/g", "E", "E/h" });
171
172 assertEquals(MergeStatus.CONFLICTING, git.merge().include(master)
173 .call().getMergeStatus());
174 assertEquals(
175 "[D/g, mode:100644, stage:1][D/g, mode:100644, stage:3][E/h, mode:100644][G/i, mode:100644][f, mode:100644, stage:1][f, mode:100644, stage:2][f, mode:100644, stage:3]",
176 indexState(0));
177 recorder.assertEvent(new String[] { "f", "D/g", "E/h" },
178 ChangeRecorder.EMPTY);
179
180 resetHard(master);
181 assertIndex(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h", "h()"));
182 assertWorkDir(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h",
183 "h()", "untracked", "untracked"));
184 recorder.assertEvent(new String[] { "f", "D/g" },
185 new String[] { "G", "G/i" });
186
187 } finally {
188 if (handle != null) {
189 handle.remove();
190 }
191 }
192 }
193
194
195
196
197
198
199
200
201
202
203 @Test
204 public void testResetHardFromIndexEntryWithoutFileToTreeWithoutFile()
205 throws Exception {
206 ChangeRecorder recorder = new ChangeRecorder();
207 ListenerHandle handle = null;
208 try (Git git = new Git(db)) {
209 handle = db.getListenerList()
210 .addWorkingTreeModifiedListener(recorder);
211 writeTrashFile("x", "x");
212 git.add().addFilepattern("x").call();
213 RevCommit id1 = git.commit().setMessage("c1").call();
214
215 writeTrashFile("f/g", "f/g");
216 git.rm().addFilepattern("x").call();
217 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { "x" });
218 git.add().addFilepattern("f/g").call();
219 git.commit().setMessage("c2").call();
220 deleteTrashFile("f/g");
221 deleteTrashFile("f");
222
223
224 git.reset().setMode(ResetType.HARD).setRef(id1.getName()).call();
225 assertIndex(mkmap("x", "x"));
226 recorder.assertEvent(new String[] { "x" }, ChangeRecorder.EMPTY);
227 } finally {
228 if (handle != null) {
229 handle.remove();
230 }
231 }
232 }
233
234
235
236
237
238
239 @Test
240 public void testInitialCheckout() throws Exception {
241 ChangeRecorder recorder = new ChangeRecorder();
242 ListenerHandle handle = null;
243 try (Git git = new Git(db);
244 TestRepository<Repository> db_t = new TestRepository<>(db)) {
245 db.incrementOpen();
246 handle = db.getListenerList()
247 .addWorkingTreeModifiedListener(recorder);
248 BranchBuilder master = db_t.branch("master");
249 master.commit().add("f", "1").message("m0").create();
250 assertFalse(new File(db.getWorkTree(), "f").exists());
251 git.checkout().setName("master").call();
252 assertTrue(new File(db.getWorkTree(), "f").exists());
253 recorder.assertEvent(new String[] { "f" }, ChangeRecorder.EMPTY);
254 } finally {
255 if (handle != null) {
256 handle.remove();
257 }
258 }
259 }
260
261 private void checkoutLineEndings(String inIndex, String expected,
262 String attributes) throws Exception {
263 try (Git git = new Git(db);
264 TestRepository<Repository> db_t = new TestRepository<>(db)) {
265 db.incrementOpen();
266 BranchBuilder master = db_t.branch("master");
267 master.commit().add("f", inIndex).message("m0").create();
268 if (!StringUtils.isEmptyOrNull(attributes)) {
269 master.commit().add(".gitattributes", attributes)
270 .message("attributes").create();
271 }
272 File f = new File(db.getWorkTree(), "f");
273 assertFalse(f.exists());
274 git.checkout().setName("master").call();
275 assertTrue(f.exists());
276 checkFile(f, expected);
277 }
278 }
279
280 @Test
281 public void testCheckoutWithCRLF() throws Exception {
282 checkoutLineEndings("first line\r\nsecond line\r\n",
283 "first line\r\nsecond line\r\n", null);
284 }
285
286 @Test
287 public void testCheckoutWithCRLFAuto() throws Exception {
288 checkoutLineEndings("first line\r\nsecond line\r\n",
289 "first line\r\nsecond line\r\n", "f text=auto");
290 }
291
292 @Test
293 public void testCheckoutWithCRLFAutoEolLf() throws Exception {
294 checkoutLineEndings("first line\r\nsecond line\r\n",
295 "first line\r\nsecond line\r\n", "f text=auto eol=lf");
296 }
297
298 @Test
299 public void testCheckoutWithCRLFAutoEolNative() throws Exception {
300 checkoutLineEndings("first line\r\nsecond line\r\n",
301 "first line\r\nsecond line\r\n", "f text=auto eol=native");
302 }
303
304 @Test
305 public void testCheckoutWithCRLFAutoEolCrLf() throws Exception {
306 checkoutLineEndings("first line\r\nsecond line\r\n",
307 "first line\r\nsecond line\r\n", "f text=auto eol=crlf");
308 }
309
310 @Test
311 public void testCheckoutWithLF() throws Exception {
312 checkoutLineEndings("first line\nsecond line\n",
313 "first line\nsecond line\n", null);
314 }
315
316 @Test
317 public void testCheckoutWithLFAuto() throws Exception {
318 String expected = String.format("first line%nsecond line%n");
319 checkoutLineEndings("first line\nsecond line\n", expected,
320 "f text=auto");
321 }
322
323 @Test
324 public void testCheckoutWithLFAutoEolLf() throws Exception {
325 checkoutLineEndings("first line\nsecond line\n",
326 "first line\nsecond line\n", "f text=auto eol=lf");
327 }
328
329 @Test
330 public void testCheckoutWithLFAutoEolNative() throws Exception {
331 String expected = String.format("first line%nsecond line%n");
332 checkoutLineEndings(
333 "first line\nsecond line\n", expected,
334 "f text=auto eol=native");
335 }
336
337 @Test
338 public void testCheckoutWithLFAutoEolCrLf() throws Exception {
339 checkoutLineEndings("first line\nsecond line\n",
340 "first line\r\nsecond line\r\n", "f text=auto eol=crlf");
341 }
342
343 @Test
344 public void testCheckoutMixedAutoEolCrLf() throws Exception {
345 checkoutLineEndings("first line\nsecond line\r\n",
346 "first line\nsecond line\r\n", "f text=auto eol=crlf");
347 }
348
349 @Test
350 public void testCheckoutMixedAutoEolLf() throws Exception {
351 checkoutLineEndings("first line\nsecond line\r\n",
352 "first line\nsecond line\r\n", "f text=auto eol=lf");
353 }
354
355 @Test
356 public void testCheckoutMixedTextCrLf() throws Exception {
357
358
359
360
361 checkoutLineEndings("first line\nsecond line\r\n",
362 "first line\r\nsecond line\r\n", "f text eol=crlf");
363 }
364
365 @Test
366 public void testCheckoutMixedTextLf() throws Exception {
367 checkoutLineEndings("first line\nsecond line\r\nfoo",
368 "first line\nsecond line\r\nfoo", "f text eol=lf");
369 }
370
371 private DirCacheCheckout resetHard(RevCommit commit)
372 throws NoWorkTreeException,
373 CorruptObjectException, IOException {
374 DirCacheCheckout dc;
375 dc = new DirCacheCheckout(db, null, db.lockDirCache(),
376 commit.getTree());
377 dc.setFailOnConflict(true);
378 assertTrue(dc.checkout());
379 return dc;
380 }
381
382 private void assertIndex(HashMap<String, String> i)
383 throws CorruptObjectException, IOException {
384 String expectedValue;
385 String path;
386 DirCache read = DirCache.read(db.getIndexFile(), db.getFS());
387
388 assertEquals("Index has not the right size.", i.size(),
389 read.getEntryCount());
390 for (int j = 0; j < read.getEntryCount(); j++) {
391 path = read.getEntry(j).getPathString();
392 expectedValue = i.get(path);
393 assertNotNull("found unexpected entry for path " + path
394 + " in index", expectedValue);
395 assertTrue("unexpected content for path " + path
396 + " in index. Expected: <" + expectedValue + ">",
397 Arrays.equals(db.open(read.getEntry(j).getObjectId())
398 .getCachedBytes(), i.get(path).getBytes(UTF_8)));
399 }
400 }
401
402 @Test
403 public void testRules1thru3_NoIndexEntry() throws IOException {
404 ObjectId head = buildTree(mk("foo"));
405 ObjectId merge = db.newObjectInserter().insert(Constants.OBJ_TREE,
406 new byte[0]);
407
408 prescanTwoTrees(head, merge);
409
410 assertTrue(getRemoved().contains("foo"));
411
412 prescanTwoTrees(merge, head);
413
414 assertTrue(getUpdated().containsKey("foo"));
415
416 merge = buildTree(mkmap("foo", "a"));
417
418 prescanTwoTrees(head, merge);
419
420 assertConflict("foo");
421 }
422
423 void setupCase(HashMap<String, String> headEntries, HashMap<String, String> mergeEntries, HashMap<String, String> indexEntries) throws IOException {
424 theHead = buildTree(headEntries);
425 theMerge = buildTree(mergeEntries);
426 buildIndex(indexEntries);
427 }
428
429 private void buildIndex(HashMap<String, String> indexEntries) throws IOException {
430 dirCache = new DirCache(db.getIndexFile(), db.getFS());
431 if (indexEntries != null) {
432 assertTrue(dirCache.lock());
433 DirCacheEditor editor = dirCache.editor();
434 for (java.util.Map.Entry<String,String> e : indexEntries.entrySet()) {
435 writeTrashFile(e.getKey(), e.getValue());
436 ObjectId id;
437 try (ObjectInserter inserter = db.newObjectInserter()) {
438 id = inserter.insert(Constants.OBJ_BLOB,
439 Constants.encode(e.getValue()));
440 }
441 editor.add(new DirCacheEditor.DeletePath(e.getKey()));
442 editor.add(new DirCacheEditor.PathEdit(e.getKey()) {
443 @Override
444 public void apply(DirCacheEntry ent) {
445 ent.setFileMode(FileMode.REGULAR_FILE);
446 ent.setObjectId(id);
447 ent.setUpdateNeeded(false);
448 }
449 });
450 }
451 assertTrue(editor.commit());
452 }
453
454 }
455
456 static final class AddEdit extends PathEdit {
457
458 private final ObjectId data;
459
460 private final long length;
461
462 public AddEdit(String entryPath, ObjectId data, long length) {
463 super(entryPath);
464 this.data = data;
465 this.length = length;
466 }
467
468 @Override
469 public void apply(DirCacheEntry ent) {
470 ent.setFileMode(FileMode.REGULAR_FILE);
471 ent.setLength(length);
472 ent.setObjectId(data);
473 }
474
475 }
476
477 private ObjectId buildTree(HashMap<String, String> headEntries)
478 throws IOException {
479 DirCache lockDirCache = DirCache.newInCore();
480
481 DirCacheEditor editor = lockDirCache.editor();
482 if (headEntries != null) {
483 for (java.util.Map.Entry<String, String> e : headEntries.entrySet()) {
484 AddEdit addEdit = new AddEdit(e.getKey(),
485 genSha1(e.getValue()), e.getValue().length());
486 editor.add(addEdit);
487 }
488 }
489 editor.finish();
490 return lockDirCache.writeTree(db.newObjectInserter());
491 }
492
493 ObjectId genSha1(String data) {
494 try (ObjectInserter w = db.newObjectInserter()) {
495 ObjectId id = w.insert(Constants.OBJ_BLOB, data.getBytes(UTF_8));
496 w.flush();
497 return id;
498 } catch (IOException e) {
499 fail(e.toString());
500 }
501 return null;
502 }
503
504 protected void go() throws IllegalStateException, IOException {
505 prescanTwoTrees(theHead, theMerge);
506 }
507
508 @Test
509 public void testRules4thru13_IndexEntryNotInHead() throws IOException {
510
511 HashMap<String, String> idxMap;
512
513 idxMap = new HashMap<>();
514 idxMap.put("foo", "foo");
515 setupCase(null, null, idxMap);
516 go();
517
518 assertTrue(getUpdated().isEmpty());
519 assertTrue(getRemoved().isEmpty());
520 assertTrue(getConflicts().isEmpty());
521
522
523 idxMap = new HashMap<>();
524 idxMap.put("foo", "foo");
525 setupCase(null, idxMap, idxMap);
526 go();
527
528 assertAllEmpty();
529
530
531 HashMap<String, String> mergeMap;
532 mergeMap = new HashMap<>();
533
534 mergeMap.put("foo", "merge");
535 setupCase(null, mergeMap, idxMap);
536 go();
537
538 assertTrue(getUpdated().isEmpty());
539 assertTrue(getRemoved().isEmpty());
540 assertTrue(getConflicts().contains("foo"));
541
542
543
544 HashMap<String, String> headMap = new HashMap<>();
545 headMap.put("foo", "foo");
546 setupCase(headMap, null, idxMap);
547 go();
548
549 assertTrue(getRemoved().contains("foo"));
550 assertTrue(getUpdated().isEmpty());
551 assertTrue(getConflicts().isEmpty());
552
553
554 setupCase(headMap, null, idxMap);
555 assertTrue(new File(trash, "foo").delete());
556 writeTrashFile("foo", "bar");
557 db.readDirCache().getEntry(0).setUpdateNeeded(true);
558 go();
559
560 assertTrue(getRemoved().isEmpty());
561 assertTrue(getUpdated().isEmpty());
562 assertTrue(getConflicts().contains("foo"));
563
564
565 headMap.put("foo", "head");
566 setupCase(headMap, null, idxMap);
567 go();
568
569 assertTrue(getRemoved().isEmpty());
570 assertTrue(getUpdated().isEmpty());
571 assertTrue(getConflicts().contains("foo"));
572
573
574 setupCase(headMap, headMap, idxMap);
575 go();
576
577 assertAllEmpty();
578
579
580 setupCase(headMap, mergeMap, idxMap); go();
581 assertTrue(getConflicts().contains("foo"));
582
583
584 setupCase(headMap, idxMap, idxMap); go();
585 assertAllEmpty();
586
587
588 setupCase(idxMap, mergeMap, idxMap); go();
589 assertTrue(getUpdated().containsKey("foo"));
590
591
592 setupCase(idxMap, mergeMap, idxMap);
593 assertTrue(new File(trash, "foo").delete());
594 writeTrashFile("foo", "bar");
595 db.readDirCache().getEntry(0).setUpdateNeeded(true);
596 go();
597 assertTrue(getConflicts().contains("foo"));
598 }
599
600 private void assertAllEmpty() {
601 assertTrue(getRemoved().isEmpty());
602 assertTrue(getUpdated().isEmpty());
603 assertTrue(getConflicts().isEmpty());
604 }
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638 @Test
639 public void testDirectoryFileSimple() throws IOException {
640 ObjectId treeDF = buildTree(mkmap("DF", "DF"));
641 ObjectId treeDFDF = buildTree(mkmap("DF/DF", "DF/DF"));
642 buildIndex(mkmap("DF", "DF"));
643
644 prescanTwoTrees(treeDF, treeDFDF);
645
646 assertTrue(getRemoved().contains("DF"));
647 assertTrue(getUpdated().containsKey("DF/DF"));
648
649 recursiveDelete(new File(trash, "DF"));
650 buildIndex(mkmap("DF/DF", "DF/DF"));
651
652 prescanTwoTrees(treeDFDF, treeDF);
653 assertTrue(getRemoved().contains("DF/DF"));
654 assertTrue(getUpdated().containsKey("DF"));
655 }
656
657 @Test
658 public void testDirectoryFileConflicts_1() throws Exception {
659
660 doit(mk("DF/DF"), mk("DF"), mk("DF/DF"));
661 assertNoConflicts();
662 assertUpdated("DF");
663 assertRemoved("DF/DF");
664 }
665
666 @Test
667 public void testDirectoryFileConflicts_2() throws Exception {
668
669 setupCase(mk("DF/DF"), mk("DF"), mk("DF/DF"));
670 writeTrashFile("DF/DF", "different");
671 go();
672 assertConflict("DF/DF");
673
674 }
675
676 @Test
677 public void testDirectoryFileConflicts_3() throws Exception {
678
679 doit(mk("DF/DF"), mk("DF/DF"), mk("DF"));
680 assertNoConflicts();
681 }
682
683 @Test
684 public void testDirectoryFileConflicts_4() throws Exception {
685
686 doit(mk("DF/DF"), mkmap("DF/DF", "foo"), mk("DF"));
687 assertConflict("DF/DF");
688
689 }
690
691 @Test
692 public void testDirectoryFileConflicts_5() throws Exception {
693
694 doit(mk("DF/DF"), mk("DF"), mk("DF"));
695 assertRemoved("DF/DF");
696 assertEquals(0, dco.getConflicts().size());
697 assertEquals(0, dco.getUpdated().size());
698 }
699
700 @Test
701 public void testDirectoryFileConflicts_5b() throws Exception {
702
703 doit(mk("DF/DF"), mkmap("DF", "different"), mk("DF"));
704 assertRemoved("DF/DF");
705 assertConflict("DF");
706 assertEquals(0, dco.getUpdated().size());
707 }
708
709 @Test
710 public void testDirectoryFileConflicts_6() throws Exception {
711
712 setupCase(mk("DF/DF"), mk("DF"), mk("DF"));
713 writeTrashFile("DF", "different");
714 go();
715 assertRemoved("DF/DF");
716 assertEquals(0, dco.getConflicts().size());
717 assertEquals(0, dco.getUpdated().size());
718 }
719
720 @Test
721 public void testDirectoryFileConflicts_6b() throws Exception {
722
723 setupCase(mk("DF/DF"), mk("DF"), mkmap("DF", "different"));
724 writeTrashFile("DF", "again different");
725 go();
726 assertRemoved("DF/DF");
727 assertConflict("DF");
728 assertEquals(0, dco.getUpdated().size());
729 }
730
731 @Test
732 public void testDirectoryFileConflicts_7() throws Exception {
733
734 doit(mk("DF"), mk("DF"), mk("DF/DF"));
735 assertUpdated("DF");
736 assertRemoved("DF/DF");
737
738 cleanUpDF();
739 setupCase(mk("DF/DF"), mk("DF/DF"), mk("DF/DF/DF/DF/DF"));
740 go();
741 assertRemoved("DF/DF/DF/DF/DF");
742 assertUpdated("DF/DF");
743
744 cleanUpDF();
745 setupCase(mk("DF/DF"), mk("DF/DF"), mk("DF/DF/DF/DF/DF"));
746 writeTrashFile("DF/DF/DF/DF/DF", "diff");
747 go();
748 assertConflict("DF/DF/DF/DF/DF");
749
750
751
752
753
754
755
756
757
758 }
759
760 @Test
761 public void testDirectoryFileConflicts_8() throws Exception {
762
763 setupCase(mk("DF"), mk("DF"), mk("DF/DF"));
764 recursiveDelete(new File(db.getWorkTree(), "DF"));
765 writeTrashFile("DF", "xy");
766 go();
767 assertConflict("DF/DF");
768 }
769
770 @Test
771 public void testDirectoryFileConflicts_9() throws Exception {
772
773 doit(mkmap("DF", "QP"), mkmap("DF", "QP"), mkmap("DF/DF", "DF/DF"));
774 assertRemoved("DF/DF");
775 assertUpdated("DF");
776 }
777
778 @Test
779 public void testDirectoryFileConflicts_10() throws Exception {
780
781 cleanUpDF();
782 doit(mk("DF"), mk("DF/DF"), mk("DF/DF"));
783 assertNoConflicts();
784 }
785
786 @Test
787 public void testDirectoryFileConflicts_11() throws Exception {
788
789 doit(mk("DF"), mk("DF/DF"), mkmap("DF/DF", "asdf"));
790 assertConflict("DF/DF");
791 }
792
793 @Test
794 public void testDirectoryFileConflicts_12() throws Exception {
795
796 cleanUpDF();
797 doit(mk("DF"), mk("DF/DF"), mk("DF"));
798 assertRemoved("DF");
799 assertUpdated("DF/DF");
800 }
801
802 @Test
803 public void testDirectoryFileConflicts_13() throws Exception {
804
805 cleanUpDF();
806 setupCase(mk("DF"), mk("DF/DF"), mk("DF"));
807 writeTrashFile("DF", "asdfsdf");
808 go();
809 assertConflict("DF");
810 assertUpdated("DF/DF");
811 }
812
813 @Test
814 public void testDirectoryFileConflicts_14() throws Exception {
815
816 cleanUpDF();
817 doit(mk("DF"), mk("DF/DF"), mkmap("DF", "Foo"));
818 assertConflict("DF");
819 assertUpdated("DF/DF");
820 }
821
822 @Test
823 public void testDirectoryFileConflicts_15() throws Exception {
824
825 doit(mkmap(), mk("DF/DF"), mk("DF"));
826
827
828
829
830
831 assertUpdated("DF/DF");
832 }
833
834 @Test
835 public void testDirectoryFileConflicts_15b() throws Exception {
836
837 doit(mkmap(), mk("DF/DF/DF/DF"), mk("DF"));
838
839
840
841
842
843
844 assertUpdated("DF/DF/DF/DF");
845 }
846
847 @Test
848 public void testDirectoryFileConflicts_16() throws Exception {
849
850 cleanUpDF();
851 doit(mkmap(), mk("DF"), mk("DF/DF/DF"));
852 assertRemoved("DF/DF/DF");
853 assertUpdated("DF");
854 }
855
856 @Test
857 public void testDirectoryFileConflicts_17() throws Exception {
858
859 cleanUpDF();
860 setupCase(mkmap(), mk("DF"), mk("DF/DF/DF"));
861 writeTrashFile("DF/DF/DF", "asdf");
862 go();
863 assertConflict("DF/DF/DF");
864
865
866
867
868
869
870 }
871
872 @Test
873 public void testDirectoryFileConflicts_18() throws Exception {
874
875 cleanUpDF();
876 doit(mk("DF/DF"), mk("DF/DF/DF/DF"), null);
877 assertRemoved("DF/DF");
878 assertUpdated("DF/DF/DF/DF");
879 }
880
881 @Test
882 public void testDirectoryFileConflicts_19() throws Exception {
883
884 cleanUpDF();
885 doit(mk("DF/DF/DF/DF"), mk("DF/DF/DF"), null);
886 assertRemoved("DF/DF/DF/DF");
887 assertUpdated("DF/DF/DF");
888 }
889
890 protected void cleanUpDF() throws Exception {
891 tearDown();
892 setUp();
893 recursiveDelete(new File(trash, "DF"));
894 }
895
896 protected void assertConflict(String s) {
897 assertTrue(getConflicts().contains(s));
898 }
899
900 protected void assertUpdated(String s) {
901 assertTrue(getUpdated().containsKey(s));
902 }
903
904 protected void assertRemoved(String s) {
905 assertTrue(getRemoved().contains(s));
906 }
907
908 protected void assertNoConflicts() {
909 assertTrue(getConflicts().isEmpty());
910 }
911
912 protected void doit(HashMap<String, String> h, HashMap<String, String> m, HashMap<String, String> i)
913 throws IOException {
914 setupCase(h, m, i);
915 go();
916 }
917
918 @Test
919 public void testUntrackedConflicts() throws IOException {
920 setupCase(null, mk("foo"), null);
921 writeTrashFile("foo", "foo");
922 go();
923
924
925 recursiveDelete(new File(trash, "foo"));
926 setupCase(mk("other"), mkmap("other", "other", "foo", "foo"),
927 mk("other"));
928 writeTrashFile("foo", "bar");
929 try {
930 checkout();
931 fail("didn't get the expected exception");
932 } catch (CheckoutConflictException e) {
933 assertConflict("foo");
934 assertEquals("foo", e.getConflictingFiles()[0]);
935 assertWorkDir(mkmap("foo", "bar", "other", "other"));
936 assertIndex(mk("other"));
937 }
938
939
940 recursiveDelete(new File(trash, "other"));
941 recursiveDelete(new File(trash, "foo"));
942 setupCase(null, mk("foo"), null);
943 writeTrashFile("foo", "bar");
944 try {
945 checkout();
946 fail("didn't get the expected exception");
947 } catch (CheckoutConflictException e) {
948 assertConflict("foo");
949 assertWorkDir(mkmap("foo", "bar"));
950 assertIndex(mkmap("other", "other"));
951 }
952
953
954
955
956
957
958
959
960
961
962 recursiveDelete(new File(trash, "foo"));
963 recursiveDelete(new File(trash, "other"));
964 setupCase(null, mk("foo"), null);
965 writeTrashFile("foo/bar/baz", "");
966 writeTrashFile("foo/blahblah", "");
967 go();
968
969 assertConflict("foo");
970 assertConflict("foo/bar/baz");
971 assertConflict("foo/blahblah");
972
973 recursiveDelete(new File(trash, "foo"));
974
975 setupCase(mkmap("foo/bar", "", "foo/baz", ""),
976 mk("foo"), mkmap("foo/bar", "", "foo/baz", ""));
977 assertTrue(new File(trash, "foo/bar").exists());
978 go();
979
980 assertNoConflicts();
981 }
982
983 @Test
984 public void testCloseNameConflictsX0() throws IOException {
985 setupCase(mkmap("a/a", "a/a-c"), mkmap("a/a","a/a", "b.b/b.b","b.b/b.bs"), mkmap("a/a", "a/a-c") );
986 checkout();
987 assertIndex(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
988 assertWorkDir(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
989 go();
990 assertIndex(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
991 assertWorkDir(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
992 assertNoConflicts();
993 }
994
995 @Test
996 public void testCloseNameConflicts1() throws IOException {
997 setupCase(mkmap("a/a", "a/a-c"), mkmap("a/a","a/a", "a.a/a.a","a.a/a.a"), mkmap("a/a", "a/a-c") );
998 checkout();
999 assertIndex(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
1000 assertWorkDir(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
1001 go();
1002 assertIndex(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
1003 assertWorkDir(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
1004 assertNoConflicts();
1005 }
1006
1007 @Test
1008 public void testCheckoutHierarchy() throws IOException {
1009 setupCase(
1010 mkmap("a", "a", "b/c", "b/c", "d", "d", "e/f", "e/f", "e/g",
1011 "e/g"),
1012 mkmap("a", "a2", "b/c", "b/c", "d", "d", "e/f", "e/f", "e/g",
1013 "e/g2"),
1014 mkmap("a", "a", "b/c", "b/c", "d", "d", "e/f", "e/f", "e/g",
1015 "e/g3"));
1016 try {
1017 checkout();
1018 fail("did not throw CheckoutConflictException");
1019 } catch (CheckoutConflictException e) {
1020 assertWorkDir(mkmap("a", "a", "b/c", "b/c", "d", "d", "e/f",
1021 "e/f", "e/g", "e/g3"));
1022 assertConflict("e/g");
1023 assertEquals("e/g", e.getConflictingFiles()[0]);
1024 }
1025 }
1026
1027 @Test
1028 public void testCheckoutOutChanges() throws IOException {
1029 setupCase(mk("foo"), mk("foo/bar"), mk("foo"));
1030 checkout();
1031 assertIndex(mk("foo/bar"));
1032 assertWorkDir(mk("foo/bar"));
1033
1034 assertFalse(new File(trash, "foo").isFile());
1035 assertTrue(new File(trash, "foo/bar").isFile());
1036 recursiveDelete(new File(trash, "foo"));
1037
1038 assertWorkDir(mkmap());
1039
1040 setupCase(mk("foo/bar"), mk("foo"), mk("foo/bar"));
1041 checkout();
1042
1043 assertIndex(mk("foo"));
1044 assertWorkDir(mk("foo"));
1045
1046 assertFalse(new File(trash, "foo/bar").isFile());
1047 assertTrue(new File(trash, "foo").isFile());
1048
1049 setupCase(mk("foo"), mkmap("foo", "qux"), mkmap("foo", "bar"));
1050
1051 assertIndex(mkmap("foo", "bar"));
1052 assertWorkDir(mkmap("foo", "bar"));
1053
1054 try {
1055 checkout();
1056 fail("did not throw exception");
1057 } catch (CheckoutConflictException e) {
1058 assertIndex(mkmap("foo", "bar"));
1059 assertWorkDir(mkmap("foo", "bar"));
1060 }
1061 }
1062
1063 @Test
1064 public void testCheckoutChangeLinkToEmptyDir() throws Exception {
1065 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
1066 String fname = "was_file";
1067 ChangeRecorder recorder = new ChangeRecorder();
1068 ListenerHandle handle = null;
1069 try (Git git = new Git(db)) {
1070 handle = db.getListenerList()
1071 .addWorkingTreeModifiedListener(recorder);
1072
1073 writeTrashFile(fname, "a");
1074 git.add().addFilepattern(fname).call();
1075
1076
1077 String linkName = "link";
1078 File link = writeLink(linkName, fname).toFile();
1079 git.add().addFilepattern(linkName).call();
1080 git.commit().setMessage("Added file and link").call();
1081
1082 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1083
1084
1085 FileUtils.delete(link);
1086 FileUtils.mkdir(link);
1087 assertTrue("Link must be a directory now", link.isDirectory());
1088
1089
1090 writeTrashFile(fname, "b");
1091 assertWorkDir(mkmap(fname, "b", linkName, "/"));
1092 recorder.assertNoEvent();
1093
1094
1095 git.checkout().setStartPoint(Constants.HEAD).addPath(fname)
1096 .addPath(linkName).call();
1097
1098 assertWorkDir(mkmap(fname, "a", linkName, "a"));
1099 recorder.assertEvent(new String[] { fname, linkName },
1100 ChangeRecorder.EMPTY);
1101
1102 Status st = git.status().call();
1103 assertTrue(st.isClean());
1104 } finally {
1105 if (handle != null) {
1106 handle.remove();
1107 }
1108 }
1109 }
1110
1111 @Test
1112 public void testCheckoutChangeLinkToEmptyDirs() throws Exception {
1113 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
1114 String fname = "was_file";
1115 ChangeRecorder recorder = new ChangeRecorder();
1116 ListenerHandle handle = null;
1117 try (Git git = new Git(db)) {
1118 handle = db.getListenerList()
1119 .addWorkingTreeModifiedListener(recorder);
1120
1121 writeTrashFile(fname, "a");
1122 git.add().addFilepattern(fname).call();
1123
1124
1125 String linkName = "link";
1126 File link = writeLink(linkName, fname).toFile();
1127 git.add().addFilepattern(linkName).call();
1128 git.commit().setMessage("Added file and link").call();
1129
1130 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1131
1132
1133 FileUtils.delete(link);
1134 FileUtils.mkdirs(new File(link, "dummyDir"));
1135 assertTrue("Link must be a directory now", link.isDirectory());
1136
1137 assertFalse("Must not delete non empty directory", link.delete());
1138
1139
1140 writeTrashFile(fname, "b");
1141 assertWorkDir(mkmap(fname, "b", linkName + "/dummyDir", "/"));
1142 recorder.assertNoEvent();
1143
1144
1145 git.checkout().setStartPoint(Constants.HEAD).addPath(fname)
1146 .addPath(linkName).call();
1147
1148 assertWorkDir(mkmap(fname, "a", linkName, "a"));
1149 recorder.assertEvent(new String[] { fname, linkName },
1150 ChangeRecorder.EMPTY);
1151
1152 Status st = git.status().call();
1153 assertTrue(st.isClean());
1154 } finally {
1155 if (handle != null) {
1156 handle.remove();
1157 }
1158 }
1159 }
1160
1161 @Test
1162 public void testCheckoutChangeLinkToNonEmptyDirs() throws Exception {
1163 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
1164 String fname = "file";
1165 ChangeRecorder recorder = new ChangeRecorder();
1166 ListenerHandle handle = null;
1167 try (Git git = new Git(db)) {
1168 handle = db.getListenerList()
1169 .addWorkingTreeModifiedListener(recorder);
1170
1171 writeTrashFile(fname, "a");
1172 git.add().addFilepattern(fname).call();
1173
1174
1175 String linkName = "link";
1176 File link = writeLink(linkName, fname).toFile();
1177 git.add().addFilepattern(linkName).call();
1178 git.commit().setMessage("Added file and link").call();
1179
1180 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1181
1182
1183 FileUtils.delete(link);
1184
1185
1186 writeTrashFile(linkName + "/dir1", "file1", "c");
1187
1188
1189 writeTrashFile(linkName + "/dir2", "file2", "d");
1190
1191 assertTrue("File must be a directory now", link.isDirectory());
1192 assertFalse("Must not delete non empty directory", link.delete());
1193
1194
1195 assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
1196 linkName + "/dir2/file2", "d"));
1197 recorder.assertNoEvent();
1198
1199
1200 git.checkout().setStartPoint(Constants.HEAD).addPath(linkName)
1201 .call();
1202
1203
1204 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1205 recorder.assertEvent(new String[] { linkName },
1206 ChangeRecorder.EMPTY);
1207
1208 Status st = git.status().call();
1209 assertTrue(st.isClean());
1210 } finally {
1211 if (handle != null) {
1212 handle.remove();
1213 }
1214 }
1215 }
1216
1217 @Test
1218 public void testCheckoutChangeLinkToNonEmptyDirsAndNewIndexEntry()
1219 throws Exception {
1220 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
1221 String fname = "file";
1222 ChangeRecorder recorder = new ChangeRecorder();
1223 ListenerHandle handle = null;
1224 try (Git git = new Git(db)) {
1225 handle = db.getListenerList()
1226 .addWorkingTreeModifiedListener(recorder);
1227
1228 writeTrashFile(fname, "a");
1229 git.add().addFilepattern(fname).call();
1230
1231
1232 String linkName = "link";
1233 File link = writeLink(linkName, fname).toFile();
1234 git.add().addFilepattern(linkName).call();
1235 git.commit().setMessage("Added file and link").call();
1236
1237 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1238
1239
1240 FileUtils.delete(link);
1241
1242
1243 writeTrashFile(linkName + "/dir1", "file1", "c");
1244 git.add().addFilepattern(linkName + "/dir1/file1").call();
1245
1246
1247 writeTrashFile(linkName + "/dir2", "file2", "d");
1248
1249 assertTrue("File must be a directory now", link.isDirectory());
1250 assertFalse("Must not delete non empty directory", link.delete());
1251
1252
1253 assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
1254 linkName + "/dir2/file2", "d"));
1255 recorder.assertNoEvent();
1256
1257
1258 git.checkout().setStartPoint(Constants.HEAD).addPath(linkName)
1259 .call();
1260
1261
1262 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1263 recorder.assertEvent(new String[] { linkName },
1264 ChangeRecorder.EMPTY);
1265
1266 Status st = git.status().call();
1267 assertTrue(st.isClean());
1268 } finally {
1269 if (handle != null) {
1270 handle.remove();
1271 }
1272 }
1273 }
1274
1275 @Test
1276 public void testCheckoutChangeFileToEmptyDir() throws Exception {
1277 String fname = "was_file";
1278 ChangeRecorder recorder = new ChangeRecorder();
1279 ListenerHandle handle = null;
1280 try (Git git = new Git(db)) {
1281 handle = db.getListenerList()
1282 .addWorkingTreeModifiedListener(recorder);
1283
1284 File file = writeTrashFile(fname, "a");
1285 git.add().addFilepattern(fname).call();
1286 git.commit().setMessage("Added file").call();
1287
1288
1289 FileUtils.delete(file);
1290 FileUtils.mkdir(file);
1291 assertTrue("File must be a directory now", file.isDirectory());
1292 assertWorkDir(mkmap(fname, "/"));
1293 recorder.assertNoEvent();
1294
1295
1296 git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
1297 assertWorkDir(mkmap(fname, "a"));
1298 recorder.assertEvent(new String[] { fname }, ChangeRecorder.EMPTY);
1299
1300 Status st = git.status().call();
1301 assertTrue(st.isClean());
1302 } finally {
1303 if (handle != null) {
1304 handle.remove();
1305 }
1306 }
1307 }
1308
1309 @Test
1310 public void testCheckoutChangeFileToEmptyDirs() throws Exception {
1311 String fname = "was_file";
1312 ChangeRecorder recorder = new ChangeRecorder();
1313 ListenerHandle handle = null;
1314 try (Git git = new Git(db)) {
1315 handle = db.getListenerList()
1316 .addWorkingTreeModifiedListener(recorder);
1317
1318 File file = writeTrashFile(fname, "a");
1319 git.add().addFilepattern(fname).call();
1320 git.commit().setMessage("Added file").call();
1321
1322
1323 FileUtils.delete(file);
1324 FileUtils.mkdirs(new File(file, "dummyDir"));
1325 assertTrue("File must be a directory now", file.isDirectory());
1326 assertFalse("Must not delete non empty directory", file.delete());
1327
1328 assertWorkDir(mkmap(fname + "/dummyDir", "/"));
1329 recorder.assertNoEvent();
1330
1331
1332 git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
1333 assertWorkDir(mkmap(fname, "a"));
1334 recorder.assertEvent(new String[] { fname }, ChangeRecorder.EMPTY);
1335
1336 Status st = git.status().call();
1337 assertTrue(st.isClean());
1338 } finally {
1339 if (handle != null) {
1340 handle.remove();
1341 }
1342 }
1343 }
1344
1345 @Test
1346 public void testCheckoutChangeFileToNonEmptyDirs() throws Exception {
1347 String fname = "was_file";
1348 ChangeRecorder recorder = new ChangeRecorder();
1349 ListenerHandle handle = null;
1350 try (Git git = new Git(db)) {
1351 handle = db.getListenerList()
1352 .addWorkingTreeModifiedListener(recorder);
1353
1354 File file = writeTrashFile(fname, "a");
1355 git.add().addFilepattern(fname).call();
1356 git.commit().setMessage("Added file").call();
1357
1358 assertWorkDir(mkmap(fname, "a"));
1359
1360
1361 FileUtils.delete(file);
1362
1363
1364 writeTrashFile(fname + "/dir1", "file1", "c");
1365
1366
1367 writeTrashFile(fname + "/dir2", "file2", "d");
1368
1369 assertTrue("File must be a directory now", file.isDirectory());
1370 assertFalse("Must not delete non empty directory", file.delete());
1371
1372
1373 assertWorkDir(mkmap(fname + "/dir1/file1", "c",
1374 fname + "/dir2/file2", "d"));
1375 recorder.assertNoEvent();
1376
1377
1378 git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
1379
1380
1381 assertWorkDir(mkmap(fname, "a"));
1382 recorder.assertEvent(new String[] { fname }, ChangeRecorder.EMPTY);
1383
1384 Status st = git.status().call();
1385 assertTrue(st.isClean());
1386 } finally {
1387 if (handle != null) {
1388 handle.remove();
1389 }
1390 }
1391 }
1392
1393 @Test
1394 public void testCheckoutChangeFileToNonEmptyDirsAndNewIndexEntry()
1395 throws Exception {
1396 String fname = "was_file";
1397 ChangeRecorder recorder = new ChangeRecorder();
1398 ListenerHandle handle = null;
1399 try (Git git = new Git(db)) {
1400 handle = db.getListenerList()
1401 .addWorkingTreeModifiedListener(recorder);
1402
1403 File file = writeTrashFile(fname, "a");
1404 git.add().addFilepattern(fname).call();
1405 git.commit().setMessage("Added file").call();
1406
1407 assertWorkDir(mkmap(fname, "a"));
1408
1409
1410 FileUtils.delete(file);
1411
1412
1413 writeTrashFile(fname + "/dir", "file1", "c");
1414 git.add().addFilepattern(fname + "/dir/file1").call();
1415
1416
1417 writeTrashFile(fname + "/dir", "file2", "d");
1418
1419 assertTrue("File must be a directory now", file.isDirectory());
1420 assertFalse("Must not delete non empty directory", file.delete());
1421
1422
1423 assertWorkDir(mkmap(fname + "/dir/file1", "c", fname + "/dir/file2",
1424 "d"));
1425 recorder.assertNoEvent();
1426
1427
1428 git.checkout().setStartPoint(Constants.HEAD).addPath(fname).call();
1429 assertWorkDir(mkmap(fname, "a"));
1430 recorder.assertEvent(new String[] { fname }, ChangeRecorder.EMPTY);
1431 Status st = git.status().call();
1432 assertTrue(st.isClean());
1433 } finally {
1434 if (handle != null) {
1435 handle.remove();
1436 }
1437 }
1438 }
1439
1440 @Test
1441 public void testCheckoutOutChangesAutoCRLFfalse() throws IOException {
1442 setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
1443 checkout();
1444 assertIndex(mkmap("foo/bar", "foo\nbar"));
1445 assertWorkDir(mkmap("foo/bar", "foo\nbar"));
1446 }
1447
1448 @Test
1449 public void testCheckoutOutChangesAutoCRLFInput() throws IOException {
1450 setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
1451 db.getConfig().setString("core", null, "autocrlf", "input");
1452 checkout();
1453 assertIndex(mkmap("foo/bar", "foo\nbar"));
1454 assertWorkDir(mkmap("foo/bar", "foo\nbar"));
1455 }
1456
1457 @Test
1458 public void testCheckoutOutChangesAutoCRLFtrue() throws IOException {
1459 setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
1460 db.getConfig().setString("core", null, "autocrlf", "true");
1461 checkout();
1462 assertIndex(mkmap("foo/bar", "foo\nbar"));
1463 assertWorkDir(mkmap("foo/bar", "foo\r\nbar"));
1464 }
1465
1466 @Test
1467 public void testCheckoutOutChangesAutoCRLFtrueBinary() throws IOException {
1468 setupCase(mk("foo"), mkmap("foo/bar", "foo\nb\u0000ar"), mk("foo"));
1469 db.getConfig().setString("core", null, "autocrlf", "true");
1470 checkout();
1471 assertIndex(mkmap("foo/bar", "foo\nb\u0000ar"));
1472 assertWorkDir(mkmap("foo/bar", "foo\nb\u0000ar"));
1473 }
1474
1475 @Test
1476 public void testCheckoutUncachedChanges() throws IOException {
1477 setupCase(mk("foo"), mk("foo"), mk("foo"));
1478 writeTrashFile("foo", "otherData");
1479 checkout();
1480 assertIndex(mk("foo"));
1481 assertWorkDir(mkmap("foo", "otherData"));
1482 assertTrue(new File(trash, "foo").isFile());
1483 }
1484
1485 @Test
1486 public void testDontOverwriteDirtyFile() throws IOException {
1487 setupCase(mk("foo"), mk("other"), mk("foo"));
1488 writeTrashFile("foo", "different");
1489 try {
1490 checkout();
1491 fail("Didn't got the expected conflict");
1492 } catch (CheckoutConflictException e) {
1493 assertIndex(mk("foo"));
1494 assertWorkDir(mkmap("foo", "different"));
1495 assertEquals(Arrays.asList("foo"), getConflicts());
1496 assertTrue(new File(trash, "foo").isFile());
1497 }
1498 }
1499
1500 @Test
1501 public void testDontOverwriteEmptyFolder() throws IOException {
1502 setupCase(mk("foo"), mk("foo"), mk("foo"));
1503 FileUtils.mkdir(new File(db.getWorkTree(), "d"));
1504 checkout();
1505 assertWorkDir(mkmap("foo", "foo", "d", "/"));
1506 }
1507
1508 @Test
1509 public void testOverwriteUntrackedIgnoredFile() throws IOException,
1510 GitAPIException {
1511 String fname="file.txt";
1512 ChangeRecorder recorder = new ChangeRecorder();
1513 ListenerHandle handle = null;
1514 try (Git git = new Git(db)) {
1515 handle = db.getListenerList()
1516 .addWorkingTreeModifiedListener(recorder);
1517
1518 writeTrashFile(fname, "a");
1519 git.add().addFilepattern(fname).call();
1520 git.commit().setMessage("create file").call();
1521
1522
1523 git.branchCreate().setName("side").call();
1524
1525
1526 writeTrashFile(fname, "b");
1527 git.add().addFilepattern(fname).call();
1528 git.commit().setMessage("modify file").call();
1529 recorder.assertNoEvent();
1530
1531
1532 git.checkout().setName("side").call();
1533 recorder.assertEvent(new String[] { fname }, ChangeRecorder.EMPTY);
1534 git.rm().addFilepattern(fname).call();
1535 recorder.assertEvent(ChangeRecorder.EMPTY, new String[] { fname });
1536 writeTrashFile(".gitignore", fname);
1537 git.add().addFilepattern(".gitignore").call();
1538 git.commit().setMessage("delete and ignore file").call();
1539
1540 writeTrashFile(fname, "Something different");
1541 recorder.assertNoEvent();
1542 git.checkout().setName("master").call();
1543 assertWorkDir(mkmap(fname, "b"));
1544 recorder.assertEvent(new String[] { fname },
1545 new String[] { ".gitignore" });
1546 assertTrue(git.status().call().isClean());
1547 } finally {
1548 if (handle != null) {
1549 handle.remove();
1550 }
1551 }
1552 }
1553
1554 @Test
1555 public void testOverwriteUntrackedFileModeChange()
1556 throws IOException, GitAPIException {
1557 String fname = "file.txt";
1558 ChangeRecorder recorder = new ChangeRecorder();
1559 ListenerHandle handle = null;
1560 try (Git git = new Git(db)) {
1561 handle = db.getListenerList()
1562 .addWorkingTreeModifiedListener(recorder);
1563
1564 File file = writeTrashFile(fname, "a");
1565 git.add().addFilepattern(fname).call();
1566 git.commit().setMessage("create file").call();
1567 assertWorkDir(mkmap(fname, "a"));
1568
1569
1570 git.branchCreate().setName("side").call();
1571
1572
1573 git.checkout().setName("side").call();
1574 recorder.assertNoEvent();
1575
1576
1577 FileUtils.delete(file);
1578
1579
1580 writeTrashFile(fname + "/dir1", "file1", "c");
1581 git.add().addFilepattern(fname + "/dir1/file1").call();
1582
1583
1584 writeTrashFile(fname + "/dir2", "file2", "d");
1585
1586 assertTrue("File must be a directory now", file.isDirectory());
1587 assertFalse("Must not delete non empty directory", file.delete());
1588
1589
1590 assertWorkDir(mkmap(fname + "/dir1/file1", "c",
1591 fname + "/dir2/file2", "d"));
1592
1593 try {
1594 git.checkout().setName("master").call();
1595 fail("did not throw exception");
1596 } catch (Exception e) {
1597
1598 assertWorkDir(mkmap(fname + "/dir1/file1", "c",
1599 fname + "/dir2/file2", "d"));
1600 }
1601 recorder.assertNoEvent();
1602 } finally {
1603 if (handle != null) {
1604 handle.remove();
1605 }
1606 }
1607 }
1608
1609 @Test
1610 public void testOverwriteUntrackedLinkModeChange()
1611 throws Exception {
1612 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
1613 String fname = "file.txt";
1614 ChangeRecorder recorder = new ChangeRecorder();
1615 ListenerHandle handle = null;
1616 try (Git git = new Git(db)) {
1617 handle = db.getListenerList()
1618 .addWorkingTreeModifiedListener(recorder);
1619
1620 writeTrashFile(fname, "a");
1621 git.add().addFilepattern(fname).call();
1622
1623
1624 String linkName = "link";
1625 File link = writeLink(linkName, fname).toFile();
1626 git.add().addFilepattern(linkName).call();
1627 git.commit().setMessage("Added file and link").call();
1628
1629 assertWorkDir(mkmap(linkName, "a", fname, "a"));
1630
1631
1632 git.branchCreate().setName("side").call();
1633
1634
1635 git.checkout().setName("side").call();
1636 recorder.assertNoEvent();
1637
1638
1639 FileUtils.delete(link);
1640
1641
1642 writeTrashFile(linkName + "/dir1", "file1", "c");
1643 git.add().addFilepattern(linkName + "/dir1/file1").call();
1644
1645
1646 writeTrashFile(linkName + "/dir2", "file2", "d");
1647
1648 assertTrue("Link must be a directory now", link.isDirectory());
1649 assertFalse("Must not delete non empty directory", link.delete());
1650
1651
1652 assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
1653 linkName + "/dir2/file2", "d"));
1654
1655 try {
1656 git.checkout().setName("master").call();
1657 fail("did not throw exception");
1658 } catch (Exception e) {
1659
1660 assertWorkDir(mkmap(fname, "a", linkName + "/dir1/file1", "c",
1661 linkName + "/dir2/file2", "d"));
1662 }
1663 recorder.assertNoEvent();
1664 } finally {
1665 if (handle != null) {
1666 handle.remove();
1667 }
1668 }
1669 }
1670
1671 @Test
1672 public void testFileModeChangeWithNoContentChangeUpdate() throws Exception {
1673 if (!FS.DETECTED.supportsExecute())
1674 return;
1675
1676 ChangeRecorder recorder = new ChangeRecorder();
1677 ListenerHandle handle = null;
1678 try (Git git = new Git(db)) {
1679 handle = db.getListenerList()
1680 .addWorkingTreeModifiedListener(recorder);
1681
1682 File file = writeTrashFile("file.txt", "a");
1683 git.add().addFilepattern("file.txt").call();
1684 git.commit().setMessage("commit1").call();
1685 assertFalse(db.getFS().canExecute(file));
1686
1687
1688 git.branchCreate().setName("b1").call();
1689
1690
1691 db.getFS().setExecute(file, true);
1692 git.add().addFilepattern("file.txt").call();
1693 git.commit().setMessage("commit2").call();
1694 recorder.assertNoEvent();
1695
1696
1697 Status status = git.status().call();
1698 assertTrue(status.getModified().isEmpty());
1699 assertTrue(status.getChanged().isEmpty());
1700 assertTrue(db.getFS().canExecute(file));
1701
1702
1703 git.checkout().setName("b1").call();
1704
1705
1706 status = git.status().call();
1707 assertTrue(status.getModified().isEmpty());
1708 assertTrue(status.getChanged().isEmpty());
1709 assertFalse(db.getFS().canExecute(file));
1710 recorder.assertEvent(new String[] { "file.txt" },
1711 ChangeRecorder.EMPTY);
1712 } finally {
1713 if (handle != null) {
1714 handle.remove();
1715 }
1716 }
1717 }
1718
1719 @Test
1720 public void testFileModeChangeAndContentChangeConflict() throws Exception {
1721 if (!FS.DETECTED.supportsExecute())
1722 return;
1723
1724 ChangeRecorder recorder = new ChangeRecorder();
1725 ListenerHandle handle = null;
1726 try (Git git = new Git(db)) {
1727 handle = db.getListenerList()
1728 .addWorkingTreeModifiedListener(recorder);
1729
1730 File file = writeTrashFile("file.txt", "a");
1731 git.add().addFilepattern("file.txt").call();
1732 git.commit().setMessage("commit1").call();
1733 assertFalse(db.getFS().canExecute(file));
1734
1735
1736 git.branchCreate().setName("b1").call();
1737
1738
1739 db.getFS().setExecute(file, true);
1740 git.add().addFilepattern("file.txt").call();
1741 git.commit().setMessage("commit2").call();
1742
1743
1744 Status status = git.status().call();
1745 assertTrue(status.getModified().isEmpty());
1746 assertTrue(status.getChanged().isEmpty());
1747 assertTrue(db.getFS().canExecute(file));
1748
1749 writeTrashFile("file.txt", "b");
1750
1751
1752 CheckoutCommand checkout = git.checkout().setName("b1");
1753 try {
1754 checkout.call();
1755 fail("Checkout exception not thrown");
1756 } catch (org.eclipse.jgit.api.errors.CheckoutConflictException e) {
1757 CheckoutResult result = checkout.getResult();
1758 assertNotNull(result);
1759 assertNotNull(result.getConflictList());
1760 assertEquals(1, result.getConflictList().size());
1761 assertTrue(result.getConflictList().contains("file.txt"));
1762 }
1763 recorder.assertNoEvent();
1764 } finally {
1765 if (handle != null) {
1766 handle.remove();
1767 }
1768 }
1769 }
1770
1771 @Test
1772 public void testDirtyFileModeEqualHeadMerge()
1773 throws Exception {
1774 if (!FS.DETECTED.supportsExecute())
1775 return;
1776
1777 ChangeRecorder recorder = new ChangeRecorder();
1778 ListenerHandle handle = null;
1779 try (Git git = new Git(db)) {
1780 handle = db.getListenerList()
1781 .addWorkingTreeModifiedListener(recorder);
1782
1783 File file = writeTrashFile("file.txt", "a");
1784 git.add().addFilepattern("file.txt").call();
1785 git.commit().setMessage("commit1").call();
1786 assertFalse(db.getFS().canExecute(file));
1787
1788
1789 git.branchCreate().setName("b1").call();
1790
1791
1792 writeTrashFile("file2.txt", "");
1793 git.add().addFilepattern("file2.txt").call();
1794 git.commit().setMessage("commit2").call();
1795
1796
1797 writeTrashFile("file.txt", "a");
1798 db.getFS().setExecute(file, true);
1799 git.add().addFilepattern("file.txt").call();
1800
1801
1802 writeTrashFile("file.txt", "b");
1803
1804 assertEquals(
1805 "[file.txt, mode:100755, content:a][file2.txt, mode:100644, content:]",
1806 indexState(CONTENT));
1807 assertWorkDir(mkmap("file.txt", "b", "file2.txt", ""));
1808 recorder.assertNoEvent();
1809
1810
1811
1812 git.checkout().setName("b1").call();
1813 assertEquals("[file.txt, mode:100755, content:a]",
1814 indexState(CONTENT));
1815 assertWorkDir(mkmap("file.txt", "b"));
1816 recorder.assertEvent(ChangeRecorder.EMPTY,
1817 new String[] { "file2.txt" });
1818 } finally {
1819 if (handle != null) {
1820 handle.remove();
1821 }
1822 }
1823 }
1824
1825 @Test
1826 public void testDirtyFileModeEqualIndexMerge()
1827 throws Exception {
1828 if (!FS.DETECTED.supportsExecute())
1829 return;
1830
1831 ChangeRecorder recorder = new ChangeRecorder();
1832 ListenerHandle handle = null;
1833 try (Git git = new Git(db)) {
1834 handle = db.getListenerList()
1835 .addWorkingTreeModifiedListener(recorder);
1836
1837 File file = writeTrashFile("file.txt", "a");
1838 git.add().addFilepattern("file.txt").call();
1839 git.commit().setMessage("commit1").call();
1840 assertFalse(db.getFS().canExecute(file));
1841
1842
1843 git.branchCreate().setName("b1").call();
1844
1845
1846 file = writeTrashFile("file.txt", "b");
1847 db.getFS().setExecute(file, true);
1848 git.add().addFilepattern("file.txt").call();
1849 git.commit().setMessage("commit2").call();
1850
1851
1852 writeTrashFile("file.txt", "a");
1853 db.getFS().setExecute(file, false);
1854 git.add().addFilepattern("file.txt").call();
1855
1856
1857 writeTrashFile("file.txt", "c");
1858 db.getFS().setExecute(file, true);
1859
1860 assertEquals("[file.txt, mode:100644, content:a]",
1861 indexState(CONTENT));
1862 assertWorkDir(mkmap("file.txt", "c"));
1863 recorder.assertNoEvent();
1864
1865
1866
1867
1868 git.checkout().setName("b1").call();
1869 assertEquals("[file.txt, mode:100644, content:a]",
1870 indexState(CONTENT));
1871 assertWorkDir(mkmap("file.txt", "c"));
1872 recorder.assertNoEvent();
1873 } finally {
1874 if (handle != null) {
1875 handle.remove();
1876 }
1877 }
1878 }
1879
1880 @Test
1881 public void testFileModeChangeAndContentChangeNoConflict() throws Exception {
1882 if (!FS.DETECTED.supportsExecute())
1883 return;
1884
1885 ChangeRecorder recorder = new ChangeRecorder();
1886 ListenerHandle handle = null;
1887 try (Git git = new Git(db)) {
1888 handle = db.getListenerList()
1889 .addWorkingTreeModifiedListener(recorder);
1890
1891 File file1 = writeTrashFile("file1.txt", "a");
1892 git.add().addFilepattern("file1.txt").call();
1893 git.commit().setMessage("commit1").call();
1894 assertFalse(db.getFS().canExecute(file1));
1895
1896
1897 File file2 = writeTrashFile("file2.txt", "b");
1898 git.add().addFilepattern("file2.txt").call();
1899 git.commit().setMessage("commit2").call();
1900 assertFalse(db.getFS().canExecute(file2));
1901 recorder.assertNoEvent();
1902
1903
1904 assertNotNull(git.checkout().setCreateBranch(true).setName("b1")
1905 .setStartPoint(Constants.HEAD + "~1").call());
1906 recorder.assertEvent(ChangeRecorder.EMPTY,
1907 new String[] { "file2.txt" });
1908
1909
1910 file1 = writeTrashFile("file1.txt", "c");
1911 db.getFS().setExecute(file1, true);
1912 git.add().addFilepattern("file1.txt").call();
1913
1914
1915 assertNotNull(git.checkout().setName(Constants.MASTER).call());
1916 recorder.assertEvent(new String[] { "file2.txt" },
1917 ChangeRecorder.EMPTY);
1918 } finally {
1919 if (handle != null) {
1920 handle.remove();
1921 }
1922 }
1923 }
1924
1925 @Test(expected = CheckoutConflictException.class)
1926 public void testFolderFileConflict() throws Exception {
1927 RevCommit headCommit = commitFile("f/a", "initial content", "master");
1928 RevCommit checkoutCommit = commitFile("f/a", "side content", "side");
1929 FileUtils.delete(new File(db.getWorkTree(), "f"), FileUtils.RECURSIVE);
1930 writeTrashFile("f", "file instead of folder");
1931 new DirCacheCheckout(db, headCommit.getTree(), db.lockDirCache(),
1932 checkoutCommit.getTree()).checkout();
1933 }
1934
1935 @Test
1936 public void testMultipleContentConflicts() throws Exception {
1937 commitFile("a", "initial content", "master");
1938 RevCommit headCommit = commitFile("b", "initial content", "master");
1939 commitFile("a", "side content", "side");
1940 RevCommit checkoutCommit = commitFile("b", "side content", "side");
1941 writeTrashFile("a", "changed content");
1942 writeTrashFile("b", "changed content");
1943
1944 try {
1945 new DirCacheCheckout(db, headCommit.getTree(), db.lockDirCache(),
1946 checkoutCommit.getTree()).checkout();
1947 fail();
1948 } catch (CheckoutConflictException expected) {
1949 assertEquals(2, expected.getConflictingFiles().length);
1950 assertTrue(Arrays.asList(expected.getConflictingFiles())
1951 .contains("a"));
1952 assertTrue(Arrays.asList(expected.getConflictingFiles())
1953 .contains("b"));
1954 assertEquals("changed content", read("a"));
1955 assertEquals("changed content", read("b"));
1956 }
1957 }
1958
1959 @Test
1960 public void testFolderFileAndContentConflicts() throws Exception {
1961 RevCommit headCommit = commitFile("f/a", "initial content", "master");
1962 commitFile("b", "side content", "side");
1963 RevCommit checkoutCommit = commitFile("f/a", "side content", "side");
1964 FileUtils.delete(new File(db.getWorkTree(), "f"), FileUtils.RECURSIVE);
1965 writeTrashFile("f", "file instead of a folder");
1966 writeTrashFile("b", "changed content");
1967
1968 try {
1969 new DirCacheCheckout(db, headCommit.getTree(), db.lockDirCache(),
1970 checkoutCommit.getTree()).checkout();
1971 fail();
1972 } catch (CheckoutConflictException expected) {
1973 assertEquals(2, expected.getConflictingFiles().length);
1974 assertTrue(Arrays.asList(expected.getConflictingFiles())
1975 .contains("b"));
1976 assertTrue(Arrays.asList(expected.getConflictingFiles())
1977 .contains("f"));
1978 assertEquals("file instead of a folder", read("f"));
1979 assertEquals("changed content", read("b"));
1980 }
1981 }
1982
1983 @Test
1984 public void testLongFilename() throws Exception {
1985 char[] bytes = new char[253];
1986 Arrays.fill(bytes, 'f');
1987 String longFileName = new String(bytes);
1988
1989 doit(mkmap(longFileName, "a"), mkmap(longFileName, "b"),
1990 mkmap(longFileName, "a"));
1991 writeTrashFile(longFileName, "a");
1992 checkout();
1993 assertNoConflicts();
1994 assertUpdated(longFileName);
1995 }
1996
1997 @Test
1998 public void testIgnoredDirectory() throws Exception {
1999 writeTrashFile(".gitignore", "src/ignored");
2000 writeTrashFile("src/ignored/sub/foo.txt", "1");
2001 try (Git git = new Git(db)) {
2002 git.add().addFilepattern(".").call();
2003 RevCommit commit = git.commit().setMessage("adding .gitignore")
2004 .call();
2005 writeTrashFile("foo.txt", "2");
2006 writeTrashFile("zzz.txt", "3");
2007 git.add().addFilepattern("foo.txt").call();
2008 git.commit().setMessage("add file").call();
2009 assertEquals("Should not have entered ignored directory", 1,
2010 resetHardAndCount(commit));
2011 }
2012 }
2013
2014 @Test
2015 public void testIgnoredDirectoryWithTrackedContent() throws Exception {
2016 writeTrashFile("src/ignored/sub/foo.txt", "1");
2017 try (Git git = new Git(db)) {
2018 git.add().addFilepattern(".").call();
2019 git.commit().setMessage("adding foo.txt").call();
2020 writeTrashFile(".gitignore", "src/ignored");
2021 writeTrashFile("src/ignored/sub/foo.txt", "2");
2022 writeTrashFile("src/ignored/other/bar.txt", "3");
2023 git.add().addFilepattern(".").call();
2024 RevCommit commit = git.commit().setMessage("adding .gitignore")
2025 .call();
2026 writeTrashFile("foo.txt", "2");
2027 writeTrashFile("zzz.txt", "3");
2028 git.add().addFilepattern("foo.txt").call();
2029 git.commit().setMessage("add file").call();
2030 File file = writeTrashFile("src/ignored/sub/foo.txt", "3");
2031 assertEquals("Should have entered ignored directory", 3,
2032 resetHardAndCount(commit));
2033 checkFile(file, "2");
2034 }
2035 }
2036
2037 @Test
2038 public void testResetWithChangeInGitignore() throws Exception {
2039 writeTrashFile(".gitignore", "src/ignored");
2040 writeTrashFile("src/ignored/sub/foo.txt", "1");
2041 try (Git git = new Git(db)) {
2042 git.add().addFilepattern(".").call();
2043 RevCommit initial = git.commit().setMessage("initial").call();
2044 writeTrashFile("src/newignored/foo.txt", "2");
2045 writeTrashFile("src/.gitignore", "newignored");
2046 git.add().addFilepattern(".").call();
2047 RevCommit commit = git.commit().setMessage("newignored").call();
2048 assertEquals("Should not have entered src/newignored directory", 1,
2049 resetHardAndCount(initial));
2050 assertEquals("Should have entered src/newignored directory", 2,
2051 resetHardAndCount(commit));
2052 deleteTrashFile("src/.gitignore");
2053 git.rm().addFilepattern("src/.gitignore").call();
2054 RevCommit top = git.commit().setMessage("Unignore newignore")
2055 .call();
2056 assertEquals("Should have entered src/newignored directory", 2,
2057 resetHardAndCount(initial));
2058 assertEquals("Should have entered src/newignored directory", 2,
2059 resetHardAndCount(commit));
2060 assertEquals("Should not have entered src/newignored directory", 1,
2061 resetHardAndCount(top));
2062
2063 }
2064 }
2065
2066 @Test
2067 public void testCheckoutWithEmptyIndexDoesntOverwrite() throws Exception {
2068 try (Git git = new Git(db);
2069 TestRepository<Repository> db_t = new TestRepository<>(db)) {
2070 db.incrementOpen();
2071
2072 BranchBuilder master = db_t.branch("master");
2073 RevCommit mergeCommit = master.commit()
2074 .add("p/x", "headContent")
2075 .message("m0").create();
2076 master.commit().add("p/x", "headContent").message("m1").create();
2077 git.checkout().setName("master").call();
2078
2079
2080 git.rm().addFilepattern("p").call();
2081 writeTrashFile("p", "important data");
2082
2083 git.checkout().setName(mergeCommit.getName()).call();
2084
2085 assertEquals("", indexState(CONTENT));
2086 assertEquals("important data", read("p"));
2087 }
2088 }
2089
2090 private static class TestFileTreeIterator extends FileTreeIterator {
2091
2092
2093 private final int[] count;
2094
2095 public TestFileTreeIterator(Repository repo, int[] count) {
2096 super(repo);
2097 this.count = count;
2098 }
2099
2100 protected TestFileTreeIterator(final WorkingTreeIterator p,
2101 final File root, FS fs, FileModeStrategy fileModeStrategy,
2102 int[] count) {
2103 super(p, root, fs, fileModeStrategy);
2104 this.count = count;
2105 }
2106
2107 @Override
2108 protected AbstractTreeIterator enterSubtree() {
2109 count[0] += 1;
2110 return new TestFileTreeIterator(this,
2111 ((FileEntry) current()).getFile(), fs, fileModeStrategy,
2112 count);
2113 }
2114 }
2115
2116 private int resetHardAndCount(RevCommit commit) throws Exception {
2117 int[] callCount = { 0 };
2118 DirCache cache = db.lockDirCache();
2119 FileTreeIterator workingTreeIterator = new TestFileTreeIterator(db,
2120 callCount);
2121 try {
2122 DirCacheCheckout checkout = new DirCacheCheckout(db, null, cache,
2123 commit.getTree().getId(), workingTreeIterator);
2124 checkout.setFailOnConflict(false);
2125 checkout.checkout();
2126 } finally {
2127 cache.unlock();
2128 }
2129 return callCount[0];
2130 }
2131
2132 public void assertWorkDir(Map<String, String> i)
2133 throws CorruptObjectException,
2134 IOException {
2135 try (TreeWalk walk = new TreeWalk(db)) {
2136 walk.setRecursive(false);
2137 walk.addTree(new FileTreeIterator(db));
2138 String expectedValue;
2139 String path;
2140 int nrFiles = 0;
2141 FileTreeIterator ft;
2142 while (walk.next()) {
2143 ft = walk.getTree(0, FileTreeIterator.class);
2144 path = ft.getEntryPathString();
2145 expectedValue = i.get(path);
2146 File file = new File(db.getWorkTree(), path);
2147 assertTrue(file.exists());
2148 if (file.isFile()) {
2149 assertNotNull("found unexpected file for path " + path
2150 + " in workdir", expectedValue);
2151 try (FileInputStream is = new FileInputStream(file)) {
2152 byte[] buffer = new byte[(int) file.length()];
2153 int offset = 0;
2154 int numRead = 0;
2155 while (offset < buffer.length
2156 && (numRead = is.read(buffer, offset,
2157 buffer.length - offset)) >= 0) {
2158 offset += numRead;
2159 }
2160 assertArrayEquals(
2161 "unexpected content for path " + path
2162 + " in workDir. ",
2163 buffer, i.get(path).getBytes(UTF_8));
2164 }
2165 nrFiles++;
2166 } else if (file.isDirectory()) {
2167 String[] files = file.list();
2168 if (files != null && files.length == 0) {
2169 assertEquals("found unexpected empty folder for path "
2170 + path + " in workDir. ", "/", i.get(path));
2171 nrFiles++;
2172 }
2173 }
2174 if (walk.isSubtree()) {
2175 walk.enterSubtree();
2176 }
2177 }
2178 assertEquals("WorkDir has not the right size.", i.size(), nrFiles);
2179 }
2180 }
2181 }