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