Merge branch 'stable-3.0' into stable-3.1

* stable-3.0:
  Remove Hugo Arès from developers section in pom.xml files
  ElasticContainer: Upgrade V6_8 to elasticsearch 6.8.10
  Upgrade elasticsearch-rest-client to 7.7.1
  ElasticContainer: Upgrade V7_7 to elasticsearch 7.7.1
  Support /COMMIT_MSG for change edit REST endpoints

Change-Id: I911d0d687a74a629d5a5955420e040088204bbd9
diff --git a/java/com/google/gerrit/server/restapi/change/ChangeEdits.java b/java/com/google/gerrit/server/restapi/change/ChangeEdits.java
index 0adb28e..4864254 100644
--- a/java/com/google/gerrit/server/restapi/change/ChangeEdits.java
+++ b/java/com/google/gerrit/server/restapi/change/ChangeEdits.java
@@ -14,9 +14,13 @@
 
 package com.google.gerrit.server.restapi.change;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
+import com.google.common.io.ByteStreams;
 import com.google.gerrit.entities.Change;
+import com.google.gerrit.entities.Patch;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.common.DiffWebLinkInfo;
@@ -119,7 +123,7 @@
     @Override
     public Response<?> apply(ChangeResource resource, IdString id, Put.Input input)
         throws AuthException, ResourceConflictException, BadRequestException, IOException,
-            PermissionBackendException {
+            PermissionBackendException, BadRequestException {
       putEdit.apply(resource, id.get(), input.content);
       return Response.none();
     }
@@ -275,23 +279,34 @@
 
     private final ChangeEditModifier editModifier;
     private final GitRepositoryManager repositoryManager;
+    private final EditMessage editMessage;
 
     @Inject
-    Put(ChangeEditModifier editModifier, GitRepositoryManager repositoryManager) {
+    Put(
+        ChangeEditModifier editModifier,
+        GitRepositoryManager repositoryManager,
+        EditMessage editMessage) {
       this.editModifier = editModifier;
       this.repositoryManager = repositoryManager;
+      this.editMessage = editMessage;
     }
 
     @Override
     public Response<?> apply(ChangeEditResource rsrc, Input input)
         throws AuthException, ResourceConflictException, BadRequestException, IOException,
-            PermissionBackendException {
+            PermissionBackendException, BadRequestException {
       return apply(rsrc.getChangeResource(), rsrc.getPath(), input.content);
     }
 
     public Response<?> apply(ChangeResource rsrc, String path, RawInput newContent)
         throws ResourceConflictException, AuthException, BadRequestException, IOException,
-            PermissionBackendException {
+            PermissionBackendException, BadRequestException {
+      if (Patch.COMMIT_MSG.equals(path)) {
+        EditMessage.Input editCommitMessageInput = new EditMessage.Input();
+        editCommitMessageInput.message =
+            new String(ByteStreams.toByteArray(newContent.getInputStream()), UTF_8);
+        return Response.ok(editMessage.apply(rsrc, editCommitMessageInput));
+      }
       if (Strings.isNullOrEmpty(path) || path.charAt(0) == '/') {
         throw new ResourceConflictException("Invalid path: " + path);
       }
@@ -345,6 +360,7 @@
   public static class Get implements RestReadView<ChangeEditResource> {
     private final FileContentUtil fileContentUtil;
     private final ProjectCache projectCache;
+    private final GetMessage getMessage;
 
     @Option(
         name = "--base",
@@ -353,14 +369,19 @@
     private boolean base;
 
     @Inject
-    Get(FileContentUtil fileContentUtil, ProjectCache projectCache) {
+    Get(FileContentUtil fileContentUtil, ProjectCache projectCache, GetMessage getMessage) {
       this.fileContentUtil = fileContentUtil;
       this.projectCache = projectCache;
+      this.getMessage = getMessage;
     }
 
     @Override
-    public Response<BinaryResult> apply(ChangeEditResource rsrc) throws IOException {
+    public Response<BinaryResult> apply(ChangeEditResource rsrc) throws AuthException, IOException {
       try {
+        if (Patch.COMMIT_MSG.equals(rsrc.getPath())) {
+          return getMessage.apply(rsrc.getChangeResource());
+        }
+
         ChangeEdit edit = rsrc.getChangeEdit();
         return Response.ok(
             fileContentUtil.getContent(
diff --git a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
index f0448aa..0d6e138 100644
--- a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
+++ b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
@@ -42,6 +42,7 @@
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.common.data.LabelType;
 import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.entities.Patch;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.api.changes.AddReviewerInput;
@@ -297,6 +298,17 @@
   }
 
   @Test
+  public void updateCommitMessageByEditingMagicCommitMsgFile() throws Exception {
+    createEmptyEditFor(changeId);
+    gApi.changes()
+        .id(changeId)
+        .edit()
+        .modifyFile(Patch.COMMIT_MSG, RawInputUtil.create("Foo Bar".getBytes(UTF_8)));
+    assertThat(getEdit(changeId)).isPresent();
+    ensureSameBytes(getFileContentOfEdit(changeId, Patch.COMMIT_MSG), "Foo Bar\n".getBytes(UTF_8));
+  }
+
+  @Test
   @TestProjectInput(createEmptyCommit = false)
   public void updateRootCommitMessage() throws Exception {
     // Re-clone empty repo; TestRepository doesn't let us reset to unborn head.
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
index 15094fd..c20650f 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
@@ -43,7 +43,7 @@
       case V6_7:
         return "blacktop/elasticsearch:6.7.2";
       case V6_8:
-        return "blacktop/elasticsearch:6.8.9";
+        return "blacktop/elasticsearch:6.8.10";
       case V7_0:
         return "blacktop/elasticsearch:7.0.1";
       case V7_1:
@@ -59,7 +59,7 @@
       case V7_6:
         return "blacktop/elasticsearch:7.6.2";
       case V7_7:
-        return "blacktop/elasticsearch:7.7.0";
+        return "blacktop/elasticsearch:7.7.1";
     }
     throw new IllegalStateException("No tests for version: " + version.name());
   }
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index 8e37e15..44deefa 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -44,9 +44,6 @@
       <name>Han-Wen Nienhuys</name>
     </developer>
     <developer>
-      <name>Hugo Arès</name>
-    </developer>
-    <developer>
       <name>Luca Milanesio</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index 23e9b30..8c30887 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -44,9 +44,6 @@
       <name>Han-Wen Nienhuys</name>
     </developer>
     <developer>
-      <name>Hugo Arès</name>
-    </developer>
-    <developer>
       <name>Luca Milanesio</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index ecbc40f..53e468c 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -44,9 +44,6 @@
       <name>Han-Wen Nienhuys</name>
     </developer>
     <developer>
-      <name>Hugo Arès</name>
-    </developer>
-    <developer>
       <name>Luca Milanesio</name>
     </developer>
     <developer>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index 301c669..a435e29 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -44,9 +44,6 @@
       <name>Han-Wen Nienhuys</name>
     </developer>
     <developer>
-      <name>Hugo Arès</name>
-    </developer>
-    <developer>
       <name>Luca Milanesio</name>
     </developer>
     <developer>
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index 19c2eaa..aa913b8 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -102,8 +102,8 @@
     # and httpasyncclient as necessary.
     maven_jar(
         name = "elasticsearch-rest-client",
-        artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.7.0",
-        sha1 = "5fc25eec3940bc0e9b0ffddcf50554a609e9db8e",
+        artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.7.1",
+        sha1 = "6d44a8e35c11df6883747200bcf46f476a1782b8",
     )
 
     maven_jar(