Search in sources :

Example 1 with Status

use of com.google.gerrit.entities.Change.Status in project gerrit by GerritCodeReview.

the class MergeOp method merge.

/**
 * Merges the given change.
 *
 * <p>Depending on the server configuration, more changes may be affected, e.g. by submission of a
 * topic or via superproject subscriptions. All affected changes are integrated using the projects
 * integration strategy.
 *
 * @param change the change to be merged.
 * @param caller the identity of the caller
 * @param checkSubmitRules whether the prolog submit rules should be evaluated
 * @param submitInput parameters regarding the merge
 * @throws RestApiException if an error occurred.
 * @throws PermissionBackendException if permissions can't be checked
 * @throws IOException an error occurred reading from NoteDb.
 * @return the merged change
 */
public Change merge(Change change, IdentifiedUser caller, boolean checkSubmitRules, SubmitInput submitInput, boolean dryrun) throws RestApiException, UpdateException, IOException, ConfigInvalidException, PermissionBackendException {
    this.submitInput = submitInput;
    this.notify = notifyResolver.resolve(firstNonNull(submitInput.notify, NotifyHandling.ALL), submitInput.notifyDetails);
    this.dryrun = dryrun;
    this.caller = caller;
    this.ts = TimeUtil.now();
    this.submissionId = new SubmissionId(change);
    try (TraceContext traceContext = TraceContext.open().addTag(RequestId.Type.SUBMISSION_ID, new RequestId(submissionId.toString()))) {
        openRepoManager();
        logger.atFine().log("Beginning integration of %s", change);
        try {
            ChangeSet indexBackedChangeSet = mergeSuperSet.setMergeOpRepoManager(orm).completeChangeSet(change, caller, /* includingTopicClosure= */
            false);
            if (!indexBackedChangeSet.ids().contains(change.getId())) {
                // indexBackedChangeSet contains only open changes, if the change is missing in this set
                // it might be that the change was concurrently submitted in the meantime.
                change = changeDataFactory.create(change).reloadChange();
                if (!change.isNew()) {
                    throw new ResourceConflictException("change is " + ChangeUtil.status(change));
                }
                throw new IllegalStateException(String.format("change %s missing from %s", change.getId(), indexBackedChangeSet));
            }
            if (indexBackedChangeSet.furtherHiddenChanges()) {
                throw new AuthException("A change to be submitted with " + change.getId() + " is not visible");
            }
            logger.atFine().log("Calculated to merge %s", indexBackedChangeSet);
            // Reload ChangeSet so that we don't rely on (potentially) stale index data for merging
            ChangeSet noteDbChangeSet = reloadChanges(indexBackedChangeSet);
            // At this point, any change that isn't new can be filtered out since they were only here
            // in the first place due to stale index.
            List<ChangeData> filteredChanges = new ArrayList<>();
            for (ChangeData changeData : noteDbChangeSet.changes()) {
                if (!changeData.change().getStatus().equals(Status.NEW)) {
                    logger.atFine().log("Change %s has status %s due to stale index, so it is skipped during submit", changeData.getId(), changeData.change().getStatus().name());
                    continue;
                }
                filteredChanges.add(changeData);
            }
            // There are no hidden changes (or else we would have thrown AuthException above).
            ChangeSet filteredNoteDbChangeSet = new ChangeSet(filteredChanges, /* hiddenChanges= */
            ImmutableList.of());
            // Count cross-project submissions outside of the retry loop. The chance of a single project
            // failing increases with the number of projects, so the failure count would be inflated if
            // this metric were incremented inside of integrateIntoHistory.
            int projects = filteredNoteDbChangeSet.projects().size();
            if (projects > 1) {
                topicMetrics.topicSubmissions.increment();
            }
            SubmissionExecutor submissionExecutor = new SubmissionExecutor(dryrun, superprojectUpdateSubmissionListeners);
            RetryTracker retryTracker = new RetryTracker();
            retryHelper.changeUpdate("integrateIntoHistory", updateFactory -> {
                long attempt = retryTracker.lastAttemptNumber + 1;
                boolean isRetry = attempt > 1;
                if (isRetry) {
                    logger.atFine().log("Retrying, attempt #%d; skipping merged changes", attempt);
                    this.ts = TimeUtil.now();
                    openRepoManager();
                }
                this.commitStatus = new CommitStatus(filteredNoteDbChangeSet, isRetry);
                if (checkSubmitRules) {
                    logger.atFine().log("Checking submit rules and state");
                    checkSubmitRulesAndState(filteredNoteDbChangeSet, isRetry);
                } else {
                    logger.atFine().log("Bypassing submit rules");
                    bypassSubmitRulesAndRequirements(filteredNoteDbChangeSet);
                }
                integrateIntoHistory(filteredNoteDbChangeSet, submissionExecutor);
                return null;
            }).listener(retryTracker).defaultTimeoutMultiplier(filteredNoteDbChangeSet.projects().size() * 2).retryOn(t -> t instanceof RuntimeException).call();
            submissionExecutor.afterExecutions(orm);
            if (projects > 1) {
                topicMetrics.topicSubmissionsCompleted.increment();
            }
            // (e.g. caller provided a change that was already merged).
            return updatedChanges.containsKey(change.getId()) ? updatedChanges.get(change.getId()) : change;
        } catch (IOException e) {
            // Anything before the merge attempt is an error
            throw new StorageException(e);
        }
    }
}
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) RequestId(com.google.gerrit.server.logging.RequestId) ArrayList(java.util.ArrayList) AuthException(com.google.gerrit.extensions.restapi.AuthException) IOException(java.io.IOException) ChangeData(com.google.gerrit.server.query.change.ChangeData) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) SubmissionId(com.google.gerrit.entities.SubmissionId) TraceContext(com.google.gerrit.server.logging.TraceContext) StorageException(com.google.gerrit.exceptions.StorageException) SubmissionExecutor(com.google.gerrit.server.update.SubmissionExecutor)

