Search in sources :

Example 1 with SubmitRequirement

use of com.google.gerrit.entities.SubmitRequirement in project gerrit by GerritCodeReview.

the class SubmitRequirementsAdapter method getLegacyRequirements.

/**
 * Retrieve legacy submit records (created by label functions and other {@link
 * com.google.gerrit.server.rules.SubmitRule}s) and convert them to submit requirement results.
 */
public static Map<SubmitRequirement, SubmitRequirementResult> getLegacyRequirements(ChangeData cd) {
    // We use SubmitRuleOptions.defaults() which does not recompute submit rules for closed changes.
    // This doesn't have an effect since we never call this class (i.e. to evaluate submit
    // requirements) for closed changes.
    List<SubmitRecord> records = cd.submitRecords(SubmitRuleOptions.defaults());
    boolean areForced = records.stream().anyMatch(record -> SubmitRecord.Status.FORCED.equals(record.status));
    List<LabelType> labelTypes = cd.getLabelTypes().getLabelTypes();
    ObjectId commitId = cd.currentPatchSet().commitId();
    Map<String, List<SubmitRequirementResult>> srsByName = records.stream().filter(r -> !SubmitRecord.Status.FORCED.equals(r.status)).map(r -> createResult(r, labelTypes, commitId, areForced)).flatMap(List::stream).collect(Collectors.groupingBy(sr -> sr.submitRequirement().name()));
    // We convert submit records to submit requirements by generating a separate
    // submit requirement result for each available label in each submit record.
    // The SR status is derived from the label status of the submit record.
    // This conversion might result in duplicate entries.
    // One such example can be a prolog rule emitting the same label name twice.
    // Another case might happen if two different submit rules emit the same label
    // name. In such cases, we need to merge these entries and return a single submit
    // requirement result. If both entries agree in their status, return any of them.
    // Otherwise, favour the entry that is blocking submission.
    ImmutableMap.Builder<SubmitRequirement, SubmitRequirementResult> result = ImmutableMap.builder();
    for (Map.Entry<String, List<SubmitRequirementResult>> entry : srsByName.entrySet()) {
        if (entry.getValue().size() == 1) {
            SubmitRequirementResult srResult = entry.getValue().iterator().next();
            result.put(srResult.submitRequirement(), srResult);
            continue;
        }
        // If all submit requirements with the same name match in status, return the first one.
        List<SubmitRequirementResult> resultsSameName = entry.getValue();
        boolean allNonBlocking = resultsSameName.stream().allMatch(sr -> sr.fulfilled());
        if (allNonBlocking) {
            result.put(resultsSameName.get(0).submitRequirement(), resultsSameName.get(0));
        } else {
            // Otherwise, return the first submit requirement result that is blocking submission.
            Optional<SubmitRequirementResult> nonFulfilled = resultsSameName.stream().filter(sr -> !sr.fulfilled()).findFirst();
            if (nonFulfilled.isPresent()) {
                result.put(nonFulfilled.get().submitRequirement(), nonFulfilled.get());
            }
        }
    }
    return result.build();
}
Also used : ImmutableMap(com.google.common.collect.ImmutableMap) SubmitRequirementExpression(com.google.gerrit.entities.SubmitRequirementExpression) SubmitRecord(com.google.gerrit.entities.SubmitRecord) DefaultSubmitRule(com.google.gerrit.server.rules.DefaultSubmitRule) Collectors(java.util.stream.Collectors) ObjectId(org.eclipse.jgit.lib.ObjectId) SubmitRequirementExpressionResult(com.google.gerrit.entities.SubmitRequirementExpressionResult) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult) Strings(com.google.common.base.Strings) ChangeData(com.google.gerrit.server.query.change.ChangeData) List(java.util.List) Label(com.google.gerrit.entities.SubmitRecord.Label) ImmutableList(com.google.common.collect.ImmutableList) LabelType(com.google.gerrit.entities.LabelType) ChangeQueryBuilder(com.google.gerrit.server.query.change.ChangeQueryBuilder) Map(java.util.Map) Optional(java.util.Optional) FluentLogger(com.google.common.flogger.FluentLogger) Status(com.google.gerrit.entities.SubmitRequirementExpressionResult.Status) SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) ObjectId(org.eclipse.jgit.lib.ObjectId) ImmutableMap(com.google.common.collect.ImmutableMap) SubmitRecord(com.google.gerrit.entities.SubmitRecord) SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) LabelType(com.google.gerrit.entities.LabelType) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult) ImmutableMap(com.google.common.collect.ImmutableMap) Map(java.util.Map)

