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(mergedFile.lastModified());
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 if (workTree == null)
790
791
792 throw new UnsupportedOperationException();
793
794 FS fs = db.getFS();
795 File of = new File(workTree, tw.getPathString());
796 File parentFolder = of.getParentFile();
797 if (!fs.exists(parentFolder))
798 parentFolder.mkdirs();
799 try (OutputStream os = new BufferedOutputStream(
800 new FileOutputStream(of))) {
801 new MergeFormatter().formatMerge(os, result,
802 Arrays.asList(commitNames), CHARACTER_ENCODING);
803 }
804 return of;
805 }
806
807 private ObjectId insertMergeResult(MergeResult<RawText> result)
808 throws IOException {
809 TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile(
810 db.getDirectory(), 10 << 20);
811 try {
812 new MergeFormatter().formatMerge(buf, result,
813 Arrays.asList(commitNames), CHARACTER_ENCODING);
814 buf.close();
815 try (InputStream in = buf.openInputStream()) {
816 return getObjectInserter().insert(OBJ_BLOB, buf.length(), in);
817 }
818 } finally {
819 buf.destroy();
820 }
821 }
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839 private int mergeFileModes(int modeB, int modeO, int modeT) {
840 if (modeO == modeT)
841 return modeO;
842 if (modeB == modeO)
843
844 return (modeT == FileMode.MISSING.getBits()) ? modeO : modeT;
845 if (modeB == modeT)
846
847 return (modeO == FileMode.MISSING.getBits()) ? modeT : modeO;
848 return FileMode.MISSING.getBits();
849 }
850
851 private static RawText getRawText(ObjectId id, ObjectReader reader)
852 throws IOException {
853 if (id.equals(ObjectId.zeroId()))
854 return new RawText(new byte[] {});
855 return new RawText(reader.open(id, OBJ_BLOB).getCachedBytes());
856 }
857
858 private static boolean nonTree(final int mode) {
859 return mode != 0 && !FileMode.TREE.equals(mode);
860 }
861
862 private static boolean isGitLink(final int mode) {
863 return FileMode.GITLINK.equals(mode);
864 }
865
866 @Override
867 public ObjectId getResultTreeId() {
868 return (resultTree == null) ? null : resultTree.toObjectId();
869 }
870
871
872
873
874
875
876 public void setCommitNames(String[] commitNames) {
877 this.commitNames = commitNames;
878 }
879
880
881
882
883
884 public String[] getCommitNames() {
885 return commitNames;
886 }
887
888
889
890
891
892 public List<String> getUnmergedPaths() {
893 return unmergedPaths;
894 }
895
896
897
898
899
900
901
902 public List<String> getModifiedFiles() {
903 return modifiedFiles;
904 }
905
906
907
908
909
910
911
912 public Map<String, DirCacheEntry> getToBeCheckedOut() {
913 return toBeCheckedOut;
914 }
915
916
917
918
919 public Map<String, MergeResult<? extends Sequence>> getMergeResults() {
920 return mergeResults;
921 }
922
923
924
925
926
927
928 public Map<String, MergeFailureReason> getFailingPaths() {
929 return (failingPaths.size() == 0) ? null : failingPaths;
930 }
931
932
933
934
935
936
937
938
939 public boolean failed() {
940 return failingPaths.size() > 0;
941 }
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956 public void setDirCache(DirCache dc) {
957 this.dircache = dc;
958 implicitDirCache = false;
959 }
960
961
962
963
964
965
966
967
968
969
970
971
972 public void setWorkingTreeIterator(WorkingTreeIterator workingTreeIterator) {
973 this.workingTreeIterator = workingTreeIterator;
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
1005
1006 protected boolean mergeTrees(AbstractTreeIterator baseTree,
1007 RevTree headTree, RevTree mergeTree, boolean ignoreConflicts)
1008 throws IOException {
1009
1010 builder = dircache.builder();
1011 DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder);
1012
1013 tw = new NameConflictTreeWalk(reader);
1014 tw.addTree(baseTree);
1015 tw.addTree(headTree);
1016 tw.addTree(mergeTree);
1017 tw.addTree(buildIt);
1018 if (workingTreeIterator != null) {
1019 tw.addTree(workingTreeIterator);
1020 } else {
1021 tw.setFilter(TreeFilter.ANY_DIFF);
1022 }
1023
1024 if (!mergeTreeWalk(tw, ignoreConflicts)) {
1025 return false;
1026 }
1027
1028 if (!inCore) {
1029
1030
1031
1032 checkout();
1033
1034
1035
1036
1037
1038 if (!builder.commit()) {
1039 cleanUp();
1040 throw new IndexWriteException();
1041 }
1042 builder = null;
1043
1044 } else {
1045 builder.finish();
1046 builder = null;
1047 }
1048
1049 if (getUnmergedPaths().isEmpty() && !failed()) {
1050 resultTree = dircache.writeTree(getObjectInserter());
1051 return true;
1052 } else {
1053 resultTree = null;
1054 return false;
1055 }
1056 }
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 protected boolean mergeTreeWalk(TreeWalk treeWalk, boolean ignoreConflicts)
1071 throws IOException {
1072 boolean hasWorkingTreeIterator = tw.getTreeCount() > T_FILE;
1073 while (treeWalk.next()) {
1074 if (!processEntry(
1075 treeWalk.getTree(T_BASE, CanonicalTreeParser.class),
1076 treeWalk.getTree(T_OURS, CanonicalTreeParser.class),
1077 treeWalk.getTree(T_THEIRS, CanonicalTreeParser.class),
1078 treeWalk.getTree(T_INDEX, DirCacheBuildIterator.class),
1079 hasWorkingTreeIterator ? treeWalk.getTree(T_FILE,
1080 WorkingTreeIterator.class) : null, ignoreConflicts)) {
1081 cleanUp();
1082 return false;
1083 }
1084 if (treeWalk.isSubtree() && enterSubtree)
1085 treeWalk.enterSubtree();
1086 }
1087 return true;
1088 }
1089 }