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:
Saša Živkov
2016-04-01 16:54:11 +02:00
committed by Dave Borowitz
parent c28ebd8d72
commit 9d5a0d3154
3 changed files with 55 additions and 12 deletions

View File

@@ -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);
}
}

View File

@@ -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',