Store commits under refs/cache-automerge/, instead of trees
Storing an (automerge) commit objects under refs/cache-automerge/ is just a small overhead compared to storing the automerge trees. A benefit of storing commits is that we can use them as the input for the blame annotations computation which is implemented in a follow-up change. Any existing tree, stored under refs/cache-automerge/, is replaced with a commit (pointing to that tree) when it gets accessed first time. Change-Id: I9c8b5addedf734e0bb500c176701d7f45e202a76
This commit is contained in:

committed by
Dave Borowitz

parent
c28ebd8d72
commit
9d5a0d3154
@@ -17,15 +17,18 @@ package com.google.gerrit.server.patch;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.RefNames;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.jgit.diff.Sequence;
|
||||
import org.eclipse.jgit.dircache.DirCache;
|
||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||
import org.eclipse.jgit.lib.CommitBuilder;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.RefUpdate;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
@@ -34,7 +37,7 @@ import org.eclipse.jgit.merge.MergeResult;
|
||||
import org.eclipse.jgit.merge.ResolveMerger;
|
||||
import org.eclipse.jgit.merge.ThreeWayMergeStrategy;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevTree;
|
||||
import org.eclipse.jgit.revwalk.RevObject;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.util.TemporaryBuffer;
|
||||
import org.slf4j.Logger;
|
||||
@@ -48,11 +51,20 @@ import java.util.Map;
|
||||
public class AutoMerger {
|
||||
private static final Logger log = LoggerFactory.getLogger(AutoMerger.class);
|
||||
|
||||
private final PersonIdent gerritIdent;
|
||||
|
||||
@Inject
|
||||
AutoMerger() {
|
||||
AutoMerger(@GerritPersonIdent PersonIdent gerritIdent) {
|
||||
this.gerritIdent = gerritIdent;
|
||||
}
|
||||
|
||||
public RevTree merge(Repository repo, RevWalk rw, RevCommit merge,
|
||||
/**
|
||||
* Perform an auto-merge of the parents of the given merge commit.
|
||||
*
|
||||
* @return auto-merge commit or {@code null} if an auto-merge commit
|
||||
* couldn't be created. Headers of the returned RevCommit are parsed.
|
||||
*/
|
||||
public RevCommit merge(Repository repo, RevWalk rw, RevCommit merge,
|
||||
ThreeWayMergeStrategy mergeStrategy) throws IOException {
|
||||
rw.parseHeaders(merge);
|
||||
String hash = merge.name();
|
||||
@@ -62,7 +74,11 @@ public class AutoMerger {
|
||||
+ hash.substring(2);
|
||||
Ref ref = repo.getRefDatabase().exactRef(refName);
|
||||
if (ref != null && ref.getObjectId() != null) {
|
||||
return rw.parseTree(ref.getObjectId());
|
||||
RevObject obj = rw.parseAny(ref.getObjectId());
|
||||
if (obj instanceof RevCommit) {
|
||||
return (RevCommit) obj;
|
||||
}
|
||||
return commit(repo, rw, refName, obj, merge);
|
||||
}
|
||||
|
||||
ResolveMerger m = (ResolveMerger) mergeStrategy.newMerger(repo, true);
|
||||
@@ -178,12 +194,38 @@ public class AutoMerger {
|
||||
}
|
||||
ins.flush();
|
||||
|
||||
RefUpdate update = repo.updateRef(refName);
|
||||
update.setNewObjectId(treeId);
|
||||
update.disableRefLog();
|
||||
update.forceUpdate();
|
||||
|
||||
return rw.lookupTree(treeId);
|
||||
return commit(repo, rw, refName, treeId, merge);
|
||||
}
|
||||
}
|
||||
|
||||
private RevCommit commit(Repository repo, RevWalk rw, String refName,
|
||||
ObjectId tree, RevCommit merge) throws IOException {
|
||||
rw.parseHeaders(merge);
|
||||
// For maximum stability, choose a single ident using the committer time of
|
||||
// the input commit, using the server name and timezone.
|
||||
PersonIdent ident = new PersonIdent(
|
||||
gerritIdent,
|
||||
merge.getCommitterIdent().getWhen(),
|
||||
gerritIdent.getTimeZone());
|
||||
CommitBuilder cb = new CommitBuilder();
|
||||
cb.setAuthor(ident);
|
||||
cb.setCommitter(ident);
|
||||
cb.setTreeId(tree);
|
||||
cb.setMessage("Auto-merge of " + merge.name() + '\n');
|
||||
for (RevCommit p : merge.getParents()) {
|
||||
cb.addParentId(p);
|
||||
}
|
||||
ObjectId commitId;
|
||||
try (ObjectInserter ins = repo.newObjectInserter()) {
|
||||
commitId = ins.insert(cb);
|
||||
ins.flush();
|
||||
}
|
||||
|
||||
RefUpdate ru = repo.updateRef(refName);
|
||||
ru.setNewObjectId(commitId);
|
||||
ru.disableRefLog();
|
||||
ru.forceUpdate();
|
||||
|
||||
return rw.parseCommit(commitId);
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class PatchListKey implements Serializable {
|
||||
static final long serialVersionUID = 19L;
|
||||
static final long serialVersionUID = 20L;
|
||||
|
||||
public static final BiMap<Whitespace, Character> WHITESPACE_TYPES = ImmutableBiMap.of(
|
||||
Whitespace.IGNORE_NONE, 'N',
|
||||
|
Reference in New Issue
Block a user