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