use of com.google.gerrit.entities.PatchSetApproval in project gerrit by GerritCodeReview.
the class LabelsJson method setAllApprovals.
private void setAllApprovals(AccountLoader accountLoader, ChangeData cd, Map<String, LabelWithStatus> labels, boolean detailed) throws PermissionBackendException {
checkState(!cd.change().isMerged(), "should not call setAllApprovals on %s change", ChangeUtil.status(cd.change()));
// Include a user in the output for this label if either:
// - They are an explicit reviewer.
// - They ever voted on this change.
Set<Account.Id> allUsers = new HashSet<>();
allUsers.addAll(cd.reviewers().byState(ReviewerStateInternal.REVIEWER));
for (PatchSetApproval psa : cd.approvals().values()) {
allUsers.add(psa.accountId());
}
Table<Account.Id, String, PatchSetApproval> current = HashBasedTable.create(allUsers.size(), cd.getLabelTypes().getLabelTypes().size());
for (PatchSetApproval psa : cd.currentApprovals()) {
current.put(psa.accountId(), psa.label(), psa);
}
LabelTypes labelTypes = cd.getLabelTypes();
for (Account.Id accountId : allUsers) {
Map<String, VotingRangeInfo> pvr = null;
PermissionBackend.ForChange perm = null;
if (detailed) {
perm = permissionBackend.absentUser(accountId).change(cd);
pvr = getPermittedVotingRanges(permittedLabels(accountId, cd));
}
for (Map.Entry<String, LabelWithStatus> e : labels.entrySet()) {
Optional<LabelType> lt = labelTypes.byLabel(e.getKey());
if (!lt.isPresent()) {
// author didn't intend for the label to show up in the table.
continue;
}
Integer value;
VotingRangeInfo permittedVotingRange = pvr == null ? null : pvr.getOrDefault(lt.get().getName(), null);
String tag = null;
Instant date = null;
PatchSetApproval psa = current.get(accountId, lt.get().getName());
if (psa != null) {
value = Integer.valueOf(psa.value());
if (value == 0) {
// This may be a dummy approval that was inserted when the reviewer
// was added. Explicitly check whether the user can vote on this
// label.
value = perm != null && perm.test(new LabelPermission(lt.get())) ? 0 : null;
}
tag = psa.tag().orElse(null);
date = psa.granted();
if (psa.postSubmit()) {
logger.atWarning().log("unexpected post-submit approval on open change: %s", psa);
}
} else {
// Either the user cannot vote on this label, or they were added as a
// reviewer but have not responded yet. Explicitly check whether the
// user can vote on this label.
value = perm != null && perm.test(new LabelPermission(lt.get())) ? 0 : null;
}
addApproval(e.getValue().label(), approvalInfo(accountLoader, accountId, value, permittedVotingRange, tag, date));
}
}
}
use of com.google.gerrit.entities.PatchSetApproval in project gerrit by GerritCodeReview.
the class LabelsJson method labelsForSubmittedChange.
private Map<String, LabelWithStatus> labelsForSubmittedChange(AccountLoader accountLoader, ChangeData cd, LabelTypes labelTypes, boolean standard, boolean detailed) throws PermissionBackendException {
Set<Account.Id> allUsers = new HashSet<>();
if (detailed) {
// the latest patch set (in the next loop).
for (PatchSetApproval psa : cd.approvals().values()) {
allUsers.add(psa.accountId());
}
}
Set<String> labelNames = new HashSet<>();
SetMultimap<Account.Id, PatchSetApproval> current = MultimapBuilder.hashKeys().hashSetValues().build();
for (PatchSetApproval a : cd.currentApprovals()) {
allUsers.add(a.accountId());
Optional<LabelType> type = labelTypes.byLabel(a.labelId());
if (type.isPresent()) {
labelNames.add(type.get().getName());
// Not worth the effort to distinguish between votable/non-votable for 0
// values on closed changes, since they can't vote anyway.
current.put(a.accountId(), a);
}
}
// Since voting on merged changes is allowed all labels which apply to
// the change must be returned. All applying labels can be retrieved from
// the submit records, which is what initLabels does.
// It's not possible to only compute the labels based on the approvals
// since merged changes may not have approvals for all labels (e.g. if not
// all labels are required for submit or if the change was auto-closed due
// to direct push or if new labels were defined after the change was
// merged).
Map<String, LabelWithStatus> labels;
labels = initLabels(accountLoader, cd, labelTypes, standard);
// it wouldn't be included in the submit records.
for (String name : labelNames) {
if (!labels.containsKey(name)) {
labels.put(name, LabelWithStatus.create(new LabelInfo(), null));
}
}
labels.entrySet().stream().filter(e -> labelTypes.byLabel(e.getKey()).isPresent()).forEach(e -> setLabelValues(labelTypes.byLabel(e.getKey()).get(), e.getValue()));
for (Account.Id accountId : allUsers) {
Map<String, ApprovalInfo> byLabel = Maps.newHashMapWithExpectedSize(labels.size());
Map<String, VotingRangeInfo> pvr = Collections.emptyMap();
if (detailed) {
pvr = getPermittedVotingRanges(permittedLabels(accountId, cd));
}
for (Map.Entry<String, LabelWithStatus> entry : labels.entrySet()) {
ApprovalInfo ai = approvalInfo(accountLoader, accountId, 0, null, null, null);
byLabel.put(entry.getKey(), ai);
addApproval(entry.getValue().label(), ai);
}
for (PatchSetApproval psa : current.get(accountId)) {
Optional<LabelType> type = labelTypes.byLabel(psa.labelId());
if (!type.isPresent()) {
continue;
}
short val = psa.value();
ApprovalInfo info = byLabel.get(type.get().getName());
if (info != null) {
info.value = Integer.valueOf(val);
info.permittedVotingRange = pvr.getOrDefault(type.get().getName(), null);
info.setDate(psa.granted());
info.tag = psa.tag().orElse(null);
if (psa.postSubmit()) {
info.postSubmit = true;
}
}
if (!standard) {
continue;
}
setLabelScores(accountLoader, type.get(), labels.get(type.get().getName()), val, accountId);
}
}
return labels;
}
use of com.google.gerrit.entities.PatchSetApproval in project gerrit by GerritCodeReview.
the class LabelsJson method labelsForUnsubmittedChange.
private Map<String, LabelWithStatus> labelsForUnsubmittedChange(AccountLoader accountLoader, ChangeData cd, LabelTypes labelTypes, boolean standard, boolean detailed) throws PermissionBackendException {
Map<String, LabelWithStatus> labels = initLabels(accountLoader, cd, labelTypes, standard);
setAllApprovals(accountLoader, cd, labels, detailed);
for (Map.Entry<String, LabelWithStatus> e : labels.entrySet()) {
Optional<LabelType> type = labelTypes.byLabel(e.getKey());
if (!type.isPresent()) {
continue;
}
if (standard) {
for (PatchSetApproval psa : cd.currentApprovals()) {
if (type.get().matches(psa)) {
short val = psa.value();
Account.Id accountId = psa.accountId();
setLabelScores(accountLoader, type.get(), e.getValue(), val, accountId);
}
}
}
setLabelValues(type.get(), e.getValue());
}
return labels;
}
use of com.google.gerrit.entities.PatchSetApproval in project gerrit by GerritCodeReview.
the class ChangeInserter method postUpdate.
@Override
public void postUpdate(PostUpdateContext ctx) throws Exception {
reviewerAdditions.postUpdate(ctx);
NotifyResolver.Result notify = ctx.getNotify(change.getId());
if (sendMail && notify.shouldNotify()) {
Runnable sender = new Runnable() {
@Override
public void run() {
try {
CreateChangeSender emailSender = createChangeSenderFactory.create(change.getProject(), change.getId());
emailSender.setFrom(change.getOwner());
emailSender.setPatchSet(patchSet, patchSetInfo);
emailSender.setNotify(notify);
emailSender.addReviewers(reviewerAdditions.flattenResults(ReviewerOp.Result::addedReviewers).stream().map(PatchSetApproval::accountId).collect(toImmutableSet()));
emailSender.addReviewersByEmail(reviewerAdditions.flattenResults(ReviewerOp.Result::addedReviewersByEmail));
emailSender.addExtraCC(reviewerAdditions.flattenResults(ReviewerOp.Result::addedCCs));
emailSender.addExtraCCByEmail(reviewerAdditions.flattenResults(ReviewerOp.Result::addedCCsByEmail));
emailSender.setMessageId(messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
emailSender.send();
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot send email for new change %s", change.getId());
}
}
@Override
public String toString() {
return "send-email newchange";
}
};
if (requestScopePropagator != null) {
@SuppressWarnings("unused") Future<?> possiblyIgnoredError = sendEmailExecutor.submit(requestScopePropagator.wrap(sender));
} else {
sender.run();
}
}
/* For labels that are not set in this operation, show the "current" value
* of 0, and no oldValue as the value was not modified by this operation.
* For labels that are set in this operation, the value was modified, so
* show a transition from an oldValue of 0 to the new value.
*/
if (fireRevisionCreated) {
revisionCreated.fire(ctx.getChangeData(change), patchSet, ctx.getAccount(), ctx.getWhen(), notify);
if (approvals != null && !approvals.isEmpty()) {
List<LabelType> labels = projectState.getLabelTypes(change.getDest()).getLabelTypes();
Map<String, Short> allApprovals = new HashMap<>();
Map<String, Short> oldApprovals = new HashMap<>();
for (LabelType lt : labels) {
allApprovals.put(lt.getName(), (short) 0);
oldApprovals.put(lt.getName(), null);
}
for (Map.Entry<String, Short> entry : approvals.entrySet()) {
if (entry.getValue() != 0) {
allApprovals.put(entry.getKey(), entry.getValue());
oldApprovals.put(entry.getKey(), (short) 0);
}
}
commentAdded.fire(ctx.getChangeData(change), patchSet, ctx.getAccount(), null, allApprovals, oldApprovals, ctx.getWhen());
}
}
}
use of com.google.gerrit.entities.PatchSetApproval in project gerrit by GerritCodeReview.
the class DeleteReviewerOp method updateChange.
@Override
public boolean updateChange(ChangeContext ctx) throws AuthException, ResourceNotFoundException, PermissionBackendException, IOException {
Account.Id reviewerId = reviewer.id();
// Check of removing this reviewer (even if there is no vote processed by the loop below) is OK
removeReviewerControl.checkRemoveReviewer(ctx.getNotes(), ctx.getUser(), reviewerId);
if (!approvalsUtil.getReviewers(ctx.getNotes()).all().contains(reviewerId)) {
throw new ResourceNotFoundException(String.format("Reviewer %s doesn't exist in the change, hence can't delete it", reviewer.getName()));
}
currChange = ctx.getChange();
setPatchSet(psUtil.current(ctx.getNotes()));
LabelTypes labelTypes = projectCache.get(ctx.getProject()).orElseThrow(illegalState(ctx.getProject())).getLabelTypes(ctx.getNotes());
// removing a reviewer will remove all her votes
for (LabelType lt : labelTypes.getLabelTypes()) {
newApprovals.put(lt.getName(), (short) 0);
}
String ccOrReviewer = approvalsUtil.getReviewers(ctx.getNotes()).byState(ReviewerStateInternal.CC).contains(reviewerId) ? "cc" : "reviewer";
StringBuilder msg = new StringBuilder();
msg.append(String.format("Removed %s %s", ccOrReviewer, AccountTemplateUtil.getAccountTemplate(reviewer.id())));
StringBuilder removedVotesMsg = new StringBuilder();
removedVotesMsg.append(" with the following votes:\n\n");
boolean votesRemoved = false;
for (PatchSetApproval a : approvals(ctx, reviewerId)) {
// Check if removing this vote is OK
removeReviewerControl.checkRemoveReviewer(ctx.getNotes(), ctx.getUser(), a);
if (a.patchSetId().equals(patchSet.id()) && a.value() != 0) {
oldApprovals.put(a.label(), a.value());
removedVotesMsg.append("* ").append(a.label()).append(formatLabelValue(a.value())).append(" by ").append(AccountTemplateUtil.getAccountTemplate(a.accountId())).append("\n");
votesRemoved = true;
}
}
if (votesRemoved) {
msg.append(removedVotesMsg);
} else {
msg.append(".");
}
ChangeUpdate update = ctx.getUpdate(patchSet.id());
update.removeReviewer(reviewerId);
mailMessage = cmUtil.setChangeMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_DELETE_REVIEWER);
return true;
}
Aggregations