Example 2 with Status

use of com.google.gerrit.entities.Change.Status in project gerrit by GerritCodeReview.

the class ChangeIndexRewriter method extractStatus.

private static EnumSet<Change.Status> extractStatus(Predicate<ChangeData> in) {
    if (in instanceof ChangeStatusPredicate) {
        Status status = ((ChangeStatusPredicate) in).getStatus();
        return status != null ? EnumSet.of(status) : null;
    } else if (in instanceof NotPredicate) {
        EnumSet<Status> s = extractStatus(in.getChild(0));
        return s != null ? EnumSet.complementOf(s) : null;
    } else if (in instanceof OrPredicate) {
        EnumSet<Change.Status> r = null;
        int childrenWithStatus = 0;
        for (int i = 0; i < in.getChildCount(); i++) {
            EnumSet<Status> c = extractStatus(in.getChild(i));
            if (c != null) {
                if (r == null) {
                    r = EnumSet.noneOf(Change.Status.class);
                }
                r.addAll(c);
                childrenWithStatus++;
            }
        }
        if (r != null && childrenWithStatus < in.getChildCount()) {
            // the child was used at the root of a query.
            return EnumSet.allOf(Change.Status.class);
        }
        return r;
    } else if (in instanceof AndPredicate) {
        EnumSet<Change.Status> r = null;
        for (int i = 0; i < in.getChildCount(); i++) {
            EnumSet<Change.Status> c = extractStatus(in.getChild(i));
            if (c != null) {
                if (r == null) {
                    r = EnumSet.allOf(Change.Status.class);
                }
                r.retainAll(c);
            }
        }
        return r;
    }
    return null;
}
Also used : Status(com.google.gerrit.entities.Change.Status) OrPredicate(com.google.gerrit.index.query.OrPredicate) EnumSet(java.util.EnumSet) ChangeStatusPredicate(com.google.gerrit.server.query.change.ChangeStatusPredicate) AndPredicate(com.google.gerrit.index.query.AndPredicate) Change(com.google.gerrit.entities.Change) NotPredicate(com.google.gerrit.index.query.NotPredicate)

Aggregations

Change (com.google.gerrit.entities.Change)2 Status (com.google.gerrit.entities.Change.Status)2 Attempt (com.github.rholder.retry.Attempt)1 RetryListener (com.github.rholder.retry.RetryListener)1 AutoValue (com.google.auto.value.AutoValue)1 Joiner (com.google.common.base.Joiner)1 MoreObjects.firstNonNull (com.google.common.base.MoreObjects.firstNonNull)1 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)1 ListMultimap (com.google.common.collect.ListMultimap)1 MultimapBuilder (com.google.common.collect.MultimapBuilder)1 SetMultimap (com.google.common.collect.SetMultimap)1 FluentLogger (com.google.common.flogger.FluentLogger)1 Nullable (com.google.gerrit.common.Nullable)1 BranchNameKey (com.google.gerrit.entities.BranchNameKey)1 PatchSet (com.google.gerrit.entities.PatchSet)1 Project (com.google.gerrit.entities.Project)1