Browse Source

RecursiveMerger: do not insert virtual commits into repository

When merging common ancestors to create a single virtual common
ancestor the commit does not need to be inserted into the Git
repository. Instead just mock it out in memory as part of the
merger's RevWalk pool.

Make the author and committer stable and predictable for any
given pair of merge bases. It is not necessary for the caller's
name or email to be used as the commit will not be written out.

Change-Id: I88d5ee4de121950e1b032a5c10486c9d2c42656c
stable-3.5
Shawn Pearce 10 years ago
parent
commit
4bd28bc958
  1. 35
      org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java

35
org.eclipse.jgit/src/org/eclipse/jgit/merge/RecursiveMerger.java

@ -52,7 +52,9 @@ package org.eclipse.jgit.merge;
import java.io.IOException; import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.TimeZone;
import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.dircache.DirCacheBuilder;
@ -62,7 +64,6 @@ import org.eclipse.jgit.errors.NoMergeBaseException;
import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder; import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
@ -90,8 +91,6 @@ public class RecursiveMerger extends ResolveMerger {
*/ */
public final int MAX_BASES = 200; public final int MAX_BASES = 200;
private PersonIdent ident = new PersonIdent(db);
/** /**
* Normal recursive merge when you want a choice of DirCache placement * Normal recursive merge when you want a choice of DirCache placement
* inCore * inCore
@ -137,7 +136,9 @@ public class RecursiveMerger extends ResolveMerger {
* the second commit to be merged * the second commit to be merged
* @param callDepth * @param callDepth
* the callDepth when this method is called recursively * the callDepth when this method is called recursively
* @return the merge base of two commits * @return the merge base of two commits. If a criss-cross merge required a
* synthetic merge base this commit is visible only the merger's
* RevWalk and will not be in the repository.
* @throws IOException * @throws IOException
* @throws IncorrectObjectTypeException * @throws IncorrectObjectTypeException
* one of the input objects is not a commit. * one of the input objects is not a commit.
@ -228,22 +229,28 @@ public class RecursiveMerger extends ResolveMerger {
* the tree this commit should capture * the tree this commit should capture
* @param parents * @param parents
* the list of parent commits * the list of parent commits
* @return a new (persisted) commit * @return a new commit visible only within this merger's RevWalk.
* @throws IOException * @throws IOException
*/ */
private RevCommit createCommitForTree(ObjectId tree, List<RevCommit> parents) private RevCommit createCommitForTree(ObjectId tree, List<RevCommit> parents)
throws IOException { throws IOException {
CommitBuilder c = new CommitBuilder(); CommitBuilder c = new CommitBuilder();
c.setParentIds(parents);
c.setTreeId(tree); c.setTreeId(tree);
c.setAuthor(ident); c.setParentIds(parents);
c.setCommitter(ident); c.setAuthor(mockAuthor(parents));
ObjectInserter odi = db.newObjectInserter(); c.setCommitter(c.getAuthor());
ObjectId newCommitId = odi.insert(c); return RevCommit.parse(walk, c.build());
odi.flush(); }
RevCommit ret = walk.lookupCommit(newCommitId);
walk.parseHeaders(ret); private static PersonIdent mockAuthor(List<RevCommit> parents) {
return ret; String name = RecursiveMerger.class.getSimpleName();
int time = 0;
for (RevCommit p : parents)
time = Math.max(time, p.getCommitTime());
return new PersonIdent(
name, name + "@JGit", //$NON-NLS-1$
new Date((time + 1) * 1000L),
TimeZone.getTimeZone("GMT+0000")); //$NON-NLS-1$
} }
/** /**

Loading…
Cancel
Save