Example 2 with SubmitRequirement

use of com.google.gerrit.entities.SubmitRequirement in project gerrit by GerritCodeReview.

the class SubmitRequirementsAdapter method createFromDefaultSubmitRecord.

private static List<SubmitRequirementResult> createFromDefaultSubmitRecord(List<Label> labels, List<LabelType> labelTypes, ObjectId psCommitId, boolean isForced) {
    ImmutableList.Builder<SubmitRequirementResult> result = ImmutableList.builder();
    for (Label label : labels) {
        if (skipSubmitRequirementFor(label)) {
            continue;
        }
        Optional<LabelType> maybeLabelType = getLabelType(labelTypes, label.label);
        if (!maybeLabelType.isPresent()) {
            // if it was blocking or not, hence we skip the label.
            continue;
        }
        LabelType labelType = maybeLabelType.get();
        if (!isBlocking(labelType)) {
            continue;
        }
        ImmutableList<String> atoms = toExpressionAtomList(labelType);
        SubmitRequirement.Builder req = SubmitRequirement.builder().setName(label.label).setSubmittabilityExpression(toExpression(atoms)).setAllowOverrideInChildProjects(labelType.isCanOverride());
        result.add(SubmitRequirementResult.builder().legacy(Optional.of(true)).submitRequirement(req.build()).submittabilityExpressionResult(createExpressionResult(toExpression(atoms), mapStatus(label), atoms)).patchSetCommitId(psCommitId).forced(Optional.of(isForced)).build());
    }
    return result.build();
}
Also used : SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) ImmutableList(com.google.common.collect.ImmutableList) LabelType(com.google.gerrit.entities.LabelType) Label(com.google.gerrit.entities.SubmitRecord.Label) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult)

Example 3 with SubmitRequirement

use of com.google.gerrit.entities.SubmitRequirement in project gerrit by GerritCodeReview.

the class SubmitRequirementsAdapter method createFromCustomSubmitRecord.

private static List<SubmitRequirementResult> createFromCustomSubmitRecord(SubmitRecord record, ObjectId psCommitId, boolean isForced) {
    String ruleName = record.ruleName != null ? record.ruleName : "Custom-Rule";
    if (record.labels == null || record.labels.isEmpty()) {
        SubmitRequirement sr = SubmitRequirement.builder().setName(ruleName).setSubmittabilityExpression(SubmitRequirementExpression.create(String.format("rule:%s", ruleName))).setAllowOverrideInChildProjects(false).build();
        return ImmutableList.of(SubmitRequirementResult.builder().legacy(Optional.of(true)).submitRequirement(sr).submittabilityExpressionResult(createExpressionResult(sr.submittabilityExpression(), mapStatus(record), ImmutableList.of(ruleName), record.errorMessage)).patchSetCommitId(psCommitId).forced(Optional.of(isForced)).build());
    }
    ImmutableList.Builder<SubmitRequirementResult> result = ImmutableList.builder();
    for (Label label : record.labels) {
        if (skipSubmitRequirementFor(label)) {
            continue;
        }
        String expressionString = String.format("label:%s=%s", label.label, ruleName);
        SubmitRequirement sr = SubmitRequirement.builder().setName(label.label).setSubmittabilityExpression(SubmitRequirementExpression.create(expressionString)).setAllowOverrideInChildProjects(false).build();
        result.add(SubmitRequirementResult.builder().legacy(Optional.of(true)).submitRequirement(sr).submittabilityExpressionResult(createExpressionResult(sr.submittabilityExpression(), mapStatus(label), ImmutableList.of(expressionString))).patchSetCommitId(psCommitId).build());
    }
    return result.build();
}
Also used : SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) ImmutableList(com.google.common.collect.ImmutableList) Label(com.google.gerrit.entities.SubmitRecord.Label) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult)

Example 4 with SubmitRequirement

use of com.google.gerrit.entities.SubmitRequirement in project gerrit by GerritCodeReview.

the class MergeOp method bypassSubmitRulesAndRequirements.

