Add reviewers to the attention set if marking a change ready for review

Another useful default for adding users to the attention set is about
marking a change ready for review. This change ensures that all
reviewers are added to the attention set when a change exits "work in
progress" state and becomes "ready for review".

Via the "review" endpoint, it is currently possible to add or remove
reviewers while marking a change ready for review. In this case, we
ensure that those new reviewers are handled correctly: New reviewers
that are added while marking a change ready for review will also be
added to the attention set, while reviewers that are removed while
marking the change ready for review will not be added.

Change-Id: I2442f167bee31040bab85c19116f6308a0873694
This commit is contained in:
Gal Paikin
2020-05-28 12:12:45 +02:00
parent fb6642911c
commit 8bf2a18575
4 changed files with 96 additions and 21 deletions

View File

@@ -17,7 +17,6 @@ package com.google.gerrit.server.change;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.AttentionSetUpdate.Operation;
@@ -81,9 +80,8 @@ public class AddToAttentionSetOp implements BatchUpdateOp {
ChangeUpdate update = ctx.getUpdate(ctx.getChange().currentPatchSetId());
update.addToPlannedAttentionSetUpdates(
ImmutableSet.of(
AttentionSetUpdate.createForWrite(
attentionUserId, AttentionSetUpdate.Operation.ADD, reason)));
AttentionSetUpdate.createForWrite(
attentionUserId, AttentionSetUpdate.Operation.ADD, reason));
if (withChangeMessage) {
addChangeMessage(ctx, update);
}

View File

@@ -17,7 +17,6 @@ package com.google.gerrit.server.change;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.AttentionSetUpdate.Operation;
@@ -81,8 +80,7 @@ public class RemoveFromAttentionSetOp implements BatchUpdateOp {
ChangeUpdate update = ctx.getUpdate(ctx.getChange().currentPatchSetId());
update.addToPlannedAttentionSetUpdates(
ImmutableSet.of(
AttentionSetUpdate.createForWrite(attentionUserId, Operation.REMOVE, reason)));
AttentionSetUpdate.createForWrite(attentionUserId, Operation.REMOVE, reason));
if (withChangeMessage) {
addChangeMessage(ctx, update);
}

View File

@@ -50,6 +50,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import com.google.gerrit.common.data.SubmitRecord;
@@ -406,6 +407,10 @@ public class ChangeUpdate extends AbstractChangeUpdate {
.forEach(u -> plannedAttentionSetUpdates.putIfAbsent(u.account(), u));
}
public void addToPlannedAttentionSetUpdates(AttentionSetUpdate update) {
addToPlannedAttentionSetUpdates(ImmutableSet.of(update));
}
public void setAssignee(Account.Id assignee) {
checkArgument(assignee != null, "use removeAssignee");
this.assignee = Optional.of(assignee);
@@ -647,7 +652,6 @@ public class ChangeUpdate extends AbstractChangeUpdate {
addIdent(msg, e.getKey()).append('\n');
}
applyReviewerUpdatesToAttentionSet();
for (Map.Entry<Address, ReviewerStateInternal> e : reviewersByEmail.entrySet()) {
addFooter(msg, e.getValue().getByEmailFooterKey(), e.getKey().toString());
}
@@ -710,6 +714,8 @@ public class ChangeUpdate extends AbstractChangeUpdate {
addFooter(msg, FOOTER_WORK_IN_PROGRESS, workInProgress);
if (workInProgress) {
clearAttentionSet("Change was marked work in progress");
} else {
addAllReviewersToAttentionSet();
}
}
@@ -742,23 +748,20 @@ public class ChangeUpdate extends AbstractChangeUpdate {
if (getNotes().getAttentionSet() == null) {
return;
}
Set<AttentionSetUpdate> removeAll =
AttentionSetUtil.additionsOnly(getNotes().getAttentionSet()).stream()
.map(
a ->
AttentionSetUpdate.createForWrite(
a.account(), AttentionSetUpdate.Operation.REMOVE, reason))
.collect(Collectors.toSet());
addToPlannedAttentionSetUpdates(removeAll);
AttentionSetUtil.additionsOnly(getNotes().getAttentionSet()).stream()
.map(
a ->
AttentionSetUpdate.createForWrite(
a.account(), AttentionSetUpdate.Operation.REMOVE, reason))
.forEach(a -> addToPlannedAttentionSetUpdates(a));
}
private void applyReviewerUpdatesToAttentionSet() {
if (workInProgress != null || getNotes().getChange().isWorkInProgress()) {
if ((workInProgress != null && workInProgress == true)
|| getNotes().getChange().isWorkInProgress()) {
// Users shouldn't be added to the attention set if the change is work in progress.
return;
}
Set<Account.Id> currentReviewers =
getNotes().getReviewers().byState(ReviewerStateInternal.REVIEWER);
Set<AttentionSetUpdate> updates = new HashSet();
@@ -781,6 +784,15 @@ public class ChangeUpdate extends AbstractChangeUpdate {
addToPlannedAttentionSetUpdates(updates);
}
private void addAllReviewersToAttentionSet() {
getNotes().getReviewers().byState(ReviewerStateInternal.REVIEWER).stream()
.map(
r ->
AttentionSetUpdate.createForWrite(
r, AttentionSetUpdate.Operation.ADD, "Change was marked ready for review"))
.forEach(a -> addToPlannedAttentionSetUpdates(a));
}
/**
* Any updates to the attention set must be done in {@link #addToPlannedAttentionSetUpdates}. This
* method is called after all the updates are finished to do the updates once and for real.