diff options
author | Dave Borowitz <dborowitz@google.com> | 2017-03-31 11:49:12 -0400 |
---|---|---|
committer | Jonathan Nieder <jrn@google.com> | 2017-04-05 17:50:54 -0400 |
commit | 4c3e274588060d9ab2e05d7919f506789bcbbc0b (patch) | |
tree | 241e54a6bfdba3a7036c030d094e3da5a5b733da | |
parent | aec22e74cf76d7b7ea53d526b908613eaeac5b55 (diff) | |
download | jgit-4c3e274588060d9ab2e05d7919f506789bcbbc0b.tar.gz jgit-4c3e274588060d9ab2e05d7919f506789bcbbc0b.zip |
Support creating Mergers without a Repository
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: Ib884dce2528424b5bcbbbbfc043baec1886b9bbd
13 files changed, 337 insertions, 22 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java index 255262255a..d8b8750ba3 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/ResolveMergerTest.java @@ -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 @@ -442,6 +453,43 @@ public class ResolveMergerTest extends RepositoryTestCase { } /** + * 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. * @@ -613,6 +661,35 @@ public class ResolveMergerTest extends RepositoryTestCase { } @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 { Git git = Git.wrap(db); @@ -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); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java index db9d87dd17..951568e7bb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java @@ -72,6 +72,16 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { } @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); boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); @@ -80,6 +90,16 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { } @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); boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); @@ -104,6 +124,16 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase { } @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); boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("f"), db.resolve("g") }); diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index 4ac399f9ec..da076dcb7f 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -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 diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index a81c93a013..0e52fccaaa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -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; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeStrategy.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeStrategy.java index 656480e468..af3d5ca078 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeStrategy.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeStrategy.java @@ -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); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java index bee2d03523..0c4488c984 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java @@ -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. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java index f8e1998ed7..1375cd3ea2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java @@ -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; @@ -111,6 +113,17 @@ public class RecursiveMerger extends ResolveMerger { } /** + * 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 * together until you end up with a single base commit. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index f667af278a..1aac352d74 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -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); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java index 12d6c6b413..2224dbc448 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyOneSided.java @@ -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; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java index 22e608ec9d..56128dd93e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyRecursive.java @@ -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; /** @@ -63,6 +65,11 @@ public class StrategyRecursive extends StrategyResolve { } @Override + public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) { + return new RecursiveMerger(inserter, config); + } + + @Override public String getName() { return "recursive"; //$NON-NLS-1$ } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java index 07368e5746..1691bf9e43 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategyResolve.java @@ -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; /** @@ -61,7 +63,12 @@ public class StrategyResolve extends ThreeWayMergeStrategy { } @Override + public ThreeWayMerger newMerger(ObjectInserter inserter, Config config) { + return new ResolveMerger(inserter, config); + } + + @Override public String getName() { return "resolve"; //$NON-NLS-1$ } -}
\ No newline at end of file +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java index ec903c139d..d05e2d4c8d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java @@ -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()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java index fbedaef865..b3ef0fb3e4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ThreeWayMerger.java @@ -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; @@ -85,6 +86,17 @@ public abstract class ThreeWayMerger extends Merger { } /** + * 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. * * @param id |