private void bypassSubmitRulesAndRequirements(ChangeSet cs) {
    checkArgument(!cs.furtherHiddenChanges(), "cannot bypass submit rules for topic with hidden change");
    for (ChangeData cd : cs.changes()) {
        Change change = cd.change();
        if (change == null) {
            throw new StorageException("Change not found");
        }
        if (change.isClosed()) {
            // No need to check submit rules if the change is closed.
            continue;
        }
        List<SubmitRecord> records = new ArrayList<>(getSubmitRecords(cd));
        SubmitRecord forced = new SubmitRecord();
        forced.status = SubmitRecord.Status.FORCED;
        records.add(forced);
        cd.setSubmitRecords(submitRuleOptions(/* allowClosed= */
        false), records);
        // Also bypass submit requirements. Mark them as forced.
        Map<SubmitRequirement, SubmitRequirementResult> forcedSRs = cd.submitRequirementsIncludingLegacy().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().toBuilder().forced(Optional.of(true)).build()));
        cd.setSubmitRequirements(forcedSRs);
    }
}
Also used : ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) SuperprojectUpdateOnSubmission(com.google.gerrit.server.update.SuperprojectUpdateOnSubmission) ListMultimap(com.google.common.collect.ListMultimap) MultimapBuilder(com.google.common.collect.MultimapBuilder) InternalUser(com.google.gerrit.server.InternalUser) Inject(com.google.inject.Inject) SubmissionId(com.google.gerrit.entities.SubmissionId) UpdateException(com.google.gerrit.server.update.UpdateException) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult) MergeUpdateException(com.google.gerrit.exceptions.MergeUpdateException) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) SubmitInput(com.google.gerrit.extensions.api.changes.SubmitInput) Map(java.util.Map) AuthException(com.google.gerrit.extensions.restapi.AuthException) StoreSubmitRequirementsOp(com.google.gerrit.server.notedb.StoreSubmitRequirementsOp) RetryHelper(com.google.gerrit.server.update.RetryHelper) MergeTip(com.google.gerrit.server.git.MergeTip) Collectors.toSet(java.util.stream.Collectors.toSet) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) Status(com.google.gerrit.entities.Change.Status) ImmutableMap(com.google.common.collect.ImmutableMap) TraceContext(com.google.gerrit.server.logging.TraceContext) SubmitType(com.google.gerrit.extensions.client.SubmitType) Collection(java.util.Collection) Set(java.util.Set) Constants(org.eclipse.jgit.lib.Constants) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) Instant(java.time.Instant) RetryListener(com.github.rholder.retry.RetryListener) SubmitRecord(com.google.gerrit.entities.SubmitRecord) Collectors(java.util.stream.Collectors) BranchNameKey(com.google.gerrit.entities.BranchNameKey) NotifyHandling(com.google.gerrit.extensions.api.changes.NotifyHandling) SubmitTypeRecord(com.google.gerrit.entities.SubmitTypeRecord) ChangeData(com.google.gerrit.server.query.change.ChangeData) List(java.util.List) Nullable(com.google.gerrit.common.Nullable) Ref(org.eclipse.jgit.lib.Ref) AutoValue(com.google.auto.value.AutoValue) InternalChangeQuery(com.google.gerrit.server.query.change.InternalChangeQuery) Optional(java.util.Optional) MoreObjects.firstNonNull(com.google.common.base.MoreObjects.firstNonNull) Counter0(com.google.gerrit.metrics.Counter0) MetricMaker(com.google.gerrit.metrics.MetricMaker) BatchUpdateOp(com.google.gerrit.server.update.BatchUpdateOp) FluentLogger(com.google.common.flogger.FluentLogger) Joiner(com.google.common.base.Joiner) ChangeMessagesUtil(com.google.gerrit.server.ChangeMessagesUtil) Singleton(com.google.inject.Singleton) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) HashMap(java.util.HashMap) Function(java.util.function.Function) SubmissionListener(com.google.gerrit.server.update.SubmissionListener) MergeValidators(com.google.gerrit.server.git.validators.MergeValidators) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ImmutableList(com.google.common.collect.ImmutableList) SubmissionExecutor(com.google.gerrit.server.update.SubmissionExecutor) Description(com.google.gerrit.metrics.Description) Objects.requireNonNull(java.util.Objects.requireNonNull) Change(com.google.gerrit.entities.Change) PatchSet(com.google.gerrit.entities.PatchSet) Comparator.comparing(java.util.Comparator.comparing) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) ChangeUtil(com.google.gerrit.server.ChangeUtil) LockFailureException(com.google.gerrit.git.LockFailureException) ChangeContext(com.google.gerrit.server.update.ChangeContext) MergeValidationException(com.google.gerrit.server.git.validators.MergeValidationException) LinkedHashSet(java.util.LinkedHashSet) SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) NotifyResolver(com.google.gerrit.server.change.NotifyResolver) OpenBranch(com.google.gerrit.server.submit.MergeOpRepoManager.OpenBranch) StorageException(com.google.gerrit.exceptions.StorageException) Attempt(com.github.rholder.retry.Attempt) NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) SubmitRuleOptions(com.google.gerrit.server.project.SubmitRuleOptions) SetMultimap(com.google.common.collect.SetMultimap) ObjectId(org.eclipse.jgit.lib.ObjectId) Provider(com.google.inject.Provider) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) Project(com.google.gerrit.entities.Project) TimeUtil(com.google.gerrit.server.util.time.TimeUtil) RequestId(com.google.gerrit.server.logging.RequestId) SubmitRecord(com.google.gerrit.entities.SubmitRecord) SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) ArrayList(java.util.ArrayList) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult) Change(com.google.gerrit.entities.Change) ChangeData(com.google.gerrit.server.query.change.ChangeData) StorageException(com.google.gerrit.exceptions.StorageException) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap)

