use of com.google.gerrit.extensions.api.changes.ReviewResult in project gerrit by GerritCodeReview.
the class PostReview method apply.
public Response<ReviewResult> apply(BatchUpdate.Factory updateFactory, RevisionResource revision, ReviewInput input, Timestamp ts) throws RestApiException, UpdateException, OrmException, IOException, PermissionBackendException {
// Respect timestamp, but truncate at change created-on time.
ts = Ordering.natural().max(ts, revision.getChange().getCreatedOn());
if (revision.getEdit().isPresent()) {
throw new ResourceConflictException("cannot post review on edit");
}
if (input.onBehalfOf != null) {
revision = onBehalfOf(revision, input);
} else if (input.drafts == null) {
input.drafts = DraftHandling.DELETE;
}
if (input.labels != null) {
checkLabels(revision, input.strictLabels, input.labels);
}
if (input.comments != null) {
cleanUpComments(input.comments);
checkComments(revision, input.comments);
}
if (input.robotComments != null) {
if (!migration.readChanges()) {
throw new MethodNotAllowedException("robot comments not supported");
}
checkRobotComments(revision, input.robotComments);
}
if (input.notify == null) {
log.warn("notify = null; assuming notify = NONE");
input.notify = NotifyHandling.NONE;
}
ListMultimap<RecipientType, Account.Id> accountsToNotify = notifyUtil.resolveAccounts(input.notifyDetails);
Map<String, AddReviewerResult> reviewerJsonResults = null;
List<PostReviewers.Addition> reviewerResults = Lists.newArrayList();
boolean hasError = false;
boolean confirm = false;
if (input.reviewers != null) {
reviewerJsonResults = Maps.newHashMap();
for (AddReviewerInput reviewerInput : input.reviewers) {
// Prevent notifications because setting reviewers is batched.
reviewerInput.notify = NotifyHandling.NONE;
PostReviewers.Addition result = postReviewers.prepareApplication(revision.getChangeResource(), reviewerInput, true);
reviewerJsonResults.put(reviewerInput.reviewer, result.result);
if (result.result.error != null) {
hasError = true;
continue;
}
if (result.result.confirm != null) {
confirm = true;
continue;
}
reviewerResults.add(result);
}
}
ReviewResult output = new ReviewResult();
output.reviewers = reviewerJsonResults;
if (hasError || confirm) {
return Response.withStatusCode(SC_BAD_REQUEST, output);
}
output.labels = input.labels;
try (BatchUpdate bu = updateFactory.create(db.get(), revision.getChange().getProject(), revision.getUser(), ts)) {
Account.Id id = revision.getUser().getAccountId();
boolean ccOrReviewer = false;
if (input.labels != null && !input.labels.isEmpty()) {
ccOrReviewer = input.labels.values().stream().filter(v -> v != 0).findFirst().isPresent();
}
if (!ccOrReviewer) {
// Check if user was already CCed or reviewing prior to this review.
ReviewerSet currentReviewers = approvalsUtil.getReviewers(db.get(), revision.getChangeResource().getNotes());
ccOrReviewer = currentReviewers.all().contains(id);
}
// themselves as a reviewer or to the CC list.
for (PostReviewers.Addition reviewerResult : reviewerResults) {
bu.addOp(revision.getChange().getId(), reviewerResult.op);
if (!ccOrReviewer && reviewerResult.result.reviewers != null) {
for (ReviewerInfo reviewerInfo : reviewerResult.result.reviewers) {
if (Objects.equals(id.get(), reviewerInfo._accountId)) {
ccOrReviewer = true;
break;
}
}
}
if (!ccOrReviewer && reviewerResult.result.ccs != null) {
for (AccountInfo accountInfo : reviewerResult.result.ccs) {
if (Objects.equals(id.get(), accountInfo._accountId)) {
ccOrReviewer = true;
break;
}
}
}
}
if (!ccOrReviewer) {
// User posting this review isn't currently in the reviewer or CC list,
// isn't being explicitly added, and isn't voting on any label.
// Automatically CC them on this change so they receive replies.
PostReviewers.Addition selfAddition = postReviewers.ccCurrentUser(revision.getUser(), revision);
bu.addOp(revision.getChange().getId(), selfAddition.op);
}
bu.addOp(revision.getChange().getId(), new Op(revision.getPatchSet().getId(), input, accountsToNotify));
bu.execute();
for (PostReviewers.Addition reviewerResult : reviewerResults) {
reviewerResult.gatherResults();
}
emailReviewers(revision.getChange(), reviewerResults, input.notify, accountsToNotify);
}
return Response.ok(output);
}
use of com.google.gerrit.extensions.api.changes.ReviewResult in project gerrit by GerritCodeReview.
the class PostReviewIT method addingAndDeletingReviewers.
@Test
public void addingAndDeletingReviewers() throws Exception {
PushOneCommit.Result r = createChange();
TestAccount user2 = accountCreator.user2();
TestAccount user3 = accountCreator.create("user3", "user3@email.com", "user3", "user3");
TestAccount user4 = accountCreator.create("user4", "user4@email.com", "user4", "user4");
// add user and user2
gApi.changes().id(r.getChangeId()).current().review(ReviewInput.create().reviewer(user.email()).reviewer(user2.email()));
sender.clear();
TestReviewerAddedListener testReviewerAddedListener = new TestReviewerAddedListener();
TestReviewerDeletedListener testReviewerDeletedListener = new TestReviewerDeletedListener();
try (Registration registration = extensionRegistry.newRegistration().add(testReviewerAddedListener).add(testReviewerDeletedListener)) {
// remove user and user2 while adding user3 and user4
ReviewResult reviewResult = gApi.changes().id(r.getChangeId()).current().review(ReviewInput.create().reviewer(user.email(), ReviewerState.REMOVED, /* confirmed= */
true).reviewer(user2.email(), ReviewerState.REMOVED, /* confirmed= */
true).reviewer(user3.email()).reviewer(user4.email()));
assertThat(reviewResult.reviewers.values().stream().filter(a -> a.removed != null).map(a -> a.removed.name).collect(toImmutableSet())).containsExactly(user.fullName(), user2.fullName());
assertThat(reviewResult.reviewers.values().stream().filter(a -> a.reviewers != null).map(a -> Iterables.getOnlyElement(a.reviewers).name).collect(toImmutableSet())).containsExactly(user3.fullName(), user4.fullName());
}
assertThat(gApi.changes().id(r.getChangeId()).reviewers().stream().map(a -> a.name).collect(toImmutableSet())).containsExactly(user3.fullName(), user4.fullName());
// Ensure only one batch email was sent for this operation
FakeEmailSender.Message message = Iterables.getOnlyElement(sender.getMessages());
assertThat(message.body()).containsMatch(Pattern.quote("Hello ") + "(" + Pattern.quote(String.format("%s, %s", user3.fullName(), user4.fullName())) + "|" + Pattern.quote(String.format("%s, %s", user4.fullName(), user3.fullName())) + ")");
assertThat(message.htmlBody()).containsMatch("(" + Pattern.quote(String.format("%s and %s", user3.fullName(), user4.fullName())) + "|" + Pattern.quote(String.format("%s and %s", user4.fullName(), user3.fullName())) + ")" + Pattern.quote(" to <strong>review</strong> this change"));
assertThat(message.body()).containsMatch(Pattern.quote("removed ") + "(" + Pattern.quote(String.format("%s, %s", user.fullName(), user2.fullName())) + "|" + Pattern.quote(String.format("%s, %s", user2.fullName(), user.fullName())) + ")");
assertThat(message.htmlBody()).containsMatch(Pattern.quote("removed ") + "(" + Pattern.quote(String.format("%s and %s", user.fullName(), user2.fullName())) + "|" + Pattern.quote(String.format("%s and %s", user2.fullName(), user.fullName())) + ")");
// Ensure that events have been sent:
// * 1 batch event for adding user3 and user4 as reviewers
// * 2 events for removing user and user2 as reviewers (one event per removed reviewer, batch
// event not available for reviewer removal)
assertThat(testReviewerAddedListener.receivedEvents).hasSize(1);
assertThat(testReviewerAddedListener.getReviewerIds()).containsExactly(user3.id(), user4.id());
assertThat(testReviewerDeletedListener.receivedEvents).hasSize(2);
assertThat(testReviewerDeletedListener.getReviewerIds()).containsExactly(user.id(), user2.id());
}
use of com.google.gerrit.extensions.api.changes.ReviewResult in project gerrit by GerritCodeReview.
the class ChangeReviewersIT method removingReviewerRemovesTheirVote.
@Test
public void removingReviewerRemovesTheirVote() throws Exception {
String crLabel = LabelId.CODE_REVIEW;
PushOneCommit.Result r = createChange();
ReviewInput input = ReviewInput.approve().reviewer(admin.email());
ReviewResult addResult = review(r.getChangeId(), r.getCommit().name(), input);
assertThat(addResult.reviewers).isNotNull();
assertThat(addResult.reviewers).hasSize(1);
Map<String, LabelInfo> changeLabels = getChangeLabels(r.getChangeId());
assertThat(changeLabels.get(crLabel).all).hasSize(1);
RestResponse deleteResult = deleteReviewer(r.getChangeId(), admin);
deleteResult.assertNoContent();
changeLabels = getChangeLabels(r.getChangeId());
assertThat(changeLabels.get(crLabel).all).isNull();
// Check that the vote is gone even after the reviewer is added back
addReviewer(r.getChangeId(), admin.email());
changeLabels = getChangeLabels(r.getChangeId());
assertThat(changeLabels.get(crLabel).all).isNull();
}
use of com.google.gerrit.extensions.api.changes.ReviewResult in project gerrit by GerritCodeReview.
the class ChangeIT method pendingReviewers.
@Test
public void pendingReviewers() throws Exception {
ConfigInput conf = new ConfigInput();
conf.enableReviewerByEmail = InheritableBoolean.TRUE;
gApi.projects().name(project.get()).config(conf);
PushOneCommit.Result r = createWorkInProgressChange();
String changeId = r.getChangeId();
assertThat(gApi.changes().id(changeId).get().pendingReviewers).isEmpty();
// Add some pending reviewers.
String email1 = name("user1") + "@example.com";
String email2 = name("user2") + "@example.com";
String email3 = name("user3") + "@example.com";
String email4 = name("user4") + "@example.com";
accountOperations.newAccount().username(name("user1")).preferredEmail(email1).fullname("User1").create();
accountOperations.newAccount().username(name("user2")).preferredEmail(email2).fullname("User2").create();
accountOperations.newAccount().username(name("user3")).preferredEmail(email3).fullname("User3").create();
accountOperations.newAccount().username(name("user4")).preferredEmail(email4).fullname("User4").create();
ReviewInput in = ReviewInput.noScore().reviewer(email1).reviewer(email2).reviewer(email3, CC, false).reviewer(email4, CC, false).reviewer("byemail1@example.com").reviewer("byemail2@example.com").reviewer("byemail3@example.com", CC, false).reviewer("byemail4@example.com", CC, false);
ReviewResult result = gApi.changes().id(changeId).current().review(in);
assertThat(result.reviewers).isNotEmpty();
ChangeInfo info = gApi.changes().id(changeId).get();
Function<Collection<AccountInfo>, Collection<String>> toEmails = ais -> ais.stream().map(ai -> ai.email).collect(toSet());
assertThat(toEmails.apply(info.pendingReviewers.get(REVIEWER))).containsExactly(email1, email2, "byemail1@example.com", "byemail2@example.com");
assertThat(toEmails.apply(info.pendingReviewers.get(CC))).containsExactly(email3, email4, "byemail3@example.com", "byemail4@example.com");
assertThat(info.pendingReviewers.get(REMOVED)).isNull();
// Stage some pending reviewer removals.
gApi.changes().id(changeId).reviewer(email1).remove();
gApi.changes().id(changeId).reviewer(email3).remove();
gApi.changes().id(changeId).reviewer("byemail1@example.com").remove();
gApi.changes().id(changeId).reviewer("byemail3@example.com").remove();
info = gApi.changes().id(changeId).get();
assertThat(toEmails.apply(info.pendingReviewers.get(REVIEWER))).containsExactly(email2, "byemail2@example.com");
assertThat(toEmails.apply(info.pendingReviewers.get(CC))).containsExactly(email4, "byemail4@example.com");
assertThat(toEmails.apply(info.pendingReviewers.get(REMOVED))).containsExactly(email1, email3, "byemail1@example.com", "byemail3@example.com");
// "Undo" a removal.
in = ReviewInput.noScore().reviewer(email1);
gApi.changes().id(changeId).current().review(in);
info = gApi.changes().id(changeId).get();
assertThat(toEmails.apply(info.pendingReviewers.get(REVIEWER))).containsExactly(email1, email2, "byemail2@example.com");
assertThat(toEmails.apply(info.pendingReviewers.get(CC))).containsExactly(email4, "byemail4@example.com");
assertThat(toEmails.apply(info.pendingReviewers.get(REMOVED))).containsExactly(email3, "byemail1@example.com", "byemail3@example.com");
// "Commit" by moving out of WIP.
gApi.changes().id(changeId).setReadyForReview();
info = gApi.changes().id(changeId).get();
assertThat(info.pendingReviewers).isEmpty();
assertThat(toEmails.apply(info.reviewers.get(REVIEWER))).containsExactly(email1, email2, "byemail2@example.com");
assertThat(toEmails.apply(info.reviewers.get(CC))).containsExactly(email4, "byemail4@example.com");
assertThat(info.reviewers.get(REMOVED)).isNull();
}
use of com.google.gerrit.extensions.api.changes.ReviewResult in project gerrit by GerritCodeReview.
the class ChangeIT method deleteGroupFromReviewersFails.
@Test
public void deleteGroupFromReviewersFails() throws Exception {
PushOneCommit.Result r = createChange();
// create a group named "kobe" with one user: lee
String myGroupUserEmail = "lee@example.com";
String myGroupUserFullname = "lee";
accountOperations.newAccount().username("lee").preferredEmail(myGroupUserEmail).fullname(myGroupUserFullname).create();
String groupName = "kobe";
String testGroup = groupOperations.newGroup().name(groupName).create().get();
GroupApi groupApi = gApi.groups().id(testGroup);
groupApi.description("test group");
groupApi.addMembers(myGroupUserFullname);
// add the user as reviewer.
gApi.changes().id(r.getChangeId()).addReviewer(myGroupUserFullname);
// fail to remove that user via group.
ReviewResult reviewResult = gApi.changes().id(r.getChangeId()).current().review(ReviewInput.create().reviewer(testGroup, REMOVED, /* confirmed= */
true));
assertThat(reviewResult.error).isEqualTo("error adding reviewer");
ReviewerInput in = new ReviewerInput();
in.reviewer = testGroup;
in.state = REMOVED;
ReviewerResult reviewerResult = gApi.changes().id(r.getChangeId()).addReviewer(in);
assertThat(reviewerResult.error).isEqualTo(MessageFormat.format(ChangeMessages.get().groupRemovalIsNotAllowed, groupName));
}
Aggregations