All that's really required to run a merge operation is a single ObjectInserter, from which we can construct a RevWalk, plus a Config that declares a diff algorithm. Provide some factory methods that don't take Repository. Change-Id: Ib884dce2528424b5bcbbbbfc043baec1886b9bbdtags/v4.8.0.201705170830-rc1
@@ -42,12 +42,17 @@ | |||
*/ | |||
package org.eclipse.jgit.merge; | |||
import static java.nio.charset.StandardCharsets.UTF_8; | |||
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertFalse; | |||
import static org.junit.Assert.assertTrue; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import org.eclipse.jgit.api.Git; | |||
import org.eclipse.jgit.api.MergeResult; | |||
@@ -59,8 +64,14 @@ import org.eclipse.jgit.dircache.DirCache; | |||
import org.eclipse.jgit.errors.NoMergeBaseException; | |||
import org.eclipse.jgit.errors.NoMergeBaseException.MergeBaseFailureReason; | |||
import org.eclipse.jgit.junit.RepositoryTestCase; | |||
import org.eclipse.jgit.junit.TestRepository; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
import org.eclipse.jgit.revwalk.RevObject; | |||
import org.eclipse.jgit.revwalk.RevTree; | |||
import org.eclipse.jgit.revwalk.RevWalk; | |||
import org.eclipse.jgit.treewalk.FileTreeIterator; | |||
import org.eclipse.jgit.util.FS; | |||
import org.eclipse.jgit.util.FileUtils; | |||
@@ -408,7 +419,7 @@ public class ResolveMergerTest extends RepositoryTestCase { | |||
/** | |||
* Merging two equal subtrees with an incore merger should lead to a merged | |||
* state (The 'Gerrit' use case). | |||
* state. | |||
* | |||
* @param strategy | |||
* @throws Exception | |||
@@ -441,6 +452,43 @@ public class ResolveMergerTest extends RepositoryTestCase { | |||
assertTrue(noProblems); | |||
} | |||
/** | |||
* Merging two equal subtrees with an incore merger should lead to a merged | |||
* state, without using a Repository (the 'Gerrit' use case). | |||
* | |||
* @param strategy | |||
* @throws Exception | |||
*/ | |||
@Theory | |||
public void checkMergeEqualTreesInCore_noRepo(MergeStrategy strategy) | |||
throws Exception { | |||
Git git = Git.wrap(db); | |||
writeTrashFile("d/1", "orig"); | |||
git.add().addFilepattern("d/1").call(); | |||
RevCommit first = git.commit().setMessage("added d/1").call(); | |||
writeTrashFile("d/1", "modified"); | |||
RevCommit masterCommit = git.commit().setAll(true) | |||
.setMessage("modified d/1 on master").call(); | |||
git.checkout().setCreateBranch(true).setStartPoint(first) | |||
.setName("side").call(); | |||
writeTrashFile("d/1", "modified"); | |||
RevCommit sideCommit = git.commit().setAll(true) | |||
.setMessage("modified d/1 on side").call(); | |||
git.rm().addFilepattern("d/1").call(); | |||
git.rm().addFilepattern("d").call(); | |||
try (ObjectInserter ins = db.newObjectInserter()) { | |||
ThreeWayMerger resolveMerger = | |||
(ThreeWayMerger) strategy.newMerger(ins, db.getConfig()); | |||
boolean noProblems = resolveMerger.merge(masterCommit, sideCommit); | |||
assertTrue(noProblems); | |||
} | |||
} | |||
/** | |||
* Merging two equal subtrees when the index and HEAD does not contain any | |||
* file in that subtree should lead to a merged state. | |||
@@ -612,6 +660,35 @@ public class ResolveMergerTest extends RepositoryTestCase { | |||
assertEquals(expected, read("file")); | |||
} | |||
@Theory | |||
public void checkContentMergeNoConflict_noRepo(MergeStrategy strategy) | |||
throws Exception { | |||
Git git = Git.wrap(db); | |||
writeTrashFile("file", "1\n2\n3"); | |||
git.add().addFilepattern("file").call(); | |||
RevCommit first = git.commit().setMessage("added file").call(); | |||
writeTrashFile("file", "1master\n2\n3"); | |||
RevCommit masterCommit = git.commit().setAll(true) | |||
.setMessage("modified file on master").call(); | |||
git.checkout().setCreateBranch(true).setStartPoint(first) | |||
.setName("side").call(); | |||
writeTrashFile("file", "1\n2\n3side"); | |||
RevCommit sideCommit = git.commit().setAll(true) | |||
.setMessage("modified file on side").call(); | |||
try (ObjectInserter ins = db.newObjectInserter()) { | |||
ResolveMerger merger = | |||
(ResolveMerger) strategy.newMerger(ins, db.getConfig()); | |||
boolean noProblems = merger.merge(masterCommit, sideCommit); | |||
assertTrue(noProblems); | |||
assertEquals("1master\n2\n3side", | |||
readBlob(merger.getResultTreeId(), "file")); | |||
} | |||
} | |||
@Theory | |||
public void checkContentMergeConflict(MergeStrategy strategy) | |||
throws Exception { | |||
@@ -644,6 +721,49 @@ public class ResolveMergerTest extends RepositoryTestCase { | |||
assertEquals(expected, read("file")); | |||
} | |||
@Theory | |||
public void checkContentMergeConflict_noTree(MergeStrategy strategy) | |||
throws Exception { | |||
Git git = Git.wrap(db); | |||
writeTrashFile("file", "1\n2\n3"); | |||
git.add().addFilepattern("file").call(); | |||
RevCommit first = git.commit().setMessage("added file").call(); | |||
writeTrashFile("file", "1master\n2\n3"); | |||
RevCommit masterCommit = git.commit().setAll(true) | |||
.setMessage("modified file on master").call(); | |||
git.checkout().setCreateBranch(true).setStartPoint(first) | |||
.setName("side").call(); | |||
writeTrashFile("file", "1side\n2\n3"); | |||
RevCommit sideCommit = git.commit().setAll(true) | |||
.setMessage("modified file on side").call(); | |||
try (ObjectInserter ins = db.newObjectInserter()) { | |||
ResolveMerger merger = | |||
(ResolveMerger) strategy.newMerger(ins, db.getConfig()); | |||
boolean noProblems = merger.merge(masterCommit, sideCommit); | |||
assertFalse(noProblems); | |||
assertEquals(Arrays.asList("file"), merger.getUnmergedPaths()); | |||
MergeFormatter fmt = new MergeFormatter(); | |||
merger.getMergeResults().get("file"); | |||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { | |||
fmt.formatMerge(out, merger.getMergeResults().get("file"), | |||
"BASE", "OURS", "THEIRS", UTF_8.name()); | |||
String expected = "<<<<<<< OURS\n" | |||
+ "1master\n" | |||
+ "=======\n" | |||
+ "1side\n" | |||
+ ">>>>>>> THEIRS\n" | |||
+ "2\n" | |||
+ "3"; | |||
assertEquals(expected, new String(out.toByteArray(), UTF_8)); | |||
} | |||
} | |||
} | |||
/** | |||
* Merging after criss-cross merges. In this case we merge together two | |||
* commits which have two equally good common ancestors | |||
@@ -875,4 +995,15 @@ public class ResolveMergerTest extends RepositoryTestCase { | |||
curMod >= lastMod); | |||
} | |||
} | |||
private String readBlob(ObjectId treeish, String path) throws Exception { | |||
TestRepository<?> tr = new TestRepository<>(db); | |||
RevWalk rw = tr.getRevWalk(); | |||
RevTree tree = rw.parseTree(treeish); | |||
RevObject obj = tr.get(tree, path); | |||
if (obj == null) { | |||
return null; | |||
} | |||
return new String(rw.getObjectReader().open(obj, OBJ_BLOB).getBytes(), UTF_8); | |||
} | |||
} |
@@ -71,6 +71,16 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { | |||
assertEquals(db.resolve("a^{tree}"), ourMerger.getResultTreeId()); | |||
} | |||
@Test | |||
public void testOurs_noRepo() throws IOException { | |||
try (ObjectInserter ins = db.newObjectInserter()) { | |||
Merger ourMerger = MergeStrategy.OURS.newMerger(ins, db.getConfig()); | |||
boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); | |||
assertTrue(merge); | |||
assertEquals(db.resolve("a^{tree}"), ourMerger.getResultTreeId()); | |||
} | |||
} | |||
@Test | |||
public void testTheirs() throws IOException { | |||
Merger ourMerger = MergeStrategy.THEIRS.newMerger(db); | |||
@@ -79,6 +89,16 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { | |||
assertEquals(db.resolve("c^{tree}"), ourMerger.getResultTreeId()); | |||
} | |||
@Test | |||
public void testTheirs_noRepo() throws IOException { | |||
try (ObjectInserter ins = db.newObjectInserter()) { | |||
Merger ourMerger = MergeStrategy.THEIRS.newMerger(db); | |||
boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); | |||
assertTrue(merge); | |||
assertEquals(db.resolve("c^{tree}"), ourMerger.getResultTreeId()); | |||
} | |||
} | |||
@Test | |||
public void testTrivialTwoWay() throws IOException { | |||
Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); | |||
@@ -103,6 +123,16 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { | |||
assertEquals(db.resolve("a^0^0^{tree}"), ourMerger.getResultTreeId()); | |||
} | |||
@Test | |||
public void testTrivialTwoWay_noRepo() throws IOException { | |||
try (ObjectInserter ins = db.newObjectInserter()) { | |||
Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(ins, db.getConfig()); | |||
boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a^0^0^0"), db.resolve("a^0^0^1") }); | |||
assertTrue(merge); | |||
assertEquals(db.resolve("a^0^0^{tree}"), ourMerger.getResultTreeId()); | |||
} | |||
} | |||
@Test | |||
public void testTrivialTwoWay_conflict() throws IOException { | |||
Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); |
@@ -538,6 +538,7 @@ renamesFindingExact=Finding exact renames | |||
renamesRejoiningModifies=Rejoining modified file pairs | |||
repositoryAlreadyExists=Repository already exists: {0} | |||
repositoryConfigFileInvalid=Repository config file {0} invalid {1} | |||
repositoryIsRequired=repository is required | |||
repositoryNotFound=repository not found: {0} | |||
repositoryState_applyMailbox=Apply mailbox | |||
repositoryState_bare=Bare |
@@ -597,6 +597,7 @@ public class JGitText extends TranslationBundle { | |||
/***/ public String renamesRejoiningModifies; | |||
/***/ public String repositoryAlreadyExists; | |||
/***/ public String repositoryConfigFileInvalid; | |||
/***/ public String repositoryIsRequired; | |||
/***/ public String repositoryNotFound; | |||
/***/ public String repositoryState_applyMailbox; | |||
/***/ public String repositoryState_bare; |
@@ -49,6 +49,8 @@ import java.text.MessageFormat; | |||
import java.util.HashMap; | |||
import org.eclipse.jgit.internal.JGitText; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.Repository; | |||
/** | |||
@@ -170,4 +172,20 @@ public abstract class MergeStrategy { | |||
* @return the new merge instance which implements this strategy. | |||
*/ | |||
public abstract Merger newMerger(Repository db, boolean inCore); | |||
/** | |||
* Create a new merge instance. | |||
* <p> | |||
* The merge will happen in memory, working folder will not be modified, in | |||
* case of a non-trivial merge that requires manual resolution, the merger | |||
* will fail. | |||
* | |||
* @param inserter | |||
* inserter to write results back to. | |||
* @param config | |||
* repo config for reading diff algorithm settings. | |||
* @return the new merge instance which implements this strategy. | |||
* @since 4.8 | |||
*/ | |||
public abstract Merger newMerger(ObjectInserter inserter, Config config); | |||
} |
@@ -47,6 +47,7 @@ package org.eclipse.jgit.merge; | |||
import java.io.IOException; | |||
import java.text.MessageFormat; | |||
import org.eclipse.jgit.annotations.Nullable; | |||
import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.NoMergeBaseException; | |||
import org.eclipse.jgit.errors.NoMergeBaseException.MergeBaseFailureReason; | |||
@@ -70,7 +71,15 @@ import org.eclipse.jgit.treewalk.CanonicalTreeParser; | |||
* Instance of a specific {@link MergeStrategy} for a single {@link Repository}. | |||
*/ | |||
public abstract class Merger { | |||
/** The repository this merger operates on. */ | |||
/** | |||
* The repository this merger operates on. | |||
* <p> | |||
* Null if and only if the merger was constructed with {@link | |||
* #Merger(ObjectInserter)}. Callers that want to assume the repo is not null | |||
* (e.g. because of a previous check that the merger is not in-core) may use | |||
* {@link #nonNullRepo()}. | |||
*/ | |||
@Nullable | |||
protected final Repository db; | |||
/** Reader to support {@link #walk} and other object loading. */ | |||
@@ -104,20 +113,55 @@ public abstract class Merger { | |||
* the repository this merger will read and write data on. | |||
*/ | |||
protected Merger(final Repository local) { | |||
if (local == null) { | |||
throw new NullPointerException(JGitText.get().repositoryIsRequired); | |||
} | |||
db = local; | |||
inserter = db.newObjectInserter(); | |||
inserter = local.newObjectInserter(); | |||
reader = inserter.newReader(); | |||
walk = new RevWalk(reader); | |||
} | |||
/** | |||
* Create a new in-core merge instance from an inserter. | |||
* | |||
* @param oi | |||
* the inserter to write objects to. Will be closed at the | |||
* conclusion of {@code merge}, unless {@code flush} is false. | |||
* @since 4.8 | |||
*/ | |||
protected Merger(ObjectInserter oi) { | |||
db = null; | |||
inserter = oi; | |||
reader = oi.newReader(); | |||
walk = new RevWalk(reader); | |||
} | |||
/** | |||
* @return the repository this merger operates on. | |||
*/ | |||
@Nullable | |||
public Repository getRepository() { | |||
return db; | |||
} | |||
/** @return an object writer to create objects in {@link #getRepository()}. */ | |||
/** | |||
* @return non-null repository instance | |||
* @throws NullPointerException | |||
* if the merger was constructed without a repository. | |||
* @since 4.8 | |||
*/ | |||
protected Repository nonNullRepo() { | |||
if (db == null) { | |||
throw new NullPointerException(JGitText.get().repositoryIsRequired); | |||
} | |||
return db; | |||
} | |||
/** | |||
* @return an object writer to create objects, writing objects to {@link | |||
* #getRepository()} (if a repository was provided). | |||
*/ | |||
public ObjectInserter getObjectInserter() { | |||
return inserter; | |||
} | |||
@@ -131,7 +175,9 @@ public abstract class Merger { | |||
* | |||
* @param oi | |||
* the inserter instance to use. Must be associated with the | |||
* repository instance returned by {@link #getRepository()}. | |||
* repository instance returned by {@link #getRepository()} (if a | |||
* repository was provided). Will be closed at the conclusion of | |||
* {@code merge}, unless {@code flush} is false. | |||
*/ | |||
public void setObjectInserter(ObjectInserter oi) { | |||
walk.close(); | |||
@@ -173,9 +219,9 @@ public abstract class Merger { | |||
* | |||
* @since 3.5 | |||
* @param flush | |||
* whether to flush the underlying object inserter when finished to | |||
* store any content-merged blobs and virtual merged bases; if | |||
* false, callers are responsible for flushing. | |||
* whether to flush and close the underlying object inserter when | |||
* finished to store any content-merged blobs and virtual merged | |||
* bases; if false, callers are responsible for flushing. | |||
* @param tips | |||
* source trees to be combined together. The merge base is not | |||
* included in this set. |
@@ -61,7 +61,9 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.NoMergeBaseException; | |||
import org.eclipse.jgit.internal.JGitText; | |||
import org.eclipse.jgit.lib.CommitBuilder; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.PersonIdent; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
@@ -110,6 +112,17 @@ public class RecursiveMerger extends ResolveMerger { | |||
this(local, false); | |||
} | |||
/** | |||
* Normal recursive merge, implies inCore. | |||
* | |||
* @param inserter | |||
* @param config | |||
* @since 4.8 | |||
*/ | |||
protected RecursiveMerger(ObjectInserter inserter, Config config) { | |||
super(inserter, config); | |||
} | |||
/** | |||
* Get a single base commit for two given commits. If the two source commits | |||
* have more than one base commit recursively merge the base commits |
@@ -44,6 +44,9 @@ | |||
*/ | |||
package org.eclipse.jgit.merge; | |||
import static org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm.HISTOGRAM; | |||
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DIFF_SECTION; | |||
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_ALGORITHM; | |||
import static org.eclipse.jgit.lib.Constants.CHARACTER_ENCODING; | |||
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB; | |||
@@ -79,9 +82,10 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.IndexWriteException; | |||
import org.eclipse.jgit.errors.MissingObjectException; | |||
import org.eclipse.jgit.errors.NoWorkTreeException; | |||
import org.eclipse.jgit.lib.ConfigConstants; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.ObjectReader; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.revwalk.RevTree; | |||
@@ -266,18 +270,25 @@ public class ResolveMerger extends ThreeWayMerger { | |||
*/ | |||
protected MergeAlgorithm mergeAlgorithm; | |||
private static MergeAlgorithm getMergeAlgorithm(Config config) { | |||
SupportedAlgorithm diffAlg = config.getEnum( | |||
CONFIG_DIFF_SECTION, null, CONFIG_KEY_ALGORITHM, | |||
HISTOGRAM); | |||
return new MergeAlgorithm(DiffAlgorithm.getAlgorithm(diffAlg)); | |||
} | |||
private static String[] defaultCommitNames() { | |||
return new String[] { "BASE", "OURS", "THEIRS" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |||
} | |||
/** | |||
* @param local | |||
* @param inCore | |||
*/ | |||
protected ResolveMerger(Repository local, boolean inCore) { | |||
super(local); | |||
SupportedAlgorithm diffAlg = local.getConfig().getEnum( | |||
ConfigConstants.CONFIG_DIFF_SECTION, null, | |||
ConfigConstants.CONFIG_KEY_ALGORITHM, | |||
SupportedAlgorithm.HISTOGRAM); | |||
mergeAlgorithm = new MergeAlgorithm(DiffAlgorithm.getAlgorithm(diffAlg)); | |||
commitNames = new String[] { "BASE", "OURS", "THEIRS" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |||
mergeAlgorithm = getMergeAlgorithm(local.getConfig()); | |||
commitNames = defaultCommitNames(); | |||
this.inCore = inCore; | |||
if (inCore) { | |||
@@ -295,10 +306,24 @@ public class ResolveMerger extends ThreeWayMerger { | |||
this(local, false); | |||
} | |||
/** | |||
* @param inserter | |||
* @param config | |||
* @since 4.8 | |||
*/ | |||
protected ResolveMerger(ObjectInserter inserter, Config config) { | |||
super(inserter); | |||
mergeAlgorithm = getMergeAlgorithm(config); | |||
commitNames = defaultCommitNames(); | |||
inCore = true; | |||
implicitDirCache = false; | |||
dircache = DirCache.newInCore(); | |||
} | |||
@Override | |||
protected boolean mergeImpl() throws IOException { | |||
if (implicitDirCache) | |||
dircache = getRepository().lockDirCache(); | |||
dircache = nonNullRepo().lockDirCache(); | |||
try { | |||
return mergeTrees(mergeBase(), sourceTrees[0], sourceTrees[1], | |||
@@ -315,7 +340,7 @@ public class ResolveMerger extends ThreeWayMerger { | |||
// of a non-empty directory, for which delete() would fail. | |||
for (int i = toBeDeleted.size() - 1; i >= 0; i--) { | |||
String fileName = toBeDeleted.get(i); | |||
File f = new File(db.getWorkTree(), fileName); | |||
File f = new File(nonNullRepo().getWorkTree(), fileName); | |||
if (!f.delete()) | |||
if (!f.isDirectory()) | |||
failingPaths.put(fileName, | |||
@@ -348,7 +373,7 @@ public class ResolveMerger extends ThreeWayMerger { | |||
return; | |||
} | |||
DirCache dc = db.readDirCache(); | |||
DirCache dc = nonNullRepo().readDirCache(); | |||
Iterator<String> mpathsIt=modifiedFiles.iterator(); | |||
while(mpathsIt.hasNext()) { | |||
String mpath=mpathsIt.next(); | |||
@@ -785,8 +810,8 @@ public class ResolveMerger extends ThreeWayMerger { | |||
*/ | |||
private File writeMergedFile(MergeResult<RawText> result) | |||
throws FileNotFoundException, IOException { | |||
File workTree = db.getWorkTree(); | |||
FS fs = db.getFS(); | |||
File workTree = nonNullRepo().getWorkTree(); | |||
FS fs = nonNullRepo().getFS(); | |||
File of = new File(workTree, tw.getPathString()); | |||
File parentFolder = of.getParentFile(); | |||
if (!fs.exists(parentFolder)) | |||
@@ -802,7 +827,7 @@ public class ResolveMerger extends ThreeWayMerger { | |||
private ObjectId insertMergeResult(MergeResult<RawText> result) | |||
throws IOException { | |||
TemporaryBuffer.LocalFile buf = new TemporaryBuffer.LocalFile( | |||
db.getDirectory(), 10 << 20); | |||
db != null ? nonNullRepo().getDirectory() : null, 10 << 20); | |||
try { | |||
new MergeFormatter().formatMerge(buf, result, | |||
Arrays.asList(commitNames), CHARACTER_ENCODING); |
@@ -46,7 +46,9 @@ package org.eclipse.jgit.merge; | |||
import java.io.IOException; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.Repository; | |||
/** | |||
@@ -89,6 +91,11 @@ public class StrategyOneSided extends MergeStrategy { | |||
return new OneSide(db, treeIndex); | |||
} | |||
@Override | |||
public Merger newMerger(final ObjectInserter inserter, final Config config) { | |||
return new OneSide(inserter, treeIndex); | |||
} | |||
static class OneSide extends Merger { | |||
private final int treeIndex; | |||
@@ -97,6 +104,11 @@ public class StrategyOneSided extends MergeStrategy { | |||
treeIndex = index; | |||
} | |||
protected OneSide(final ObjectInserter inserter, final int index) { | |||
super(inserter); | |||
treeIndex = index; | |||
} | |||
@Override | |||
protected boolean mergeImpl() throws IOException { | |||
return treeIndex < sourceTrees.length; |
@@ -43,6 +43,8 @@ | |||
package org.eclipse.jgit.merge; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.Repository; | |||
/** | |||
@@ -62,6 +64,11 @@ public class StrategyRecursive extends StrategyResolve { | |||
return new RecursiveMerger(db, inCore); | |||
} | |||
@Override | |||
public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) { | |||
return new RecursiveMerger(inserter, config); | |||
} | |||
@Override | |||
public String getName() { | |||
return "recursive"; //$NON-NLS-1$ |
@@ -43,6 +43,8 @@ | |||
*/ | |||
package org.eclipse.jgit.merge; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.Repository; | |||
/** | |||
@@ -60,8 +62,13 @@ public class StrategyResolve extends ThreeWayMergeStrategy { | |||
return new ResolveMerger(db, inCore); | |||
} | |||
@Override | |||
public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) { | |||
return new ResolveMerger(inserter, config); | |||
} | |||
@Override | |||
public String getName() { | |||
return "resolve"; //$NON-NLS-1$ | |||
} | |||
} | |||
} |
@@ -49,6 +49,7 @@ import org.eclipse.jgit.dircache.DirCache; | |||
import org.eclipse.jgit.dircache.DirCacheBuilder; | |||
import org.eclipse.jgit.dircache.DirCacheEntry; | |||
import org.eclipse.jgit.errors.UnmergedPathException; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
@@ -89,6 +90,11 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy { | |||
return newMerger(db); | |||
} | |||
@Override | |||
public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) { | |||
return new InCoreMerger(inserter); | |||
} | |||
private static class InCoreMerger extends ThreeWayMerger { | |||
private static final int T_BASE = 0; | |||
@@ -110,6 +116,12 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy { | |||
cache = DirCache.newInCore(); | |||
} | |||
InCoreMerger(final ObjectInserter inserter) { | |||
super(inserter); | |||
tw = new NameConflictTreeWalk(null, reader); | |||
cache = DirCache.newInCore(); | |||
} | |||
@Override | |||
protected boolean mergeImpl() throws IOException { | |||
tw.addTree(mergeBase()); |
@@ -50,6 +50,7 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException; | |||
import org.eclipse.jgit.errors.MissingObjectException; | |||
import org.eclipse.jgit.lib.AnyObjectId; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectInserter; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
import org.eclipse.jgit.revwalk.RevTree; | |||
@@ -84,6 +85,17 @@ public abstract class ThreeWayMerger extends Merger { | |||
this(local); | |||
} | |||
/** | |||
* Create a new in-core merge instance from an inserter. | |||
* | |||
* @param inserter | |||
* the inserter to write objects to. | |||
* @since 4.8 | |||
*/ | |||
protected ThreeWayMerger(ObjectInserter inserter) { | |||
super(inserter); | |||
} | |||
/** | |||
* Set the common ancestor tree. | |||
* |