Add 'gerrit set-topic' SSH command

Currently the only way to set the topic is through the REST API,
however this is a bit annoying if you don't want to use the REST API.
It's desirable to also have an SSH command that covers this use case.

Change-Id: I6686e64a788365bd252df69ae5b3ec9d65aaf068
This commit is contained in:
Michael Kelly
2020-03-04 00:40:26 -08:00
committed by David Pursehouse
parent 0627e6ee9e
commit fc1c3dded8
5 changed files with 152 additions and 0 deletions

View File

@@ -94,6 +94,9 @@ link:cmd-set-project-parent.html[gerrit set-project-parent]::
link:cmd-set-reviewers.html[gerrit set-reviewers]::
Add or remove reviewers on a change.
link:cmd-set-topic.html[gerrit set-topic]::
Set the topic for a change.
link:cmd-stream-events.html[gerrit stream-events]::
Monitor events occurring in real time.

View File

@@ -0,0 +1,43 @@
= gerrit set-topic
== NAME
gerrit set-topic - Set the topic for one or more changes.
== SYNOPSIS
[verse]
--
_ssh_ -p <port> <host> _gerrit set-topic_
<CHANGE>
[ --topic <TOPIC> | -t <TOPIC> ]
--
== DESCRIPTION
Sets the topic for the specified changes.
== ACCESS
Caller must have the rights to modify the topic of the specified changes.
== SCRIPTING
This command is intended to be used in scripts.
== OPTIONS
<CHANGE>::
Required; change id.
--topic::
-topic::
Valid topic name to apply to the specified changes.
== EXAMPLES
Set the topic of the change "I6686e64a788365bd252df69ae5b3ec9d65aaf068" in "MyProject" on branch "master" to "MyTopic".
----
$ ssh -p 29418 user@review.example.com gerrit set-topic MyProject~master~I6686e64a788365bd252df69ae5b3ec9d65aaf068 --topic MyTopic
----
GERRIT
------
Part of link:index.html[Gerrit Code Review]
SEARCHBOX
---------

View File

@@ -109,6 +109,7 @@ public class DefaultCommandModule extends CommandModule {
command(gerrit, ReviewCommand.class);
command(gerrit, SetProjectCommand.class);
command(gerrit, SetReviewersCommand.class);
command(gerrit, SetTopicCommand.class);
command(gerrit, SetMembersCommand.class);
command(gerrit, CreateBranchCommand.class);

View File

@@ -0,0 +1,104 @@
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.sshd.commands;
import com.google.gerrit.entities.Change;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.api.changes.TopicInput;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.extensions.events.TopicEdited;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.change.SetTopicOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.sshd.ChangeArgumentParser;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
import java.util.LinkedHashMap;
import java.util.Map;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
@CommandMetaData(name = "set-topic", description = "Set the topic for one or more changes")
public class SetTopicCommand extends SshCommand {
private final BatchUpdate.Factory updateFactory;
private final ChangeMessagesUtil cmUtil;
private final TopicEdited topicEdited;
private final ChangeArgumentParser changeArgumentParser;
private final SetTopicOp.Factory topicOpFactory;
private Map<Change.Id, ChangeResource> changes = new LinkedHashMap<>();
@Argument(
index = 0,
required = true,
multiValued = true,
metaVar = "CHANGE",
usage = "changes to index")
void addChange(String token) {
try {
changeArgumentParser.addChange(token, changes, null, true);
} catch (UnloggedFailure | StorageException | PermissionBackendException e) {
writeError("warning", e.getMessage());
}
}
@Option(
name = "--topic",
aliases = "-t",
usage = "applies a topic to the given changes",
metaVar = "TOPIC")
private String topic;
@Inject
SetTopicCommand(
BatchUpdate.Factory updateFactory,
ChangeMessagesUtil cmUtil,
TopicEdited topicEdited,
ChangeArgumentParser changeArgumentParser,
SetTopicOp.Factory topicOpFactory) {
this.updateFactory = updateFactory;
this.cmUtil = cmUtil;
this.topicEdited = topicEdited;
this.changeArgumentParser = changeArgumentParser;
this.topicOpFactory = topicOpFactory;
}
@Override
public void run() throws Exception {
TopicInput input = new TopicInput();
if (topic != null) {
input.topic = topic.trim();
}
if (input.topic != null && input.topic.length() > ChangeUtil.TOPIC_MAX_LENGTH) {
throw new BadRequestException(
String.format("topic length exceeds the limit (%s)", ChangeUtil.TOPIC_MAX_LENGTH));
}
for (ChangeResource r : changes.values()) {
SetTopicOp op = topicOpFactory.create(input);
try (BatchUpdate u =
updateFactory.create(r.getChange().getProject(), user, TimeUtil.nowTs())) {
u.addOp(r.getId(), op);
u.execute();
}
}
}
}

View File

@@ -74,6 +74,7 @@ public class SshCommandsIT extends AbstractDaemonTest {
"set-project",
"set-project-parent",
"set-reviewers",
"set-topic",
"stream-events",
"test-submit");