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