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
This commit is contained in:
parent
aec22e74cf
commit
4c3e274588
|
@ -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.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 void checkMergeEqualTreesWithoutIndex(MergeStrategy strategy)
|
|||
|
||||
/**
|
||||
* 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 void checkMergeEqualTreesInCore(MergeStrategy strategy)
|
|||
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 void checkContentMergeNoConflict(MergeStrategy strategy)
|
|||
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 void checkContentMergeConflict(MergeStrategy strategy)
|
|||
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 @@ private void checkModificationTimeStampOrder(String... pathes)
|
|||
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 void testOurs() throws IOException {
|
|||
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 void testTheirs() throws IOException {
|
|||
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 void testTrivialTwoWay_ok() throws IOException {
|
|||
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 static JGitText get() {
|
|||
/***/ 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.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 static synchronized MergeStrategy[] get() {
|
|||
* @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 @@
|
|||
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 @@
|
|||
* 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 ObjectInserter getObjectInserter() {
|
|||
*
|
||||
* @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 boolean merge(final AnyObjectId... tips) throws IOException {
|
|||
*
|
||||
* @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.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 @@ protected RecursiveMerger(Repository local) {
|
|||
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.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 enum MergeFailureReason {
|
|||
*/
|
||||
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 @@ protected ResolveMerger(Repository local) {
|
|||
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 @@ private void checkout() throws NoWorkTreeException, IOException {
|
|||
// 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 @@ protected void cleanUp() throws NoWorkTreeException,
|
|||
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 @@ private void updateIndex(CanonicalTreeParser base,
|
|||
*/
|
||||
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 @@ private File writeMergedFile(MergeResult<RawText> result)
|
|||
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 @@
|
|||
|
||||
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 Merger newMerger(final Repository db, boolean inCore) {
|
|||
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 @@ protected OneSide(final Repository local, final int index) {
|
|||
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 ThreeWayMerger newMerger(Repository db, boolean inCore) {
|
|||
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 ThreeWayMerger newMerger(Repository db, boolean inCore) {
|
|||
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.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 ThreeWayMerger newMerger(Repository db, boolean inCore) {
|
|||
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 @@ private static class InCoreMerger extends ThreeWayMerger {
|
|||
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.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 @@ protected ThreeWayMerger(final Repository local, boolean inCore) {
|
|||
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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue