diff --git a/Documentation/cmd-stream-events.txt b/Documentation/cmd-stream-events.txt index 8ce7d7e40f..197cac8416 100644 --- a/Documentation/cmd-stream-events.txt +++ b/Documentation/cmd-stream-events.txt @@ -281,6 +281,24 @@ oldTopic:: Topic name before it was changed. eventCreatedOn:: Time in seconds since the UNIX epoch when this event was created. +=== Vote Deleted + +Sent when a vote was removed from a change. + +type:: "vote-deleted" + +change:: link:json.html#change[change attribute] + +patchSet:: link:json.html#patchSet[patchSet attribute] + +reviewer:: user whose vote was removed as link:json.html#account[account attribute] + +remover:: user who removed the vote as link:json.html#account[account attribute] + +approvals:: all votes as link:json.html#approval[approval attributes] + +comment:: Review comment cover message. + == SEE ALSO * link:json.html[JSON Data Formats] diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/events/VoteDeletedListener.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/events/VoteDeletedListener.java index 3958a819a2..2e2a8f6d07 100644 --- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/events/VoteDeletedListener.java +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/events/VoteDeletedListener.java @@ -15,6 +15,7 @@ package com.google.gerrit.extensions.events; import com.google.gerrit.extensions.annotations.ExtensionPoint; +import com.google.gerrit.extensions.common.AccountInfo; import com.google.gerrit.extensions.common.ApprovalInfo; import java.util.Map; @@ -27,6 +28,8 @@ public interface VoteDeletedListener { Map getApprovals(); String getMessage(); + + AccountInfo getReviewer(); } void onVoteDeleted(Event event); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java index 963e7b4081..e02dee97be 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteVote.java @@ -116,7 +116,7 @@ public class DeleteVote implements RestModifyView try (BatchUpdate bu = batchUpdateFactory.create( db.get(), change.getProject(), r.getControl().getUser(), TimeUtil.nowTs())) { - bu.addOp(change.getId(), new Op(r.getReviewerUser().getAccountId(), rsrc.getLabel(), input)); + bu.addOp(change.getId(), new Op(r.getReviewerUser().getAccount(), rsrc.getLabel(), input)); bu.execute(); } @@ -124,7 +124,7 @@ public class DeleteVote implements RestModifyView } private class Op implements BatchUpdateOp { - private final Account.Id accountId; + private final Account account; private final String label; private final DeleteVoteInput input; private ChangeMessage changeMessage; @@ -133,8 +133,8 @@ public class DeleteVote implements RestModifyView private Map newApprovals = new HashMap<>(); private Map oldApprovals = new HashMap<>(); - private Op(Account.Id accountId, String label, DeleteVoteInput input) { - this.accountId = accountId; + private Op(Account account, String label, DeleteVoteInput input) { + this.account = account; this.label = label; this.input = input; } @@ -150,7 +150,8 @@ public class DeleteVote implements RestModifyView boolean found = false; LabelTypes labelTypes = ctx.getControl().getLabelTypes(); - for (PatchSetApproval a : approvalsUtil.byPatchSetUser(ctx.getDb(), ctl, psId, accountId)) { + for (PatchSetApproval a : + approvalsUtil.byPatchSetUser(ctx.getDb(), ctl, psId, account.getId())) { if (labelTypes.byLabel(a.getLabelId()) == null) { continue; // Ignore undefined labels. } else if (!a.getLabel().equals(label)) { @@ -172,13 +173,13 @@ public class DeleteVote implements RestModifyView throw new ResourceNotFoundException(); } - ctx.getUpdate(psId).removeApprovalFor(accountId, label); + ctx.getUpdate(psId).removeApprovalFor(account.getId(), label); ctx.getDb().patchSetApprovals().upsert(Collections.singleton(deletedApproval(ctx))); StringBuilder msg = new StringBuilder(); msg.append("Removed "); LabelVote.appendTo(msg, label, checkNotNull(oldApprovals.get(label))); - msg.append(" by ").append(userFactory.create(accountId).getNameEmail()).append("\n"); + msg.append(" by ").append(userFactory.create(account.getId()).getNameEmail()).append("\n"); changeMessage = ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_DELETE_VOTE); cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(psId), changeMessage); @@ -191,7 +192,7 @@ public class DeleteVote implements RestModifyView // set the real user; this preserves the calling user as the NoteDb // committer. return new PatchSetApproval( - new PatchSetApproval.Key(ps.getId(), accountId, new LabelId(label)), + new PatchSetApproval.Key(ps.getId(), account.getId(), new LabelId(label)), (short) 0, ctx.getWhen()); } @@ -219,6 +220,7 @@ public class DeleteVote implements RestModifyView voteDeleted.fire( change, ps, + account, newApprovals, oldApprovals, input.notify, diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/StreamEventsApiListener.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/StreamEventsApiListener.java index 15c1ae99c3..614bb408e7 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/events/StreamEventsApiListener.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/StreamEventsApiListener.java @@ -37,6 +37,7 @@ import com.google.gerrit.extensions.events.ReviewerAddedListener; import com.google.gerrit.extensions.events.ReviewerDeletedListener; import com.google.gerrit.extensions.events.RevisionCreatedListener; import com.google.gerrit.extensions.events.TopicEditedListener; +import com.google.gerrit.extensions.events.VoteDeletedListener; import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.reviewdb.client.Account; @@ -84,7 +85,8 @@ public class StreamEventsApiListener ReviewerAddedListener, ReviewerDeletedListener, RevisionCreatedListener, - TopicEditedListener { + TopicEditedListener, + VoteDeletedListener { private static final Logger log = LoggerFactory.getLogger(StreamEventsApiListener.class); public static class Module extends AbstractModule { @@ -104,6 +106,7 @@ public class StreamEventsApiListener DynamicSet.bind(binder(), ReviewerDeletedListener.class).to(StreamEventsApiListener.class); DynamicSet.bind(binder(), RevisionCreatedListener.class).to(StreamEventsApiListener.class); DynamicSet.bind(binder(), TopicEditedListener.class).to(StreamEventsApiListener.class); + DynamicSet.bind(binder(), VoteDeletedListener.class).to(StreamEventsApiListener.class); } } @@ -473,4 +476,24 @@ public class StreamEventsApiListener log.error("Failed to dispatch event", e); } } + + @Override + public void onVoteDeleted(VoteDeletedListener.Event ev) { + try { + ChangeNotes notes = getNotes(ev.getChange()); + Change change = notes.getChange(); + VoteDeletedEvent event = new VoteDeletedEvent(change); + + event.change = changeAttributeSupplier(change); + event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); + event.comment = ev.getMessage(); + event.reviewer = accountAttributeSupplier(ev.getReviewer()); + event.remover = accountAttributeSupplier(ev.getWho()); + event.approvals = approvalsAttributeSupplier(change, ev.getApprovals(), ev.getOldApprovals()); + + dispatcher.get().postEvent(change, event); + } catch (OrmException e) { + log.error("Failed to dispatch event", e); + } + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/VoteDeletedEvent.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/VoteDeletedEvent.java new file mode 100644 index 0000000000..87c4c055e3 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/VoteDeletedEvent.java @@ -0,0 +1,32 @@ +// Copyright (C) 2017 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.server.events; + +import com.google.common.base.Supplier; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.server.data.AccountAttribute; +import com.google.gerrit.server.data.ApprovalAttribute; + +public class VoteDeletedEvent extends PatchSetEvent { + static final String TYPE = "vote-deleted"; + public Supplier reviewer; + public Supplier remover; + public Supplier approvals; + public String comment; + + public VoteDeletedEvent(Change change) { + super(TYPE, change); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/extensions/events/VoteDeleted.java b/gerrit-server/src/main/java/com/google/gerrit/server/extensions/events/VoteDeleted.java index c4fa1002e9..71a603c7a2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/extensions/events/VoteDeleted.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/extensions/events/VoteDeleted.java @@ -49,6 +49,7 @@ public class VoteDeleted { public void fire( Change change, PatchSet ps, + Account reviewer, Map approvals, Map oldApprovals, NotifyHandling notify, @@ -63,6 +64,7 @@ public class VoteDeleted { new Event( util.changeInfo(change), util.revisionInfo(change.getProject(), ps), + util.accountInfo(reviewer), util.approvals(remover, approvals, when), util.approvals(remover, oldApprovals, when), notify, @@ -82,7 +84,7 @@ public class VoteDeleted { } private static class Event extends AbstractRevisionEvent implements VoteDeletedListener.Event { - + private final AccountInfo reviewer; private final Map approvals; private final Map oldApprovals; private final String message; @@ -90,6 +92,7 @@ public class VoteDeleted { Event( ChangeInfo change, RevisionInfo revision, + AccountInfo reviewer, Map approvals, Map oldApprovals, NotifyHandling notify, @@ -97,6 +100,7 @@ public class VoteDeleted { AccountInfo remover, Timestamp when) { super(change, revision, remover, when, notify); + this.reviewer = reviewer; this.approvals = approvals; this.oldApprovals = oldApprovals; this.message = message; @@ -116,5 +120,10 @@ public class VoteDeleted { public String getMessage() { return message; } + + @Override + public AccountInfo getReviewer() { + return reviewer; + } } }