1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 package org.eclipse.jgit.merge;
46
47 import static org.eclipse.jgit.lib.Constants.CHARACTER_ENCODING;
48 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
49
50 import java.io.BufferedOutputStream;
51 import java.io.File;
52 import java.io.FileInputStream;
53 import java.io.FileNotFoundException;
54 import java.io.FileOutputStream;
55 import java.io.IOException;
56 import java.io.InputStream;
57 import java.io.OutputStream;
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.Collections;
61 import java.util.HashMap;
62 import java.util.Iterator;
63 import java.util.LinkedList;
64 import java.util.List;
65 import java.util.Map;
66
67 import org.eclipse.jgit.diff.DiffAlgorithm;
68 import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm;
69 import org.eclipse.jgit.diff.RawText;
70 import org.eclipse.jgit.diff.RawTextComparator;
71 import org.eclipse.jgit.diff.Sequence;
72 import org.eclipse.jgit.dircache.DirCache;
73 import org.eclipse.jgit.dircache.DirCacheBuildIterator;
74 import org.eclipse.jgit.dircache.DirCacheBuilder;
75 import org.eclipse.jgit.dircache.DirCacheCheckout;
76 import org.eclipse.jgit.dircache.DirCacheEntry;
77 import org.eclipse.jgit.errors.CorruptObjectException;
78 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
79 import org.eclipse.jgit.errors.IndexWriteException;
80 import org.eclipse.jgit.errors.MissingObjectException;
81 import org.eclipse.jgit.errors.NoWorkTreeException;
82 import org.eclipse.jgit.lib.ConfigConstants;
83 import org.eclipse.jgit.lib.FileMode;
84 import org.eclipse.jgit.lib.ObjectId;
85 import org.eclipse.jgit.lib.ObjectReader;
86 import org.eclipse.jgit.lib.Repository;
87 import org.eclipse.jgit.revwalk.RevTree;
88 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
89 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
90 import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
91 import org.eclipse.jgit.treewalk.TreeWalk;
92 import org.eclipse.jgit.treewalk.WorkingTreeIterator;
93 import org.eclipse.jgit.treewalk.filter.TreeFilter;
94 import org.eclipse.jgit.util.FS;
95 import org.eclipse.jgit.util.TemporaryBuffer;
96
97
98
99
100 public class ResolveMerger extends ThreeWayMerger {
101
102
103
104
105 public enum MergeFailureReason {
106
107 DIRTY_INDEX,
108
109 DIRTY_WORKTREE,
110
111 COULD_NOT_DELETE
112 }
113
114
115
116
117
118
119 protected NameConflictTreeWalk tw;
120
121
122
123
124
125
126 protected String commitNames[];
127
128
129
130
131
132
133 protected static final int T_BASE = 0;
134
135
136
137
138
139
140 protected static final int T_OURS = 1;
141
142
143
144
145
146
147 protected static final int T_THEIRS = 2;
148
149
150
151
152
153
154 protected static final int T_INDEX = 3;
155
156
157
158
159
160
161 protected static final int T_FILE = 4;
162
163
164
165
166
167
168 protected DirCacheBuilder builder;
169
170
171
172
173
174
175 protected ObjectId resultTree;
176
177
178
179
180
181
182
183 protected List<String> unmergedPaths = new ArrayList<String>();
184
185
186
187
188
189
190 protected List<String> modifiedFiles = new LinkedList<String>();
191
192
193
194
195
196
197
198 protected Map<String, DirCacheEntry> toBeCheckedOut = new HashMap<String, DirCacheEntry>();
199
200
201
202
203
204
205
206 protected List<String> toBeDeleted = new ArrayList<String>();
207
208
209
210
211
212
213
214 protected Map<String, MergeResult<? extends Sequence>> mergeResults = new HashMap<String, MergeResult<? extends Sequence>>();
215
216
217
218
219
220
221 protected Map<String, MergeFailureReason> failingPaths = new HashMap<String, MergeFailureReason>();
222
223
224
225
226
227
228
229 protected boolean enterSubtree;
230
231
232
233
234
235
236
237
238
239 protected boolean inCore;
240
241
242
243
244
245
246
247
248 protected boolean implicitDirCache;
249
250
251
252
253
254 protected DirCache dircache;
255
256
257
258
259
260
261 protected WorkingTreeIterator workingTreeIterator;
262
263
264
265
266
267 protected MergeAlgorithm mergeAlgorithm;
268
269
270
271
272
273 protected ResolveMerger(Repository local, boolean inCore) {
274 super(local);
275 SupportedAlgorithm diffAlg = local.getConfig().getEnum(
276 ConfigConstants.CONFIG_DIFF_SECTION, null,
277 ConfigConstants.CONFIG_KEY_ALGORITHM,
278 SupportedAlgorithm.HISTOGRAM);
279 mergeAlgorithm = new MergeAlgorithm(DiffAlgorithm.getAlgorithm(diffAlg));
280 commitNames = new String[] { "BASE", "OURS", "THEIRS" };
281 this.inCore = inCore;
282
283 if (inCore) {
284 implicitDirCache = false;
285 dircache = DirCache.newInCore();
286 } else {
287 implicitDirCache = true;
288 }
289 }
290
291
292
293
294 protected ResolveMerger(Repository local) {
295 this(local, false);
296 }
297
298 @Override
299 protected boolean mergeImpl() throws IOException {
300 if (implicitDirCache)
301 dircache = getRepository().lockDirCache();
302
303 try {
304 return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1],
305 false);
306 } finally {
307 if (implicitDirCache)
308 dircache.unlock();
309 }
310 }
311
312 private void checkout() throws NoWorkTreeException, IOException {
313
314
315
316 for (int i = toBeDeleted.size() - 1; i >= 0; i--) {
317 String fileName = toBeDeleted.get(i);
318 File f = new File(db.getWorkTree(), fileName);
319 if (!f.delete())
320 if (!f.isDirectory())
321 failingPaths.put(fileName,
322 MergeFailureReason.COULD_NOT_DELETE);
323 modifiedFiles.add(fileName);
324 }
325 for (Map.Entry<String, DirCacheEntry> entry : toBeCheckedOut
326 .entrySet()) {
327 DirCacheCheckout.checkoutEntry(db, entry.getValue(), reader);
328 modifiedFiles.add(entry.getKey());
329 }
330 }
331
332
333
334
335
336
337
338
339
340
341
342
343 protected void cleanUp() throws NoWorkTreeException,
344 CorruptObjectException,
345 IOException {
346 if (inCore) {
347 modifiedFiles.clear();
348 return;
349 }
350
351 DirCache dc = db.readDirCache();
352 Iterator<String> mpathsIt=modifiedFiles.iterator();
353 while(mpathsIt.hasNext()) {
354 String mpath=mpathsIt.next();
355 DirCacheEntry entry = dc.getEntry(mpath);
356 if (entry != null)
357 DirCacheCheckout.checkoutEntry(db, entry, reader);
358 mpathsIt.remove();
359 }
360 }
361
362
363
364
365
366
367
368
369
370
371
372 private DirCacheEntry add(byte[] path, CanonicalTreeParser p, int stage,
373 long lastMod, long len) {
374 if (p != null && !p.getEntryFileMode().equals(FileMode.TREE)) {
375 DirCacheEntry e = new DirCacheEntry(path, stage);
376 e.setFileMode(p.getEntryFileMode());
377 e.setObjectId(p.getEntryObjectId());
378 e.setLastModified(lastMod);
379 e.setLength(len);
380 builder.add(e);
381 return e;
382 }
383 return null;
384 }
385
386
387
388
389
390
391
392
393
394
395 private DirCacheEntry keep(DirCacheEntry e) {
396 DirCacheEntry newEntry = new DirCacheEntry(e.getPathString(),
397 e.getStage());
398 newEntry.setFileMode(e.getFileMode());
399 newEntry.setObjectId(e.getObjectId());
400 newEntry.setLastModified(e.getLastModified());
401 newEntry.setLength(e.getLength());
402 builder.add(newEntry);
403 return newEntry;
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450 protected boolean processEntry(CanonicalTreeParser base,
451 CanonicalTreeParser ours, CanonicalTreeParser theirs,
452 DirCacheBuildIterator index, WorkingTreeIterator work,
453 boolean ignoreConflicts)
454 throws MissingObjectException, IncorrectObjectTypeException,
455 CorruptObjectException, IOException {
456 enterSubtree = true;
457 final int modeO = tw.getRawMode(T_OURS);
458 final int modeT = tw.getRawMode(T_THEIRS);
459 final int modeB = tw.getRawMode(T_BASE);
460
461 if (modeO == 0 && modeT == 0 && modeB == 0)
462
463 return true;
464
465 if (isIndexDirty())
466 return false;
467
468 DirCacheEntry ourDce = null;
469
470 if (index == null || index.getDirCacheEntry() == null) {
471
472
473 if (nonTree(modeO)) {
474 ourDce = new DirCacheEntry(tw.getRawPath());
475 ourDce.setObjectId(tw.getObjectId(T_OURS));
476 ourDce.setFileMode(tw.getFileMode(T_OURS));
477 }
478 } else {
479 ourDce = index.getDirCacheEntry();
480 }
481
482 if (nonTree(modeO) && nonTree(modeT) && tw.idEqual(T_OURS, T_THEIRS)) {
483
484 if (modeO == modeT) {
485
486
487
488 keep(ourDce);
489
490 return true;
491 } else {
492
493
494
495 int newMode = mergeFileModes(modeB, modeO, modeT);
496 if (newMode != FileMode.MISSING.getBits()) {
497 if (newMode == modeO)
498
499 keep(ourDce);
500 else {
501
502
503 if (isWorktreeDirty(work, ourDce))
504 return false;
505
506
507 DirCacheEntry e = add(tw.getRawPath(), theirs,
508 DirCacheEntry.STAGE_0, 0, 0);
509 toBeCheckedOut.put(tw.getPathString(), e);
510 }
511 return true;
512 } else {
513
514
515 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
516 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
517 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
518 unmergedPaths.add(tw.getPathString());
519 mergeResults.put(
520 tw.getPathString(),
521 new MergeResult<RawText>(Collections
522 .<RawText> emptyList()));
523 }
524 return true;
525 }
526 }
527
528 if (nonTree(modeO) && modeB == modeT && tw.idEqual(T_BASE, T_THEIRS)) {
529
530
531 keep(ourDce);
532
533 return true;
534 }
535
536 if (modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
537
538
539
540
541 if (isWorktreeDirty(work, ourDce))
542 return false;
543 if (nonTree(modeT)) {
544
545
546
547 DirCacheEntry e = add(tw.getRawPath(), theirs,
548 DirCacheEntry.STAGE_0, 0, 0);
549 if (e != null)
550 toBeCheckedOut.put(tw.getPathString(), e);
551 return true;
552 } else if (modeT == 0 && modeB != 0) {
553
554
555
556
557 if (tw.getTreeCount() > T_FILE && tw.getRawMode(T_FILE) == 0)
558 return true;
559 toBeDeleted.add(tw.getPathString());
560 return true;
561 }
562 }
563
564 if (tw.isSubtree()) {
565
566
567
568
569 if (nonTree(modeO) && !nonTree(modeT)) {
570 if (nonTree(modeB))
571 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
572 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
573 unmergedPaths.add(tw.getPathString());
574 enterSubtree = false;
575 return true;
576 }
577 if (nonTree(modeT) && !nonTree(modeO)) {
578 if (nonTree(modeB))
579 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
580 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
581 unmergedPaths.add(tw.getPathString());
582 enterSubtree = false;
583 return true;
584 }
585
586
587
588
589
590 if (!nonTree(modeO))
591 return true;
592
593
594
595 }
596
597 if (nonTree(modeO) && nonTree(modeT)) {
598
599 if (isWorktreeDirty(work, ourDce))
600 return false;
601
602
603 if (isGitLink(modeO) || isGitLink(modeT)) {
604 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
605 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
606 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
607 unmergedPaths.add(tw.getPathString());
608 return true;
609 }
610
611 MergeResult<RawText> result = contentMerge(base, ours, theirs);
612 if (ignoreConflicts)
613 result.setContainsConflicts(false);
614 updateIndex(base, ours, theirs, result);
615 if (result.containsConflicts() && !ignoreConflicts)
616 unmergedPaths.add(tw.getPathString());
617 modifiedFiles.add(tw.getPathString());
618 } else if (modeO != modeT) {
619
620 if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw
621 .idEqual(T_BASE, T_THEIRS)))) {
622
623 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
624 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
625 DirCacheEntry e = add(tw.getRawPath(), theirs,
626 DirCacheEntry.STAGE_3, 0, 0);
627
628
629 if (modeO == 0) {
630
631 if (isWorktreeDirty(work, ourDce))
632 return false;
633 if (nonTree(modeT)) {
634 if (e != null)
635 toBeCheckedOut.put(tw.getPathString(), e);
636 }
637 }
638
639 unmergedPaths.add(tw.getPathString());
640
641
642 mergeResults.put(tw.getPathString(),
643 contentMerge(base, ours, theirs));
644 }
645 }
646 return true;
647 }
648
649
650
651
652
653
654
655
656
657
658
659
660
661 private MergeResult<RawText> contentMerge(CanonicalTreeParser base,
662 CanonicalTreeParser ours, CanonicalTreeParser theirs)
663 throws IOException {
664 RawText baseText = base == null ? RawText.EMPTY_TEXT : getRawText(
665 base.getEntryObjectId(), reader);
666 RawText ourText = ours == null ? RawText.EMPTY_TEXT : getRawText(
667 ours.getEntryObjectId(), reader);
668 RawText theirsText = theirs == null ? RawText.EMPTY_TEXT : getRawText(
669 theirs.getEntryObjectId(), reader);
670 return (mergeAlgorithm.merge(RawTextComparator.DEFAULT, baseText,
671 ourText, theirsText));
672 }
673
674 private boolean isIndexDirty() {
675 if (inCore)
676 return false;
677
678 final int modeI = tw.getRawMode(T_INDEX);
679 final int modeO = tw.getRawMode(T_OURS);
680
681
682 final boolean isDirty = nonTree(modeI)
683 && !(modeO == modeI && tw.idEqual(T_INDEX, T_OURS));
684 if (isDirty)
685 failingPaths
686 .put(tw.getPathString(), MergeFailureReason.DIRTY_INDEX);
687 return isDirty;
688 }
689
690 private boolean isWorktreeDirty(WorkingTreeIterator work,
691 DirCacheEntry ourDce) throws IOException {
692 if (work == null)
693 return false;
694
695 final int modeF = tw.getRawMode(T_FILE);
696 final int modeO = tw.getRawMode(T_OURS);
697
698
699 boolean isDirty;
700 if (ourDce != null)
701 isDirty = work.isModified(ourDce, true, reader);
702 else {
703 isDirty = work.isModeDifferent(modeO);
704 if (!isDirty && nonTree(modeF))
705 isDirty = !tw.idEqual(T_FILE, T_OURS);
706 }
707
708
709 if (isDirty && modeF == FileMode.TYPE_TREE
710 && modeO == FileMode.TYPE_MISSING)
711 isDirty = false;
712 if (isDirty)
713 failingPaths.put(tw.getPathString(),
714 MergeFailureReason.DIRTY_WORKTREE);
715 return isDirty;
716 }
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731 private void updateIndex(CanonicalTreeParser base,
732 CanonicalTreeParser ours, CanonicalTreeParser theirs,
733 MergeResult<RawText> result) throws FileNotFoundException,
734 IOException {
735 File mergedFile = !inCore ? writeMergedFile(result) : null;
736 if (result.containsConflicts()) {
737
738
739
740 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
741 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
742 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
743 mergeResults.put(tw.getPathString(), result);
744 return;
745 }
746
747
748
749 DirCacheEntry dce = new DirCacheEntry(tw.getPathString());
750
751
752
753 int newMode = mergeFileModes(
754 tw.getRawMode(0),
755 tw.getRawMode(1),
756 tw.getRawMode(2));
757 dce.setFileMode(newMode == FileMode.MISSING.getBits()
758 ? FileMode.REGULAR_FILE
759 : FileMode.fromBits(newMode));
760 if (mergedFile != null) {
761 long len = mergedFile.length();
762 dce.setLastModified(mergedFile.lastModified());
763 dce.setLength((int) len);
764 InputStream is = new FileInputStream(mergedFile);
765 try {
766 dce.setObjectId(getObjectInserter().insert(OBJ_BLOB, len, is));
767 } finally {
768 is.close();
769 }
770 } else
771 dce.setObjectId(insertMergeResult(result));
772 builder.add(dce);
773 }
774
775
776
777
778
779
780
781
782
783
784 private File writeMergedFile(MergeResult<RawText> result)
785 throws FileNotFoundException, IOException {
786 File workTree = db.getWorkTree();
787 if (workTree == null)
788
789
790 throw new UnsupportedOperationException();
791
792 FS fs = db.getFS();
793 File of = new File(workTree, tw.getPathString());
794 File parentFolder = of.getParentFile();
795 if (!fs.exists(parentFolder))
796 parentFolder.mkdirs();
797 try (OutputStream os = new BufferedOutputStream(
798 new FileOutputStream(of))) {
799 new MergeFormatter().formatMerge(os, result,
800 Arrays.asList(commitNames), CHARACTER_ENCODING);
801 }
802 return of;
803 }
804
805 private ObjectId insertMergeResult(MergeResult<RawText> result)
806 throws IOException {
807 TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile(
808 db.getDirectory(), 10 << 20);
809 try {
810 new MergeFormatter().formatMerge(buf, result,
811 Arrays.asList(commitNames), CHARACTER_ENCODING);
812 buf.close();
813 try (InputStream in = buf.openInputStream()) {
814 return getObjectInserter().insert(OBJ_BLOB, buf.length(), in);
815 }
816 } finally {
817 buf.destroy();
818 }
819 }
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837 private int mergeFileModes(int modeB, int modeO, int modeT) {
838 if (modeO == modeT)
839 return modeO;
840 if (modeB == modeO)
841
842 return (modeT == FileMode.MISSING.getBits()) ? modeO : modeT;
843 if (modeB == modeT)
844
845 return (modeO == FileMode.MISSING.getBits()) ? modeT : modeO;
846 return FileMode.MISSING.getBits();
847 }
848
849 private static RawText getRawText(ObjectId id, ObjectReader reader)
850 throws IOException {
851 if (id.equals(ObjectId.zeroId()))
852 return new RawText(new byte[] {});
853 return new RawText(reader.open(id, OBJ_BLOB).getCachedBytes());
854 }
855
856 private static boolean nonTree(final int mode) {
857 return mode != 0 && !FileMode.TREE.equals(mode);
858 }
859
860 private static boolean isGitLink(final int mode) {
861 return FileMode.GITLINK.equals(mode);
862 }
863
864 @Override
865 public ObjectId getResultTreeId() {
866 return (resultTree == null) ? null : resultTree.toObjectId();
867 }
868
869
870
871
872
873
874 public void setCommitNames(String[] commitNames) {
875 this.commitNames = commitNames;
876 }
877
878
879
880
881
882 public String[] getCommitNames() {
883 return commitNames;
884 }
885
886
887
888
889
890 public List<String> getUnmergedPaths() {
891 return unmergedPaths;
892 }
893
894
895
896
897
898
899
900 public List<String> getModifiedFiles() {
901 return modifiedFiles;
902 }
903
904
905
906
907
908
909
910 public Map<String, DirCacheEntry> getToBeCheckedOut() {
911 return toBeCheckedOut;
912 }
913
914
915
916
917 public Map<String, MergeResult<? extends Sequence>> getMergeResults() {
918 return mergeResults;
919 }
920
921
922
923
924
925
926 public Map<String, MergeFailureReason> getFailingPaths() {
927 return (failingPaths.size() == 0) ? null : failingPaths;
928 }
929
930
931
932
933
934
935
936
937 public boolean failed() {
938 return failingPaths.size() > 0;
939 }
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954 public void setDirCache(DirCache dc) {
955 this.dircache = dc;
956 implicitDirCache = false;
957 }
958
959
960
961
962
963
964
965
966
967
968
969
970 public void setWorkingTreeIterator(WorkingTreeIterator workingTreeIterator) {
971 this.workingTreeIterator = workingTreeIterator;
972 }
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004 protected boolean mergeTrees(AbstractTreeIterator baseTree,
1005 RevTree headTree, RevTree mergeTree, boolean ignoreConflicts)
1006 throws IOException {
1007
1008 builder = dircache.builder();
1009 DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder);
1010
1011 tw = new NameConflictTreeWalk(reader);
1012 tw.addTree(baseTree);
1013 tw.addTree(headTree);
1014 tw.addTree(mergeTree);
1015 tw.addTree(buildIt);
1016 if (workingTreeIterator != null) {
1017 tw.addTree(workingTreeIterator);
1018 } else {
1019 tw.setFilter(TreeFilter.ANY_DIFF);
1020 }
1021
1022 if (!mergeTreeWalk(tw, ignoreConflicts)) {
1023 return false;
1024 }
1025
1026 if (!inCore) {
1027
1028
1029
1030 checkout();
1031
1032
1033
1034
1035
1036 if (!builder.commit()) {
1037 cleanUp();
1038 throw new IndexWriteException();
1039 }
1040 builder = null;
1041
1042 } else {
1043 builder.finish();
1044 builder = null;
1045 }
1046
1047 if (getUnmergedPaths().isEmpty() && !failed()) {
1048 resultTree = dircache.writeTree(getObjectInserter());
1049 return true;
1050 } else {
1051 resultTree = null;
1052 return false;
1053 }
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 protected boolean mergeTreeWalk(TreeWalk treeWalk, boolean ignoreConflicts)
1069 throws IOException {
1070 boolean hasWorkingTreeIterator = tw.getTreeCount() > T_FILE;
1071 while (treeWalk.next()) {
1072 if (!processEntry(
1073 treeWalk.getTree(T_BASE, CanonicalTreeParser.class),
1074 treeWalk.getTree(T_OURS, CanonicalTreeParser.class),
1075 treeWalk.getTree(T_THEIRS, CanonicalTreeParser.class),
1076 treeWalk.getTree(T_INDEX, DirCacheBuildIterator.class),
1077 hasWorkingTreeIterator ? treeWalk.getTree(T_FILE,
1078 WorkingTreeIterator.class) : null, ignoreConflicts)) {
1079 cleanUp();
1080 return false;
1081 }
1082 if (treeWalk.isSubtree() && enterSubtree)
1083 treeWalk.enterSubtree();
1084 }
1085 return true;
1086 }
1087 }