Handle commit validation errors when publishing change edit

When a commit validator throws a CommitValidationException during
publish of a new patch set from the inline editor, it is translated
to an InvalidChangeOperationException which results in an internal
server error message being displayed to the user.

Instead, catch the InvalidChangeOperationException and throw a
ResourceConflictException, which results in the actual error message
being displayed to the user.

The corresponding change in the cookbook plugin includes an example
of commit validation to reproduce this case.

Bug: Issue 3442
Change-Id: I95b88dc6f2bc76df088ebef50a52974b33cab5ad
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishChangeEdit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishChangeEdit.java
index 952636f..5db46ae 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishChangeEdit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PublishChangeEdit.java
@@ -28,7 +28,6 @@
 import com.google.gerrit.extensions.restapi.RestView;
 import com.google.gerrit.server.edit.ChangeEdit;
 import com.google.gerrit.server.edit.ChangeEditUtil;
-import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
@@ -84,7 +83,7 @@
     @Override
     public Response<?> apply(ChangeResource rsrc, Publish.Input in)
         throws AuthException, ResourceConflictException, NoSuchChangeException,
-        IOException, InvalidChangeOperationException, OrmException {
+        IOException, OrmException {
       Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getChange());
       if (!edit.isPresent()) {
         throw new ResourceConflictException(String.format(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java
index dadd5af6..933007d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/edit/ChangeEditUtil.java
@@ -143,13 +143,11 @@
    * @param edit change edit to publish
    * @throws NoSuchChangeException
    * @throws IOException
-   * @throws InvalidChangeOperationException
    * @throws OrmException
    * @throws ResourceConflictException
    */
   public void publish(ChangeEdit edit) throws NoSuchChangeException,
-      IOException, InvalidChangeOperationException,
-      OrmException, ResourceConflictException {
+      IOException, OrmException, ResourceConflictException {
     Change change = edit.getChange();
     try (Repository repo = gitManager.openRepository(change.getProject());
         RevWalk rw = new RevWalk(repo);
@@ -160,12 +158,16 @@
             "only edit for current patch set can be published");
       }
 
-      Change updatedChange =
-          insertPatchSet(edit, change, repo, rw, basePatchSet,
-              squashEdit(rw, inserter, edit.getEditCommit(), basePatchSet));
-      // TODO(davido): This should happen in the same BatchRefUpdate.
-      deleteRef(repo, edit);
-      indexer.index(db.get(), updatedChange);
+      try {
+        Change updatedChange =
+            insertPatchSet(edit, change, repo, rw, basePatchSet,
+                squashEdit(rw, inserter, edit.getEditCommit(), basePatchSet));
+        // TODO(davido): This should happen in the same BatchRefUpdate.
+        deleteRef(repo, edit);
+        indexer.index(db.get(), updatedChange);
+      } catch (InvalidChangeOperationException e) {
+        throw new ResourceConflictException(e.getMessage());
+      }
     }
   }
 
diff --git a/plugins/cookbook-plugin b/plugins/cookbook-plugin
index a93641d..f5edbf0 160000
--- a/plugins/cookbook-plugin
+++ b/plugins/cookbook-plugin
@@ -1 +1 @@
-Subproject commit a93641db50f52e24421f75671bb1d4df268dd722
+Subproject commit f5edbf0b1db7186df382659f29f741333eaf4923