Merge branch 'stable-3.1'

Change-Id: I9c34cec575fdcfb14b9af5d0b5ef8ed51dc51138
diff --git a/WORKSPACE b/WORKSPACE
index 9b24a27..8083453 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "20079f696c22c733053077b13c0dc6d9902e6b8e",
+    commit = "8dc0767541f16b35d2136eccebffd9ebe2b81133",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/pom.xml b/pom.xml
index 0ef2e07..ad9286c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
   <groupId>com.googlesource.gerrit.plugins.batch</groupId>
   <artifactId>batch</artifactId>
   <packaging>jar</packaging>
-  <version>3.1.0</version>
+  <version>3.2.0</version>
   <name>batch</name>
 
   <properties>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/batch/BatchSubmitter.java b/src/main/java/com/googlesource/gerrit/plugins/batch/BatchSubmitter.java
index 82b944e..a2729b7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/batch/BatchSubmitter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/batch/BatchSubmitter.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.SubmissionId;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.server.IdentifiedUser;
@@ -135,13 +136,17 @@
       throws IOException, RepositoryNotFoundException, RestApiException, UpdateException,
           PermissionBackendException {
     if (dest.changes != null) {
+      // TODO: Is using the first change in the batch for each dest the correct thing to do?
+      Change firstInDest =
+          notesFactory.createChecked(dest.changes.get(0).toPatchSetId().changeId()).getChange();
+      SubmissionId submissionId = new SubmissionId(firstInDest);
       for (Batch.Change change : dest.changes) {
-        closeChange(change.toPatchSetId(), dest.sha1);
+        closeChange(change.toPatchSetId(), dest.sha1, submissionId);
       }
     }
   }
 
-  private void closeChange(PatchSet.Id psId, String sha1)
+  private void closeChange(PatchSet.Id psId, String sha1, SubmissionId submissionId)
       throws IOException, RepositoryNotFoundException, RestApiException, UpdateException,
           PermissionBackendException {
     ChangeNotes changeNotes = notesFactory.createChecked(psId.changeId());
@@ -172,7 +177,8 @@
       bu.setRefLogMessage("merged (batch submit)");
       bu.addOp(
           psId.changeId(),
-          mergedByPushOpFactory.create(requestScopePropagator, psId, destination.branch(), sha1));
+          mergedByPushOpFactory.create(
+              requestScopePropagator, psId, submissionId, destination.branch(), sha1));
       bu.execute();
     }
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBranch.java b/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBranch.java
index 02831e6..5245b9e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBranch.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBranch.java
@@ -19,15 +19,16 @@
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.MergeConflictException;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.NoSuchRefException;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.submit.IntegrationException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 import com.googlesource.gerrit.plugins.batch.util.MergeBuilder.FastForwardMode;
 import java.io.IOException;
+import java.util.Optional;
 import java.util.concurrent.Callable;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.ObjectId;
@@ -86,8 +87,8 @@
 
   @Override
   public ObjectId call()
-      throws IOException, NoSuchRefException, RepositoryNotFoundException, IntegrationException,
-          BadRequestException {
+      throws IOException, NoSuchRefException, RepositoryNotFoundException, BadRequestException,
+          MergeConflictException {
     try (Repository repo = repoManager.openRepository(projectName)) {
       Ref destRef = repo.getRefDatabase().exactRef(destName);
       if (destRef == null) {
@@ -112,17 +113,12 @@
 
   protected MergeStrategy defaultStrategy(MergeStrategy strategy) {
     if (strategy == null) {
-      ProjectState project = projectFromName(projectName);
-      if (project != null && project.is(BooleanProjectConfig.USE_CONTENT_MERGE)) {
+      Optional<ProjectState> project = projectCache.get(projectName);
+      if (project.isPresent() && project.get().is(BooleanProjectConfig.USE_CONTENT_MERGE)) {
         return MergeStrategy.RESOLVE;
       }
       return MergeStrategy.SIMPLE_TWO_WAY_IN_CORE;
     }
     return strategy;
   }
-
-  protected ProjectState projectFromName(Project.NameKey name) {
-    ProjectState ps = projectCache.get(name);
-    return ps != null ? ps : null;
-  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBuilder.java b/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBuilder.java
index 7265604..05552c0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBuilder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/batch/util/MergeBuilder.java
@@ -15,10 +15,10 @@
 
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Project;
+import com.google.gerrit.extensions.restapi.MergeConflictException;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.submit.IntegrationException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 import java.io.IOException;
@@ -121,13 +121,13 @@
   }
 
   @Override
-  public ObjectId call() throws IOException, IntegrationException {
+  public ObjectId call() throws IOException, MergeConflictException {
     try (Repository repo = repoManager.openRepository(project)) {
       return build(repo);
     }
   }
 
-  public ObjectId build(Repository repo) throws IOException, IntegrationException {
+  public ObjectId build(Repository repo) throws IOException, MergeConflictException {
     try (RevWalk revWalk = new RevWalk(repo)) {
       RevCommit firstParentCommit = revWalk.lookupCommit(firstParent);
       RevCommit secondParentCommit = revWalk.lookupCommit(secondParent);
@@ -139,17 +139,17 @@
         return secondParent; // Fast forward merge
       }
       if (fastForwardMode == FastForwardMode.FF_ONLY) {
-        throw new IntegrationException("Merge aborted"); // because not FF
+        throw new MergeConflictException("Merge aborted"); // because not FF
       }
       return merge(repo, revWalk);
     }
   }
 
   protected ObjectId merge(Repository repo, RevWalk revWalk)
-      throws IOException, IntegrationException {
+      throws IOException, MergeConflictException {
     ThreeWayMerger merger = getMerger(repo);
     if (!merger.merge(firstParent, secondParent)) {
-      throw new IntegrationException("Merge conflict");
+      throw new MergeConflictException("Merge conflict");
     }
     message = defaultMessage(revWalk, message);
     return insert(merger, buildCommit(merger));