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