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
@@ -373,7 +373,8 @@ public class AllChangesIndexer
|
|||||||
walk.parseBody(a);
|
walk.parseBody(a);
|
||||||
return walk.parseTree(a.getTree());
|
return walk.parseTree(a.getTree());
|
||||||
case 2:
|
case 2:
|
||||||
return autoMerger.merge(repo, walk, b, mergeStrategy);
|
RevCommit am = autoMerger.merge(repo, walk, b, mergeStrategy);
|
||||||
|
return am == null ? null : am.getTree();
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -17,15 +17,18 @@ package com.google.gerrit.server.patch;
|
|||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.RefNames;
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.eclipse.jgit.diff.Sequence;
|
import org.eclipse.jgit.diff.Sequence;
|
||||||
import org.eclipse.jgit.dircache.DirCache;
|
import org.eclipse.jgit.dircache.DirCache;
|
||||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||||
|
import org.eclipse.jgit.lib.CommitBuilder;
|
||||||
import org.eclipse.jgit.lib.Constants;
|
import org.eclipse.jgit.lib.Constants;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
import org.eclipse.jgit.lib.ObjectInserter;
|
import org.eclipse.jgit.lib.ObjectInserter;
|
||||||
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.RefUpdate;
|
import org.eclipse.jgit.lib.RefUpdate;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
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.ResolveMerger;
|
||||||
import org.eclipse.jgit.merge.ThreeWayMergeStrategy;
|
import org.eclipse.jgit.merge.ThreeWayMergeStrategy;
|
||||||
import org.eclipse.jgit.revwalk.RevCommit;
|
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.revwalk.RevWalk;
|
||||||
import org.eclipse.jgit.util.TemporaryBuffer;
|
import org.eclipse.jgit.util.TemporaryBuffer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -48,11 +51,20 @@ import java.util.Map;
|
|||||||
public class AutoMerger {
|
public class AutoMerger {
|
||||||
private static final Logger log = LoggerFactory.getLogger(AutoMerger.class);
|
private static final Logger log = LoggerFactory.getLogger(AutoMerger.class);
|
||||||
|
|
||||||
|
private final PersonIdent gerritIdent;
|
||||||
|
|
||||||
@Inject
|
@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 {
|
ThreeWayMergeStrategy mergeStrategy) throws IOException {
|
||||||
rw.parseHeaders(merge);
|
rw.parseHeaders(merge);
|
||||||
String hash = merge.name();
|
String hash = merge.name();
|
||||||
@@ -62,7 +74,11 @@ public class AutoMerger {
|
|||||||
+ hash.substring(2);
|
+ hash.substring(2);
|
||||||
Ref ref = repo.getRefDatabase().exactRef(refName);
|
Ref ref = repo.getRefDatabase().exactRef(refName);
|
||||||
if (ref != null && ref.getObjectId() != null) {
|
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);
|
ResolveMerger m = (ResolveMerger) mergeStrategy.newMerger(repo, true);
|
||||||
@@ -178,12 +194,38 @@ public class AutoMerger {
|
|||||||
}
|
}
|
||||||
ins.flush();
|
ins.flush();
|
||||||
|
|
||||||
RefUpdate update = repo.updateRef(refName);
|
return commit(repo, rw, refName, treeId, merge);
|
||||||
update.setNewObjectId(treeId);
|
|
||||||
update.disableRefLog();
|
|
||||||
update.forceUpdate();
|
|
||||||
|
|
||||||
return rw.lookupTree(treeId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public class PatchListKey implements 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(
|
public static final BiMap<Whitespace, Character> WHITESPACE_TYPES = ImmutableBiMap.of(
|
||||||
Whitespace.IGNORE_NONE, 'N',
|
Whitespace.IGNORE_NONE, 'N',
|
||||||
|
Reference in New Issue
Block a user