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