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 (modeB == modeT && tw.idEqual(T_BASE, T_THEIRS)) {
529
530
531 if (ourDce != null)
532 keep(ourDce);
533
534 return true;
535 }
536
537 if (modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
538
539
540
541
542 if (isWorktreeDirty(work, ourDce))
543 return false;
544 if (nonTree(modeT)) {
545
546
547
548 DirCacheEntry e = add(tw.getRawPath(), theirs,
549 DirCacheEntry.STAGE_0, 0, 0);
550 if (e != null)
551 toBeCheckedOut.put(tw.getPathString(), e);
552 return true;
553 } else {
554
555
556
557
558
559 if (tw.getTreeCount() > T_FILE && tw.getRawMode(T_FILE) == 0)
560 return true;
561 toBeDeleted.add(tw.getPathString());
562 return true;
563 }
564 }
565
566 if (tw.isSubtree()) {
567
568
569
570
571 if (nonTree(modeO) && !nonTree(modeT)) {
572 if (nonTree(modeB))
573 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
574 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
575 unmergedPaths.add(tw.getPathString());
576 enterSubtree = false;
577 return true;
578 }
579 if (nonTree(modeT) && !nonTree(modeO)) {
580 if (nonTree(modeB))
581 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
582 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
583 unmergedPaths.add(tw.getPathString());
584 enterSubtree = false;
585 return true;
586 }
587
588
589
590
591
592 if (!nonTree(modeO))
593 return true;
594
595
596
597 }
598
599 if (nonTree(modeO) && nonTree(modeT)) {
600
601 if (isWorktreeDirty(work, ourDce))
602 return false;
603
604
605 if (isGitLink(modeO) || isGitLink(modeT)) {
606 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
607 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
608 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
609 unmergedPaths.add(tw.getPathString());
610 return true;
611 }
612
613 MergeResult<RawText> result = contentMerge(base, ours, theirs);
614 if (ignoreConflicts)
615 result.setContainsConflicts(false);
616 updateIndex(base, ours, theirs, result);
617 if (result.containsConflicts() && !ignoreConflicts)
618 unmergedPaths.add(tw.getPathString());
619 modifiedFiles.add(tw.getPathString());
620 } else if (modeO != modeT) {
621
622 if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw
623 .idEqual(T_BASE, T_THEIRS)))) {
624
625 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
626 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
627 DirCacheEntry e = add(tw.getRawPath(), theirs,
628 DirCacheEntry.STAGE_3, 0, 0);
629
630
631 if (modeO == 0) {
632
633 if (isWorktreeDirty(work, ourDce))
634 return false;
635 if (nonTree(modeT)) {
636 if (e != null)
637 toBeCheckedOut.put(tw.getPathString(), e);
638 }
639 }
640
641 unmergedPaths.add(tw.getPathString());
642
643
644 mergeResults.put(tw.getPathString(),
645 contentMerge(base, ours, theirs));
646 }
647 }
648 return true;
649 }
650
651
652
653
654
655
656
657
658
659
660
661
662
663 private MergeResult<RawText> contentMerge(CanonicalTreeParser base,
664 CanonicalTreeParser ours, CanonicalTreeParser theirs)
665 throws IOException {
666 RawText baseText = base == null ? RawText.EMPTY_TEXT : getRawText(
667 base.getEntryObjectId(), reader);
668 RawText ourText = ours == null ? RawText.EMPTY_TEXT : getRawText(
669 ours.getEntryObjectId(), reader);
670 RawText theirsText = theirs == null ? RawText.EMPTY_TEXT : getRawText(
671 theirs.getEntryObjectId(), reader);
672 return (mergeAlgorithm.merge(RawTextComparator.DEFAULT, baseText,
673 ourText, theirsText));
674 }
675
676 private boolean isIndexDirty() {
677 if (inCore)
678 return false;
679
680 final int modeI = tw.getRawMode(T_INDEX);
681 final int modeO = tw.getRawMode(T_OURS);
682
683
684 final boolean isDirty = nonTree(modeI)
685 && !(modeO == modeI && tw.idEqual(T_INDEX, T_OURS));
686 if (isDirty)
687 failingPaths
688 .put(tw.getPathString(), MergeFailureReason.DIRTY_INDEX);
689 return isDirty;
690 }
691
692 private boolean isWorktreeDirty(WorkingTreeIterator work,
693 DirCacheEntry ourDce) throws IOException {
694 if (work == null)
695 return false;
696
697 final int modeF = tw.getRawMode(T_FILE);
698 final int modeO = tw.getRawMode(T_OURS);
699
700
701 boolean isDirty;
702 if (ourDce != null)
703 isDirty = work.isModified(ourDce, true, reader);
704 else {
705 isDirty = work.isModeDifferent(modeO);
706 if (!isDirty && nonTree(modeF))
707 isDirty = !tw.idEqual(T_FILE, T_OURS);
708 }
709
710
711 if (isDirty && modeF == FileMode.TYPE_TREE
712 && modeO == FileMode.TYPE_MISSING)
713 isDirty = false;
714 if (isDirty)
715 failingPaths.put(tw.getPathString(),
716 MergeFailureReason.DIRTY_WORKTREE);
717 return isDirty;
718 }
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733 private void updateIndex(CanonicalTreeParser base,
734 CanonicalTreeParser ours, CanonicalTreeParser theirs,
735 MergeResult<RawText> result) throws FileNotFoundException,
736 IOException {
737 File mergedFile = !inCore ? writeMergedFile(result) : null;
738 if (result.containsConflicts()) {
739
740
741
742 add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
743 add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
744 add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
745 mergeResults.put(tw.getPathString(), result);
746 return;
747 }
748
749
750
751 DirCacheEntry dce = new DirCacheEntry(tw.getPathString());
752
753
754
755 int newMode = mergeFileModes(
756 tw.getRawMode(0),
757 tw.getRawMode(1),
758 tw.getRawMode(2));
759 dce.setFileMode(newMode == FileMode.MISSING.getBits()
760 ? FileMode.REGULAR_FILE
761 : FileMode.fromBits(newMode));
762 if (mergedFile != null) {
763 long len = mergedFile.length();
764 dce.setLastModified(FS.DETECTED.lastModified(mergedFile));
765 dce.setLength((int) len);
766 InputStream is = new FileInputStream(mergedFile);
767 try {
768 dce.setObjectId(getObjectInserter().insert(OBJ_BLOB, len, is));
769 } finally {
770 is.close();
771 }
772 } else
773 dce.setObjectId(insertMergeResult(result));
774 builder.add(dce);
775 }
776
777
778
779
780
781
782
783
784
785
786 private File writeMergedFile(MergeResult<RawText> result)
787 throws FileNotFoundException, IOException {
788 File workTree = db.getWorkTree();
789 FS fs = db.getFS();
790 File of = new File(workTree, tw.getPathString());
791 File parentFolder = of.getParentFile();
792 if (!fs.exists(parentFolder))
793 parentFolder.mkdirs();
794 try (OutputStream os = new BufferedOutputStream(
795 new FileOutputStream(of))) {
796 new MergeFormatter().formatMerge(os, result,
797 Arrays.asList(commitNames), CHARACTER_ENCODING);
798 }
799 return of;
800 }
801
802 private ObjectId insertMergeResult(MergeResult<RawText> result)
803 throws IOException {
804 TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile(
805 db.getDirectory(), 10 << 20);
806 try {
807 new MergeFormatter().formatMerge(buf, result,
808 Arrays.asList(commitNames), CHARACTER_ENCODING);
809 buf.close();
810 try (InputStream in = buf.openInputStream()) {
811 return getObjectInserter().insert(OBJ_BLOB, buf.length(), in);
812 }
813 } finally {
814 buf.destroy();
815 }
816 }
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834 private int mergeFileModes(int modeB, int modeO, int modeT) {
835 if (modeO == modeT)
836 return modeO;
837 if (modeB == modeO)
838
839 return (modeT == FileMode.MISSING.getBits()) ? modeO : modeT;
840 if (modeB == modeT)
841
842 return (modeO == FileMode.MISSING.getBits()) ? modeT : modeO;
843 return FileMode.MISSING.getBits();
844 }
845
846 private static RawText getRawText(ObjectId id, ObjectReader reader)
847 throws IOException {
848 if (id.equals(ObjectId.zeroId()))
849 return new RawText(new byte[] {});
850 return new RawText(reader.open(id, OBJ_BLOB).getCachedBytes());
851 }
852
853 private static boolean nonTree(final int mode) {
854 return mode != 0 && !FileMode.TREE.equals(mode);
855 }
856
857 private static boolean isGitLink(final int mode) {
858 return FileMode.GITLINK.equals(mode);
859 }
860
861 @Override
862 public ObjectId getResultTreeId() {
863 return (resultTree == null) ? null : resultTree.toObjectId();
864 }
865
866
867
868
869
870
871 public void setCommitNames(String[] commitNames) {
872 this.commitNames = commitNames;
873 }
874
875
876
877
878
879 public String[] getCommitNames() {
880 return commitNames;
881 }
882
883
884
885
886
887 public List<String> getUnmergedPaths() {
888 return unmergedPaths;
889 }
890
891
892
893
894
895
896
897 public List<String> getModifiedFiles() {
898 return modifiedFiles;
899 }
900
901
902
903
904
905
906
907 public Map<String, DirCacheEntry> getToBeCheckedOut() {
908 return toBeCheckedOut;
909 }
910
911
912
913
914 public Map<String, MergeResult<? extends Sequence>> getMergeResults() {
915 return mergeResults;
916 }
917
918
919
920
921
922
923 public Map<String, MergeFailureReason> getFailingPaths() {
924 return (failingPaths.size() == 0) ? null : failingPaths;
925 }
926
927
928
929
930
931
932
933
934 public boolean failed() {
935 return failingPaths.size() > 0;
936 }
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951 public void setDirCache(DirCache dc) {
952 this.dircache = dc;
953 implicitDirCache = false;
954 }
955
956
957
958
959
960
961
962
963
964
965
966
967 public void setWorkingTreeIterator(WorkingTreeIterator workingTreeIterator) {
968 this.workingTreeIterator = workingTreeIterator;
969 }
970
971
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 protected boolean mergeTrees(AbstractTreeIterator baseTree,
1002 RevTree headTree, RevTree mergeTree, boolean ignoreConflicts)
1003 throws IOException {
1004
1005 builder = dircache.builder();
1006 DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder);
1007
1008 tw = new NameConflictTreeWalk(db, reader);
1009 tw.addTree(baseTree);
1010 tw.addTree(headTree);
1011 tw.addTree(mergeTree);
1012 int dciPos = tw.addTree(buildIt);
1013 if (workingTreeIterator != null) {
1014 tw.addTree(workingTreeIterator);
1015 workingTreeIterator.setDirCacheIterator(tw, dciPos);
1016 } else {
1017 tw.setFilter(TreeFilter.ANY_DIFF);
1018 }
1019
1020 if (!mergeTreeWalk(tw, ignoreConflicts)) {
1021 return false;
1022 }
1023
1024 if (!inCore) {
1025
1026
1027
1028 checkout();
1029
1030
1031
1032
1033
1034 if (!builder.commit()) {
1035 cleanUp();
1036 throw new IndexWriteException();
1037 }
1038 builder = null;
1039
1040 } else {
1041 builder.finish();
1042 builder = null;
1043 }
1044
1045 if (getUnmergedPaths().isEmpty() && !failed()) {
1046 resultTree = dircache.writeTree(getObjectInserter());
1047 return true;
1048 } else {
1049 resultTree = null;
1050 return false;
1051 }
1052 }
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066 protected boolean mergeTreeWalk(TreeWalk treeWalk, boolean ignoreConflicts)
1067 throws IOException {
1068 boolean hasWorkingTreeIterator = tw.getTreeCount() > T_FILE;
1069 while (treeWalk.next()) {
1070 if (!processEntry(
1071 treeWalk.getTree(T_BASE, CanonicalTreeParser.class),
1072 treeWalk.getTree(T_OURS, CanonicalTreeParser.class),
1073 treeWalk.getTree(T_THEIRS, CanonicalTreeParser.class),
1074 treeWalk.getTree(T_INDEX, DirCacheBuildIterator.class),
1075 hasWorkingTreeIterator ? treeWalk.getTree(T_FILE,
1076 WorkingTreeIterator.class) : null, ignoreConflicts)) {
1077 cleanUp();
1078 return false;
1079 }
1080 if (treeWalk.isSubtree() && enterSubtree)
1081 treeWalk.enterSubtree();
1082 }
1083 return true;
1084 }
1085 }