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 package org.eclipse.jgit.merge;
45
46 import java.io.IOException;
47
48 import org.eclipse.jgit.dircache.DirCache;
49 import org.eclipse.jgit.dircache.DirCacheBuilder;
50 import org.eclipse.jgit.dircache.DirCacheEntry;
51 import org.eclipse.jgit.errors.UnmergedPathException;
52 import org.eclipse.jgit.lib.FileMode;
53 import org.eclipse.jgit.lib.ObjectId;
54 import org.eclipse.jgit.lib.ObjectInserter;
55 import org.eclipse.jgit.lib.Repository;
56 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
57 import org.eclipse.jgit.treewalk.NameConflictTreeWalk;
58
59
60
61
62
63
64
65
66
67
68
69
70 public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy {
71
72 protected StrategySimpleTwoWayInCore() {
73
74 }
75
76 @Override
77 public String getName() {
78 return "simple-two-way-in-core";
79 }
80
81 @Override
82 public ThreeWayMerger newMerger(final Repository db) {
83 return new InCoreMerger(db);
84 }
85
86 @Override
87 public ThreeWayMerger newMerger(Repository db, boolean inCore) {
88
89 return newMerger(db);
90 }
91
92 private static class InCoreMerger extends ThreeWayMerger {
93 private static final int T_BASE = 0;
94
95 private static final int T_OURS = 1;
96
97 private static final int T_THEIRS = 2;
98
99 private final NameConflictTreeWalk tw;
100
101 private final DirCache cache;
102
103 private DirCacheBuilder builder;
104
105 private ObjectId resultTree;
106
107 InCoreMerger(final Repository local) {
108 super(local);
109 tw = new NameConflictTreeWalk(local, reader);
110 cache = DirCache.newInCore();
111 }
112
113 @Override
114 protected boolean mergeImpl() throws IOException {
115 tw.addTree(mergeBase());
116 tw.addTree(sourceTrees[0]);
117 tw.addTree(sourceTrees[1]);
118
119 boolean hasConflict = false;
120 builder = cache.builder();
121 while (tw.next()) {
122 final int modeO = tw.getRawMode(T_OURS);
123 final int modeT = tw.getRawMode(T_THEIRS);
124 if (modeO == modeT && tw.idEqual(T_OURS, T_THEIRS)) {
125 add(T_OURS, DirCacheEntry.STAGE_0);
126 continue;
127 }
128
129 final int modeB = tw.getRawMode(T_BASE);
130 if (modeB == modeO && tw.idEqual(T_BASE, T_OURS))
131 add(T_THEIRS, DirCacheEntry.STAGE_0);
132 else if (modeB == modeT && tw.idEqual(T_BASE, T_THEIRS))
133 add(T_OURS, DirCacheEntry.STAGE_0);
134 else {
135 if (nonTree(modeB)) {
136 add(T_BASE, DirCacheEntry.STAGE_1);
137 hasConflict = true;
138 }
139 if (nonTree(modeO)) {
140 add(T_OURS, DirCacheEntry.STAGE_2);
141 hasConflict = true;
142 }
143 if (nonTree(modeT)) {
144 add(T_THEIRS, DirCacheEntry.STAGE_3);
145 hasConflict = true;
146 }
147 if (tw.isSubtree())
148 tw.enterSubtree();
149 }
150 }
151 builder.finish();
152 builder = null;
153
154 if (hasConflict)
155 return false;
156 try {
157 ObjectInserter odi = getObjectInserter();
158 resultTree = cache.writeTree(odi);
159 odi.flush();
160 return true;
161 } catch (UnmergedPathException upe) {
162 resultTree = null;
163 return false;
164 }
165 }
166
167 private static boolean nonTree(final int mode) {
168 return mode != 0 && !FileMode.TREE.equals(mode);
169 }
170
171 private void add(final int tree, final int stage) throws IOException {
172 final AbstractTreeIterator i = getTree(tree);
173 if (i != null) {
174 if (FileMode.TREE.equals(tw.getRawMode(tree))) {
175 builder.addTree(tw.getRawPath(), stage, reader, tw
176 .getObjectId(tree));
177 } else {
178 final DirCacheEntry e;
179
180 e = new DirCacheEntry(tw.getRawPath(), stage);
181 e.setObjectIdFromRaw(i.idBuffer(), i.idOffset());
182 e.setFileMode(tw.getFileMode(tree));
183 builder.add(e);
184 }
185 }
186 }
187
188 private AbstractTreeIterator getTree(final int tree) {
189 return tw.getTree(tree, AbstractTreeIterator.class);
190 }
191
192 @Override
193 public ObjectId getResultTreeId() {
194 return resultTree;
195 }
196 }
197
198 }