Example 5 with SubmitRequirement

use of com.google.gerrit.entities.SubmitRequirement in project gerrit by GerritCodeReview.

the class MergeOp method checkSubmitRequirements.

public static void checkSubmitRequirements(ChangeData cd) throws ResourceConflictException {
    PatchSet patchSet = cd.currentPatchSet();
    if (patchSet == null) {
        throw new ResourceConflictException("missing current patch set for change " + cd.getId());
    }
    Map<SubmitRequirement, SubmitRequirementResult> srResults = cd.submitRequirementsIncludingLegacy();
    if (srResults.values().stream().allMatch(SubmitRequirementResult::fulfilled)) {
        return;
    } else if (srResults.isEmpty()) {
        throw new IllegalStateException(String.format("Submit requirement results for change '%s' and patchset '%s' " + "are empty in project '%s'", cd.getId(), patchSet.id(), cd.change().getProject().get()));
    }
    for (SubmitRequirementResult srResult : srResults.values()) {
        switch(srResult.status()) {
            case SATISFIED:
            case NOT_APPLICABLE:
            case OVERRIDDEN:
            case FORCED:
                break;
            case ERROR:
                throw new ResourceConflictException(String.format("submit requirement '%s' has an error: %s", srResult.submitRequirement().name(), srResult.errorMessage().orElse("")));
            case UNSATISFIED:
                throw new ResourceConflictException(String.format("submit requirement '%s' is unsatisfied.", srResult.submitRequirement().name()));
            default:
                throw new IllegalStateException(String.format("Unexpected submit requirement status %s for %s in %s", srResult.status().name(), patchSet.id().getId(), cd.change().getProject().get()));
        }
    }
    throw new IllegalStateException();
}
Also used : SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) PatchSet(com.google.gerrit.entities.PatchSet) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult)

Aggregations

SubmitRequirement (com.google.gerrit.entities.SubmitRequirement)39 SubmitRequirementResult (com.google.gerrit.entities.SubmitRequirementResult)27 Test (org.junit.Test)24 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)20 Registration (com.google.gerrit.acceptance.ExtensionRegistry.Registration)8 PushOneCommit (com.google.gerrit.acceptance.PushOneCommit)6 ChangeInfo (com.google.gerrit.extensions.common.ChangeInfo)6 LegacySubmitRequirement (com.google.gerrit.entities.LegacySubmitRequirement)5 ChangeData (com.google.gerrit.server.query.change.ChangeData)5 Map (java.util.Map)5 RevCommit (org.eclipse.jgit.revwalk.RevCommit)5 ImmutableList (com.google.common.collect.ImmutableList)4 ImmutableMap (com.google.common.collect.ImmutableMap)4 HashMap (java.util.HashMap)4 Label (com.google.gerrit.entities.SubmitRecord.Label)3 LinkedHashMap (java.util.LinkedHashMap)3 Optional (java.util.Optional)3 FluentLogger (com.google.common.flogger.FluentLogger)2 LabelType (com.google.gerrit.entities.LabelType)2 PatchSet (com.google.gerrit.entities.PatchSet)2