Merge "Merge branch 'stable-3.0'"
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 0c2c1ca..7f2aa94 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -6922,6 +6922,9 @@
 |`notify_details`|optional|
 Additional information about whom to notify about the revert as a map
 of recipient type to link:#notify-info[NotifyInfo] entity.
+|`topic`         |optional|
+Name of the topic for the revert change. If not set, the default is the topic
+of the change being reverted.
 |=============================
 
 [[review-info]]
diff --git a/java/com/google/gerrit/extensions/api/changes/RevertInput.java b/java/com/google/gerrit/extensions/api/changes/RevertInput.java
index c1be9b0..c4272e4 100644
--- a/java/com/google/gerrit/extensions/api/changes/RevertInput.java
+++ b/java/com/google/gerrit/extensions/api/changes/RevertInput.java
@@ -24,4 +24,6 @@
   public NotifyHandling notify = NotifyHandling.ALL;
 
   public Map<RecipientType, NotifyInfo> notifyDetails;
+
+  public String topic;
 }
diff --git a/java/com/google/gerrit/server/restapi/change/Revert.java b/java/com/google/gerrit/server/restapi/change/Revert.java
index c69a348..af0d4bf 100644
--- a/java/com/google/gerrit/server/restapi/change/Revert.java
+++ b/java/com/google/gerrit/server/restapi/change/Revert.java
@@ -215,7 +215,7 @@
       ChangeInserter ins =
           changeInserterFactory
               .create(changeId, revertCommit, notes.getChange().getDest().branch())
-              .setTopic(changeToRevert.getTopic());
+              .setTopic(input.topic == null ? changeToRevert.getTopic() : input.topic.trim());
       ins.setMessage("Uploaded patch set 1.");
 
       ReviewerSet reviewerSet = approvalsUtil.getReviewers(notes);
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 61e7582..ab4f77f9 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -785,6 +785,29 @@
   }
 
   @Test
+  public void revertWithDefaultTopic() throws Exception {
+    PushOneCommit.Result result = createChange();
+    gApi.changes().id(result.getChangeId()).current().review(ReviewInput.approve());
+    gApi.changes().id(result.getChangeId()).topic("topic");
+    gApi.changes().id(result.getChangeId()).revision(result.getCommit().name()).submit();
+    RevertInput revertInput = new RevertInput();
+    assertThat(gApi.changes().id(result.getChangeId()).revert(revertInput).topic())
+        .isEqualTo("topic");
+  }
+
+  @Test
+  public void revertWithSetTopic() throws Exception {
+    PushOneCommit.Result result = createChange();
+    gApi.changes().id(result.getChangeId()).current().review(ReviewInput.approve());
+    gApi.changes().id(result.getChangeId()).topic("topic");
+    gApi.changes().id(result.getChangeId()).revision(result.getCommit().name()).submit();
+    RevertInput revertInput = new RevertInput();
+    revertInput.topic = "reverted-not-default";
+    assertThat(gApi.changes().id(result.getChangeId()).revert(revertInput).topic())
+        .isEqualTo(revertInput.topic);
+  }
+
+  @Test
   public void revertNotifications() throws Exception {
     PushOneCommit.Result r = createChange();
     gApi.changes().id(r.getChangeId()).addReviewer(user.email());
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 7c86143..87ac4fd7 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -116,6 +116,7 @@
         margin-top: .5em;
         padding: .5em 0;
       }
+      .hashtag gr-linked-chip,
       .topic gr-linked-chip {
         --linked-chip-text-color: var(--link-color);
       }
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html
index 941f99c..06510dc 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.html
@@ -36,7 +36,7 @@
       .hideInput {
         display: none;
       }
-      input {
+      input#input {
         font-family: var(--monospace-font-family);
         font-size: inherit;
         @apply --text-container-style;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index 87e4975..f0df879 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -442,8 +442,8 @@
     getIsGroupOwner(groupName) {
       const encodeName = encodeURIComponent(groupName);
       const req = {
-        url: `/groups/?owned&q=${encodeName}`,
-        anonymizedUrl: '/groups/owned&q=*',
+        url: `/groups/?owned&g=${encodeName}`,
+        anonymizedUrl: '/groups/owned&g=*',
       };
       return this._fetchSharedCacheURL(req)
           .then(configs => configs.hasOwnProperty(groupName));