Search in sources :

Example 46 with PatchSetApproval

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));
        }
    }
}
Also used : Account(com.google.gerrit.entities.Account) LabelTypes(com.google.gerrit.entities.LabelTypes) PermissionBackend(com.google.gerrit.server.permissions.PermissionBackend) Instant(java.time.Instant) VotingRangeInfo(com.google.gerrit.extensions.common.VotingRangeInfo) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval) LabelType(com.google.gerrit.entities.LabelType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) TreeMap(java.util.TreeMap) LabelPermission(com.google.gerrit.server.permissions.LabelPermission) HashSet(java.util.HashSet)

Example 47 with PatchSetApproval

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;
}
Also used : Iterables(com.google.common.collect.Iterables) AccountLoader(com.google.gerrit.server.account.AccountLoader) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) LabelInfo(com.google.gerrit.extensions.common.LabelInfo) MultimapBuilder(com.google.common.collect.MultimapBuilder) Inject(com.google.inject.Inject) HashBasedTable(com.google.common.collect.HashBasedTable) HashMap(java.util.HashMap) PermissionBackend(com.google.gerrit.server.permissions.PermissionBackend) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval) LabelTypes(com.google.gerrit.entities.LabelTypes) Lists(com.google.common.collect.Lists) LabelValue(com.google.gerrit.entities.LabelValue) LabelType(com.google.gerrit.entities.LabelType) Map(java.util.Map) ChangeUtil(com.google.gerrit.server.ChangeUtil) LinkedHashMultimap(com.google.common.collect.LinkedHashMultimap) ApprovalInfo(com.google.gerrit.extensions.common.ApprovalInfo) ImmutableMap(com.google.common.collect.ImmutableMap) ReviewerStateInternal(com.google.gerrit.server.notedb.ReviewerStateInternal) Collection(java.util.Collection) Account(com.google.gerrit.entities.Account) Set(java.util.Set) Instant(java.time.Instant) Maps(com.google.common.collect.Maps) Ints(com.google.common.primitives.Ints) SubmitRecord(com.google.gerrit.entities.SubmitRecord) SetMultimap(com.google.common.collect.SetMultimap) Preconditions.checkState(com.google.common.base.Preconditions.checkState) VotingRangeInfo(com.google.gerrit.extensions.common.VotingRangeInfo) Collectors.toList(java.util.stream.Collectors.toList) ChangeData(com.google.gerrit.server.query.change.ChangeData) List(java.util.List) Nullable(com.google.gerrit.common.Nullable) TreeMap(java.util.TreeMap) AutoValue(com.google.auto.value.AutoValue) Optional(java.util.Optional) Table(com.google.common.collect.Table) Collections(java.util.Collections) FluentLogger(com.google.common.flogger.FluentLogger) LabelPermission(com.google.gerrit.server.permissions.LabelPermission) Singleton(com.google.inject.Singleton) Account(com.google.gerrit.entities.Account) VotingRangeInfo(com.google.gerrit.extensions.common.VotingRangeInfo) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval) LabelInfo(com.google.gerrit.extensions.common.LabelInfo) ApprovalInfo(com.google.gerrit.extensions.common.ApprovalInfo) LabelType(com.google.gerrit.entities.LabelType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) TreeMap(java.util.TreeMap) HashSet(java.util.HashSet)

Example 48 with PatchSetApproval

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;
}
Also used : Account(com.google.gerrit.entities.Account) LabelType(com.google.gerrit.entities.LabelType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) TreeMap(java.util.TreeMap) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval)

Example 49 with PatchSetApproval

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());
        }
    }
}
Also used : HashMap(java.util.HashMap) CreateChangeSender(com.google.gerrit.server.mail.send.CreateChangeSender) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) CommitValidationException(com.google.gerrit.server.git.validators.CommitValidationException) ValidationException(com.google.gerrit.server.validators.ValidationException) IOException(java.io.IOException) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) LabelType(com.google.gerrit.entities.LabelType) Map(java.util.Map) HashMap(java.util.HashMap)

Example 50 with PatchSetApproval

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;
}
Also used : Account(com.google.gerrit.entities.Account) LabelTypes(com.google.gerrit.entities.LabelTypes) LabelType(com.google.gerrit.entities.LabelType) ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval) ChangeUpdate(com.google.gerrit.server.notedb.ChangeUpdate)

Aggregations

PatchSetApproval (com.google.gerrit.entities.PatchSetApproval)93 Test (org.junit.Test)57 Change (com.google.gerrit.entities.Change)41 LabelType (com.google.gerrit.entities.LabelType)22 Account (com.google.gerrit.entities.Account)20 PushOneCommit (com.google.gerrit.acceptance.PushOneCommit)14 Map (java.util.Map)14 ObjectId (org.eclipse.jgit.lib.ObjectId)14 LabelId (com.google.gerrit.entities.LabelId)13 PatchSet (com.google.gerrit.entities.PatchSet)12 SubmitRecord (com.google.gerrit.entities.SubmitRecord)12 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)11 ReviewInput (com.google.gerrit.extensions.api.changes.ReviewInput)10 SubmissionId (com.google.gerrit.entities.SubmissionId)9 ChangeData (com.google.gerrit.server.query.change.ChangeData)9 Inject (com.google.inject.Inject)9 Instant (java.time.Instant)9 HashMap (java.util.HashMap)9 List (java.util.List)9 ChangeMessage (com.google.gerrit.entities.ChangeMessage)8