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);
 | 
			
		||||
          return walk.parseTree(a.getTree());
 | 
			
		||||
        case 2:
 | 
			
		||||
          return autoMerger.merge(repo, walk, b, mergeStrategy);
 | 
			
		||||
          RevCommit am = autoMerger.merge(repo, walk, b, mergeStrategy);
 | 
			
		||||
          return am == null ? null : am.getTree();
 | 
			
		||||
        default:
 | 
			
		||||
          return null;
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -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