Allow setting a comment message on a push
Gerrit has a feature that allow setting labels, reviewers, and topic on push[1] of a new change or patchset. This adds an additional 'message' parameter to allow setting a comment message. [1] https://gerrit-review.googlesource.com/Documentation/user-upload.html#push_create Change-Id: I9e242e4de2892723a0eb03c8a3b7fe3c574058ac Feature: Issue 4015
This commit is contained in:
@@ -178,6 +178,20 @@ updates:
|
|||||||
git push ssh://john.doe@git.example.com:29418/kernel/common HEAD:refs/for/experimental%topic=driver/i42
|
git push ssh://john.doe@git.example.com:29418/kernel/common HEAD:refs/for/experimental%topic=driver/i42
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[message]]
|
||||||
|
A comment message can be applied to the change by using the `message` (or `m`)
|
||||||
|
option:
|
||||||
|
|
||||||
|
====
|
||||||
|
git push ssh://john.doe@git.example.com:29418/kernel/common HEAD:refs/for/experimental%m=This_is_a_rebase_on_master
|
||||||
|
====
|
||||||
|
|
||||||
|
.Note
|
||||||
|
****
|
||||||
|
git push refs parameter does not allow spaces. Use the '_' character instead,
|
||||||
|
it will then be applied as "This is a rebase on master".
|
||||||
|
****
|
||||||
|
|
||||||
[[review_labels]]
|
[[review_labels]]
|
||||||
Review labels can be applied to the change by using the `label` (or `l`)
|
Review labels can be applied to the change by using the `label` (or `l`)
|
||||||
option in the reference:
|
option in the reference:
|
||||||
|
@@ -34,6 +34,7 @@ import com.google.gerrit.extensions.api.changes.ReviewInput;
|
|||||||
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||||
import com.google.gerrit.extensions.client.InheritableBoolean;
|
import com.google.gerrit.extensions.client.InheritableBoolean;
|
||||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||||
|
import com.google.gerrit.extensions.common.ChangeMessageInfo;
|
||||||
import com.google.gerrit.extensions.common.EditInfo;
|
import com.google.gerrit.extensions.common.EditInfo;
|
||||||
import com.google.gerrit.extensions.common.LabelInfo;
|
import com.google.gerrit.extensions.common.LabelInfo;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
@@ -51,6 +52,7 @@ import org.junit.Before;
|
|||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
||||||
@@ -236,6 +238,20 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
|||||||
assertThat(edit).isNotNull();
|
assertThat(edit).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPushForMasterWithMessage() throws Exception {
|
||||||
|
PushOneCommit.Result r = pushTo("refs/for/master/%m=my_test_message");
|
||||||
|
r.assertOkStatus();
|
||||||
|
r.assertChange(Change.Status.NEW, null);
|
||||||
|
ChangeInfo ci = get(r.getChangeId());
|
||||||
|
Collection<ChangeMessageInfo> changeMessages = ci.messages;
|
||||||
|
assertThat(changeMessages).hasSize(1);
|
||||||
|
for (ChangeMessageInfo cm : changeMessages) {
|
||||||
|
assertThat(cm.message).isEqualTo(
|
||||||
|
"Uploaded patch set 1.\nmy test message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPushForMasterWithApprovals() throws Exception {
|
public void testPushForMasterWithApprovals() throws Exception {
|
||||||
PushOneCommit.Result r = pushTo("refs/for/master/%l=Code-Review");
|
PushOneCommit.Result r = pushTo("refs/for/master/%l=Code-Review");
|
||||||
|
@@ -47,6 +47,7 @@ import com.google.gerrit.server.notedb.ChangeUpdate;
|
|||||||
import com.google.gerrit.server.notedb.NotesMigration;
|
import com.google.gerrit.server.notedb.NotesMigration;
|
||||||
import com.google.gerrit.server.notedb.ReviewerStateInternal;
|
import com.google.gerrit.server.notedb.ReviewerStateInternal;
|
||||||
import com.google.gerrit.server.project.ChangeControl;
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
|
import com.google.gerrit.server.util.LabelVote;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
@@ -330,4 +331,25 @@ public class ApprovalsUtil {
|
|||||||
}
|
}
|
||||||
return submitter;
|
return submitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String renderMessageWithApprovals(int patchSetId,
|
||||||
|
Map<String, Short> n, Map<String, PatchSetApproval> c) {
|
||||||
|
StringBuilder msgs = new StringBuilder("Uploaded patch set " + patchSetId);
|
||||||
|
if (!n.isEmpty()) {
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, Short> e : n.entrySet()) {
|
||||||
|
if (c.containsKey(e.getKey())
|
||||||
|
&& c.get(e.getKey()).getValue() == e.getValue()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (first) {
|
||||||
|
msgs.append(":");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
msgs.append(" ")
|
||||||
|
.append(LabelVote.create(e.getKey(), e.getValue()).format());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msgs.append('.').toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1127,6 +1127,7 @@ public class ReceiveCommits {
|
|||||||
Set<Account.Id> reviewer = Sets.newLinkedHashSet();
|
Set<Account.Id> reviewer = Sets.newLinkedHashSet();
|
||||||
Set<Account.Id> cc = Sets.newLinkedHashSet();
|
Set<Account.Id> cc = Sets.newLinkedHashSet();
|
||||||
Map<String, Short> labels = new HashMap<>();
|
Map<String, Short> labels = new HashMap<>();
|
||||||
|
String message;
|
||||||
List<RevCommit> baseCommit;
|
List<RevCommit> baseCommit;
|
||||||
LabelTypes labelTypes;
|
LabelTypes labelTypes;
|
||||||
CmdLineParser clp;
|
CmdLineParser clp;
|
||||||
@@ -1183,6 +1184,13 @@ public class ReceiveCommits {
|
|||||||
labels.put(v.label(), v.value());
|
labels.put(v.label(), v.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Option(name = "--message", aliases = {"-m"}, metaVar = "MESSAGE",
|
||||||
|
usage = "Comment message to apply to the review")
|
||||||
|
void addMessage(final String token) {
|
||||||
|
// git push does not allow spaces in refs.
|
||||||
|
message = token.replace("_", " ");
|
||||||
|
}
|
||||||
|
|
||||||
@Option(name = "--hashtag", aliases = {"-t"}, metaVar = "HASHTAG",
|
@Option(name = "--hashtag", aliases = {"-t"}, metaVar = "HASHTAG",
|
||||||
usage = "add hashtag to changes")
|
usage = "add hashtag to changes")
|
||||||
void addHashtag(String token) throws CmdLineException {
|
void addHashtag(String token) throws CmdLineException {
|
||||||
@@ -1750,8 +1758,12 @@ public class ReceiveCommits {
|
|||||||
recipients.add(getRecipientsFromFooters(
|
recipients.add(getRecipientsFromFooters(
|
||||||
accountResolver, magicBranch.draft, footerLines));
|
accountResolver, magicBranch.draft, footerLines));
|
||||||
recipients.remove(me);
|
recipients.remove(me);
|
||||||
String msg = renderMessageWithApprovals(psId.get(), null,
|
StringBuilder msg =
|
||||||
approvals, Collections.<String, PatchSetApproval> emptyMap());
|
new StringBuilder(ApprovalsUtil.renderMessageWithApprovals(psId.get(),
|
||||||
|
approvals, Collections.<String, PatchSetApproval> emptyMap()));
|
||||||
|
if (!Strings.isNullOrEmpty(magicBranch.message)) {
|
||||||
|
msg.append("\n").append(magicBranch.message);
|
||||||
|
}
|
||||||
try (BatchUpdate bu = batchUpdateFactory.create(state.db,
|
try (BatchUpdate bu = batchUpdateFactory.create(state.db,
|
||||||
magicBranch.dest.getParentKey(), user, TimeUtil.nowTs())) {
|
magicBranch.dest.getParentKey(), user, TimeUtil.nowTs())) {
|
||||||
bu.setRepository(state.repo, state.rw, state.ins);
|
bu.setRepository(state.repo, state.rw, state.ins);
|
||||||
@@ -1759,7 +1771,7 @@ public class ReceiveCommits {
|
|||||||
.setReviewers(recipients.getReviewers())
|
.setReviewers(recipients.getReviewers())
|
||||||
.setExtraCC(recipients.getCcOnly())
|
.setExtraCC(recipients.getCcOnly())
|
||||||
.setApprovals(approvals)
|
.setApprovals(approvals)
|
||||||
.setMessage(msg)
|
.setMessage(msg.toString())
|
||||||
.setNotify(magicBranch.notify)
|
.setNotify(magicBranch.notify)
|
||||||
.setRequestScopePropagator(requestScopePropagator)
|
.setRequestScopePropagator(requestScopePropagator)
|
||||||
.setSendMail(true)
|
.setSendMail(true)
|
||||||
@@ -1890,32 +1902,6 @@ public class ReceiveCommits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String renderMessageWithApprovals(int patchSetId, String suffix,
|
|
||||||
Map<String, Short> n, Map<String, PatchSetApproval> c) {
|
|
||||||
StringBuilder msgs = new StringBuilder("Uploaded patch set " + patchSetId);
|
|
||||||
if (!n.isEmpty()) {
|
|
||||||
boolean first = true;
|
|
||||||
for (Map.Entry<String, Short> e : n.entrySet()) {
|
|
||||||
if (c.containsKey(e.getKey())
|
|
||||||
&& c.get(e.getKey()).getValue() == e.getValue()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (first) {
|
|
||||||
msgs.append(":");
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
msgs.append(" ")
|
|
||||||
.append(LabelVote.create(e.getKey(), e.getValue()).format());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty(suffix)) {
|
|
||||||
msgs.append(suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgs.append('.').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ReplaceRequest {
|
private class ReplaceRequest {
|
||||||
final Change.Id ontoChange;
|
final Change.Id ontoChange;
|
||||||
final ObjectId newCommitId;
|
final ObjectId newCommitId;
|
||||||
|
@@ -49,7 +49,6 @@ import com.google.gerrit.server.project.ChangeControl;
|
|||||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||||
import com.google.gerrit.server.project.ProjectControl;
|
import com.google.gerrit.server.project.ProjectControl;
|
||||||
import com.google.gerrit.server.query.change.ChangeData;
|
import com.google.gerrit.server.query.change.ChangeData;
|
||||||
import com.google.gerrit.server.util.LabelVote;
|
|
||||||
import com.google.gerrit.server.util.RequestScopePropagator;
|
import com.google.gerrit.server.util.RequestScopePropagator;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.assistedinject.Assisted;
|
import com.google.inject.assistedinject.Assisted;
|
||||||
@@ -201,8 +200,10 @@ public class ReplaceOp extends BatchUpdate.Op {
|
|||||||
ChangeUpdate update = ctx.getUpdate(patchSetId);
|
ChangeUpdate update = ctx.getUpdate(patchSetId);
|
||||||
update.setSubjectForCommit("Create patch set " + patchSetId.get());
|
update.setSubjectForCommit("Create patch set " + patchSetId.get());
|
||||||
|
|
||||||
|
String reviewMessage = null;
|
||||||
if (magicBranch != null) {
|
if (magicBranch != null) {
|
||||||
recipients.add(magicBranch.getMailRecipients());
|
recipients.add(magicBranch.getMailRecipients());
|
||||||
|
reviewMessage = magicBranch.message;
|
||||||
approvals.putAll(magicBranch.labels);
|
approvals.putAll(magicBranch.labels);
|
||||||
Set<String> hashtags = magicBranch.hashtags;
|
Set<String> hashtags = magicBranch.hashtags;
|
||||||
if (hashtags != null && !hashtags.isEmpty()) {
|
if (hashtags != null && !hashtags.isEmpty()) {
|
||||||
@@ -242,12 +243,21 @@ public class ReplaceOp extends BatchUpdate.Op {
|
|||||||
approvals);
|
approvals);
|
||||||
recipients.add(oldRecipients);
|
recipients.add(oldRecipients);
|
||||||
|
|
||||||
|
String approvalMessage = ApprovalsUtil.renderMessageWithApprovals(
|
||||||
|
patchSetId.get(), approvals, scanLabels(ctx, approvals));
|
||||||
|
StringBuilder message = new StringBuilder(approvalMessage);
|
||||||
|
String kindMessage = changeKindMessage(changeKind);
|
||||||
|
if (!Strings.isNullOrEmpty(kindMessage)) {
|
||||||
|
message.append(kindMessage);
|
||||||
|
}
|
||||||
|
if (!Strings.isNullOrEmpty(reviewMessage)) {
|
||||||
|
message.append("\n").append(reviewMessage);
|
||||||
|
}
|
||||||
msg = new ChangeMessage(
|
msg = new ChangeMessage(
|
||||||
new ChangeMessage.Key(change.getId(),
|
new ChangeMessage.Key(change.getId(),
|
||||||
ChangeUtil.messageUUID(ctx.getDb())),
|
ChangeUtil.messageUUID(ctx.getDb())),
|
||||||
ctx.getUser().getAccountId(), ctx.getWhen(), patchSetId);
|
ctx.getUser().getAccountId(), ctx.getWhen(), patchSetId);
|
||||||
msg.setMessage(renderMessageWithApprovals(patchSetId.get(),
|
msg.setMessage(message.toString());
|
||||||
changeKindMessage(changeKind), approvals, scanLabels(ctx, approvals)));
|
|
||||||
cmUtil.addChangeMessage(ctx.getDb(), update, msg);
|
cmUtil.addChangeMessage(ctx.getDb(), update, msg);
|
||||||
|
|
||||||
if (mergedIntoRef == null) {
|
if (mergedIntoRef == null) {
|
||||||
@@ -272,32 +282,6 @@ public class ReplaceOp extends BatchUpdate.Op {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String renderMessageWithApprovals(int patchSetId,
|
|
||||||
String suffix, Map<String, Short> n, Map<String, PatchSetApproval> c) {
|
|
||||||
StringBuilder msgs = new StringBuilder("Uploaded patch set " + patchSetId);
|
|
||||||
if (!n.isEmpty()) {
|
|
||||||
boolean first = true;
|
|
||||||
for (Map.Entry<String, Short> e : n.entrySet()) {
|
|
||||||
if (c.containsKey(e.getKey())
|
|
||||||
&& c.get(e.getKey()).getValue() == e.getValue()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (first) {
|
|
||||||
msgs.append(":");
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
msgs.append(" ")
|
|
||||||
.append(LabelVote.create(e.getKey(), e.getValue()).format());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty(suffix)) {
|
|
||||||
msgs.append(suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgs.append('.').toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, PatchSetApproval> scanLabels(ChangeContext ctx,
|
private Map<String, PatchSetApproval> scanLabels(ChangeContext ctx,
|
||||||
Map<String, Short> approvals) throws OrmException {
|
Map<String, Short> approvals) throws OrmException {
|
||||||
Map<String, PatchSetApproval> current = new HashMap<>();
|
Map<String, PatchSetApproval> current = new HashMap<>();
|
||||||
|
Reference in New Issue
Block a user