ReceiveCommits: Include approvals from magic branch in change message

I52a6799395 extended magic branch options with approvals, but missed
to include the approvals in the change message.

Render the approvals for new change and for new patch set.

* Uploaded patch set 1: Code-Review-1 Verified+1.
* Uploaded patch set 2: Code-Review+1 Verified-1: Commit message was
  updated.

Label votes are only included in the change message, when they differ
from the current votes from the same user. This is the same logic as
implemented in PostReview.

Unit test is extended to verify that the approvals included in change
message. To prevent the test to be flaky and make chronological sorting
order stable (createdOn attribute of message) clock step is bumped to 1
second in AbstractPushForReview.

Reported-By: Khai Do <zaro0508@gmail.com>
Change-Id: I60a5f1447f084dfd3967ee335652df4a75354a71
This commit is contained in:
David Ostrovsky
2015-10-11 10:47:21 +02:00
parent d79ac58829
commit 44a935eb0a
3 changed files with 99 additions and 8 deletions

View File

@@ -68,6 +68,7 @@ import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -1716,7 +1717,9 @@ public class ReceiveCommits {
ChangeMessage msg =
new ChangeMessage(new ChangeMessage.Key(change.getId(),
ChangeUtil.messageUUID(db)), me, ps.getCreatedOn(), ps.getId());
msg.setMessage("Uploaded patch set " + ps.getPatchSetId() + ".");
StringBuilder msgs = renderMessageWithApprovals(ps.getPatchSetId(),
approvals, Collections.<String, PatchSetApproval>emptyMap());
msg.setMessage(msgs.toString() + ".");
ins
.setReviewers(recipients.getReviewers())
@@ -1842,6 +1845,27 @@ public class ReceiveCommits {
}
}
private StringBuilder 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;
}
private class ReplaceRequest {
final Change.Id ontoChange;
final RevCommit newCommit;
@@ -2075,29 +2099,52 @@ public class ReceiveCommits {
return Futures.makeChecked(future, INSERT_EXCEPTION);
}
private ChangeMessage newChangeMessage(ReviewDb db, ChangeKind changeKind)
private ChangeMessage newChangeMessage(ReviewDb db, ChangeKind changeKind,
Map<String, Short> approvals)
throws OrmException {
msg =
new ChangeMessage(new ChangeMessage.Key(change.getId(), ChangeUtil
.messageUUID(db)), currentUser.getAccountId(), newPatchSet.getCreatedOn(),
newPatchSet.getId());
String message = "Uploaded patch set " + newPatchSet.getPatchSetId();
StringBuilder msgs = renderMessageWithApprovals(
newPatchSet.getPatchSetId(), approvals, scanLabels(db, approvals));
switch (changeKind) {
case TRIVIAL_REBASE:
case NO_CHANGE:
message += ": Patch Set " + priorPatchSet.get() + " was rebased";
msgs.append(": Patch Set " + priorPatchSet.get() + " was rebased");
break;
case NO_CODE_CHANGE:
message += ": Commit message was updated";
msgs.append(": Commit message was updated");
break;
case REWORK:
default:
break;
}
msg.setMessage(message + ".");
msg.setMessage(msgs.toString() + ".");
return msg;
}
private Map<String, PatchSetApproval> scanLabels(ReviewDb db,
Map<String, Short> approvals)
throws OrmException {
Map<String, PatchSetApproval> current = new HashMap<>();
// We optimize here and only retrieve current when approvals provided
if (!approvals.isEmpty()) {
for (PatchSetApproval a : approvalsUtil.byPatchSetUser(
db, changeCtl, priorPatchSet, currentUser.getAccountId())) {
if (a.isSubmit()) {
continue;
}
LabelType lt = labelTypes.byLabel(a.getLabelId());
if (lt != null) {
current.put(lt.getName(), a);
}
}
}
return current;
}
PatchSet.Id upsertEdit() {
if (cmd.getResult() == NOT_ATTEMPTED) {
cmd.execute(rp);
@@ -2158,7 +2205,8 @@ public class ReceiveCommits {
changeKind = changeKindCache.getChangeKind(
projectControl.getProjectState(), repo, priorCommit, newCommit);
cmUtil.addChangeMessage(db, update, newChangeMessage(db, changeKind));
cmUtil.addChangeMessage(db, update, newChangeMessage(db, changeKind,
approvals));
if (mergedIntoRef == null) {
// Change should be new, so it can go through review again.