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.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertFalse;
49 import static org.junit.Assert.assertTrue;
50
51 import java.io.IOException;
52
53 import org.eclipse.jgit.dircache.DirCache;
54 import org.eclipse.jgit.dircache.DirCacheBuilder;
55 import org.eclipse.jgit.lib.CommitBuilder;
56 import org.eclipse.jgit.lib.FileMode;
57 import org.eclipse.jgit.lib.ObjectId;
58 import org.eclipse.jgit.lib.ObjectInserter;
59 import org.eclipse.jgit.lib.PersonIdent;
60 import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
61 import org.eclipse.jgit.treewalk.TreeWalk;
62 import org.junit.Test;
63
64 public class SimpleMergeTest extends SampleDataRepositoryTestCase {
65
66 @Test
67 public void testOurs() throws IOException {
68 Merger ourMerger = MergeStrategy.OURS.newMerger(db);
69 boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") });
70 assertTrue(merge);
71 assertEquals(db.resolve("a^{tree}"), ourMerger.getResultTreeId());
72 }
73
74 @Test
75 public void testTheirs() throws IOException {
76 Merger ourMerger = MergeStrategy.THEIRS.newMerger(db);
77 boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") });
78 assertTrue(merge);
79 assertEquals(db.resolve("c^{tree}"), ourMerger.getResultTreeId());
80 }
81
82 @Test
83 public void testTrivialTwoWay() throws IOException {
84 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
85 boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") });
86 assertTrue(merge);
87 assertEquals("02ba32d3649e510002c21651936b7077aa75ffa9",ourMerger.getResultTreeId().name());
88 }
89
90 @Test
91 public void testTrivialTwoWay_disjointhistories() throws IOException {
92 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
93 boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c~4") });
94 assertTrue(merge);
95 assertEquals("86265c33b19b2be71bdd7b8cb95823f2743d03a8",ourMerger.getResultTreeId().name());
96 }
97
98 @Test
99 public void testTrivialTwoWay_ok() throws IOException {
100 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
101 boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a^0^0^0"), db.resolve("a^0^0^1") });
102 assertTrue(merge);
103 assertEquals(db.resolve("a^0^0^{tree}"), ourMerger.getResultTreeId());
104 }
105
106 @Test
107 public void testTrivialTwoWay_conflict() throws IOException {
108 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
109 boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("f"), db.resolve("g") });
110 assertFalse(merge);
111 }
112
113 @Test
114 public void testTrivialTwoWay_validSubtreeSort() throws Exception {
115 final DirCache treeB = db.readDirCache();
116 final DirCache treeO = db.readDirCache();
117 final DirCache treeT = db.readDirCache();
118 {
119 final DirCacheBuilder b = treeB.builder();
120 final DirCacheBuilder o = treeO.builder();
121 final DirCacheBuilder t = treeT.builder();
122
123 b.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE));
124 b.add(createEntry("libelf/c", FileMode.REGULAR_FILE));
125
126 o.add(createEntry("Makefile", FileMode.REGULAR_FILE));
127 o.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE));
128 o.add(createEntry("libelf/c", FileMode.REGULAR_FILE));
129
130 t.add(createEntry("libelf-po/a", FileMode.REGULAR_FILE));
131 t.add(createEntry("libelf/c", FileMode.REGULAR_FILE, "blah"));
132
133 b.finish();
134 o.finish();
135 t.finish();
136 }
137
138 final ObjectInserter ow = db.newObjectInserter();
139 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
140 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
141 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
142
143 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
144 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
145 assertTrue(merge);
146
147 final TreeWalk tw = new TreeWalk(db);
148 tw.setRecursive(true);
149 tw.reset(ourMerger.getResultTreeId());
150
151 assertTrue(tw.next());
152 assertEquals("Makefile", tw.getPathString());
153 assertCorrectId(treeO, tw);
154
155 assertTrue(tw.next());
156 assertEquals("libelf-po/a", tw.getPathString());
157 assertCorrectId(treeO, tw);
158
159 assertTrue(tw.next());
160 assertEquals("libelf/c", tw.getPathString());
161 assertCorrectId(treeT, tw);
162
163 assertFalse(tw.next());
164 }
165
166 @Test
167 public void testTrivialTwoWay_concurrentSubtreeChange() throws Exception {
168 final DirCache treeB = db.readDirCache();
169 final DirCache treeO = db.readDirCache();
170 final DirCache treeT = db.readDirCache();
171 {
172 final DirCacheBuilder b = treeB.builder();
173 final DirCacheBuilder o = treeO.builder();
174 final DirCacheBuilder t = treeT.builder();
175
176 b.add(createEntry("d/o", FileMode.REGULAR_FILE));
177 b.add(createEntry("d/t", FileMode.REGULAR_FILE));
178
179 o.add(createEntry("d/o", FileMode.REGULAR_FILE, "o !"));
180 o.add(createEntry("d/t", FileMode.REGULAR_FILE));
181
182 t.add(createEntry("d/o", FileMode.REGULAR_FILE));
183 t.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !"));
184
185 b.finish();
186 o.finish();
187 t.finish();
188 }
189
190 final ObjectInserter ow = db.newObjectInserter();
191 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
192 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
193 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
194
195 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
196 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
197 assertTrue(merge);
198
199 final TreeWalk tw = new TreeWalk(db);
200 tw.setRecursive(true);
201 tw.reset(ourMerger.getResultTreeId());
202
203 assertTrue(tw.next());
204 assertEquals("d/o", tw.getPathString());
205 assertCorrectId(treeO, tw);
206
207 assertTrue(tw.next());
208 assertEquals("d/t", tw.getPathString());
209 assertCorrectId(treeT, tw);
210
211 assertFalse(tw.next());
212 }
213
214 @Test
215 public void testTrivialTwoWay_conflictSubtreeChange() throws Exception {
216 final DirCache treeB = db.readDirCache();
217 final DirCache treeO = db.readDirCache();
218 final DirCache treeT = db.readDirCache();
219 {
220 final DirCacheBuilder b = treeB.builder();
221 final DirCacheBuilder o = treeO.builder();
222 final DirCacheBuilder t = treeT.builder();
223
224 b.add(createEntry("d/o", FileMode.REGULAR_FILE));
225 b.add(createEntry("d/t", FileMode.REGULAR_FILE));
226
227 o.add(createEntry("d/o", FileMode.REGULAR_FILE));
228 o.add(createEntry("d/t", FileMode.REGULAR_FILE, "o !"));
229
230 t.add(createEntry("d/o", FileMode.REGULAR_FILE, "t !"));
231 t.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !"));
232
233 b.finish();
234 o.finish();
235 t.finish();
236 }
237
238 final ObjectInserter ow = db.newObjectInserter();
239 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
240 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
241 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
242
243 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
244 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
245 assertFalse(merge);
246 }
247
248 @Test
249 public void testTrivialTwoWay_leftDFconflict1() throws Exception {
250 final DirCache treeB = db.readDirCache();
251 final DirCache treeO = db.readDirCache();
252 final DirCache treeT = db.readDirCache();
253 {
254 final DirCacheBuilder b = treeB.builder();
255 final DirCacheBuilder o = treeO.builder();
256 final DirCacheBuilder t = treeT.builder();
257
258 b.add(createEntry("d/o", FileMode.REGULAR_FILE));
259 b.add(createEntry("d/t", FileMode.REGULAR_FILE));
260
261 o.add(createEntry("d", FileMode.REGULAR_FILE));
262
263 t.add(createEntry("d/o", FileMode.REGULAR_FILE));
264 t.add(createEntry("d/t", FileMode.REGULAR_FILE, "t !"));
265
266 b.finish();
267 o.finish();
268 t.finish();
269 }
270
271 final ObjectInserter ow = db.newObjectInserter();
272 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
273 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
274 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
275
276 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
277 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
278 assertFalse(merge);
279 }
280
281 @Test
282 public void testTrivialTwoWay_rightDFconflict1() throws Exception {
283 final DirCache treeB = db.readDirCache();
284 final DirCache treeO = db.readDirCache();
285 final DirCache treeT = db.readDirCache();
286 {
287 final DirCacheBuilder b = treeB.builder();
288 final DirCacheBuilder o = treeO.builder();
289 final DirCacheBuilder t = treeT.builder();
290
291 b.add(createEntry("d/o", FileMode.REGULAR_FILE));
292 b.add(createEntry("d/t", FileMode.REGULAR_FILE));
293
294 o.add(createEntry("d/o", FileMode.REGULAR_FILE));
295 o.add(createEntry("d/t", FileMode.REGULAR_FILE, "o !"));
296
297 t.add(createEntry("d", FileMode.REGULAR_FILE));
298
299 b.finish();
300 o.finish();
301 t.finish();
302 }
303
304 final ObjectInserter ow = db.newObjectInserter();
305 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
306 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
307 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
308
309 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
310 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
311 assertFalse(merge);
312 }
313
314 @Test
315 public void testTrivialTwoWay_leftDFconflict2() throws Exception {
316 final DirCache treeB = db.readDirCache();
317 final DirCache treeO = db.readDirCache();
318 final DirCache treeT = db.readDirCache();
319 {
320 final DirCacheBuilder b = treeB.builder();
321 final DirCacheBuilder o = treeO.builder();
322 final DirCacheBuilder t = treeT.builder();
323
324 b.add(createEntry("d", FileMode.REGULAR_FILE));
325
326 o.add(createEntry("d", FileMode.REGULAR_FILE, "o !"));
327
328 t.add(createEntry("d/o", FileMode.REGULAR_FILE));
329
330 b.finish();
331 o.finish();
332 t.finish();
333 }
334
335 final ObjectInserter ow = db.newObjectInserter();
336 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
337 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
338 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
339
340 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
341 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
342 assertFalse(merge);
343 }
344
345 @Test
346 public void testTrivialTwoWay_rightDFconflict2() throws Exception {
347 final DirCache treeB = db.readDirCache();
348 final DirCache treeO = db.readDirCache();
349 final DirCache treeT = db.readDirCache();
350 {
351 final DirCacheBuilder b = treeB.builder();
352 final DirCacheBuilder o = treeO.builder();
353 final DirCacheBuilder t = treeT.builder();
354
355 b.add(createEntry("d", FileMode.REGULAR_FILE));
356
357 o.add(createEntry("d/o", FileMode.REGULAR_FILE));
358
359 t.add(createEntry("d", FileMode.REGULAR_FILE, "t !"));
360
361 b.finish();
362 o.finish();
363 t.finish();
364 }
365
366 final ObjectInserter ow = db.newObjectInserter();
367 final ObjectId b = commit(ow, treeB, new ObjectId[] {});
368 final ObjectId o = commit(ow, treeO, new ObjectId[] { b });
369 final ObjectId t = commit(ow, treeT, new ObjectId[] { b });
370
371 Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
372 boolean merge = ourMerger.merge(new ObjectId[] { o, t });
373 assertFalse(merge);
374 }
375
376 private static void assertCorrectId(final DirCache treeT, final TreeWalk tw) {
377 assertEquals(treeT.getEntry(tw.getPathString()).getObjectId(), tw
378 .getObjectId(0));
379 }
380
381 private static ObjectId commit(final ObjectInserter odi,
382 final DirCache treeB,
383 final ObjectId[] parentIds) throws Exception {
384 final CommitBuilder c = new CommitBuilder();
385 c.setTreeId(treeB.writeTree(odi));
386 c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
387 c.setCommitter(c.getAuthor());
388 c.setParentIds(parentIds);
389 c.setMessage("Tree " + c.getTreeId().name());
390 ObjectId id = odi.insert(c);
391 odi.flush();
392 return id;
393 }
394 }