All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.submit.SubmitStrategy Maven / Gradle / Ivy

The newest version!
// Copyright (C) 2012 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.submit;

import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static java.util.Objects.requireNonNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.SubmissionId;
import com.google.gerrit.extensions.api.changes.SubmitInput;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.approval.ApprovalsUtil;
import com.google.gerrit.server.change.LabelNormalizer;
import com.google.gerrit.server.change.RebaseChangeOp;
import com.google.gerrit.server.change.SetPrivateOp;
import com.google.gerrit.server.change.TestSubmitInput;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.ChangeMerged;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeTip;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.git.MergeUtilFactory;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.validators.OnSubmitValidators;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.SubmitWithStickyApprovalDiff;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.submit.MergeOp.CommitStatus;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;

/**
 * Base class that submit strategies must extend.
 *
 * 

A submit strategy for a certain {@link SubmitType} defines how the submitted commits should be * merged. */ public abstract class SubmitStrategy { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); public static Module module() { return new FactoryModule() { @Override protected void configure() { factory(SubmitStrategy.Arguments.Factory.class); factory(EmailMerge.Factory.class); } }; } static class Arguments { interface Factory { Arguments create( SubmitType submitType, BranchNameKey destBranch, CommitStatus commitStatus, CodeReviewRevWalk rw, IdentifiedUser caller, MergeTip mergeTip, RevFlag canMergeFlag, Set alreadyAccepted, Set incoming, SubmissionId submissionId, SubmitInput submitInput, SubmoduleCommits submoduleCommits, SubscriptionGraph subscriptionGraph, boolean dryrun); } final AccountCache accountCache; final ApprovalsUtil approvalsUtil; final ChangeMerged changeMerged; final ChangeMessagesUtil cmUtil; final EmailMerge.Factory mergedSenderFactory; final GitRepositoryManager repoManager; final LabelNormalizer labelNormalizer; final Config cfg; final PatchSetInfoFactory patchSetInfoFactory; final PatchSetUtil psUtil; final ProjectCache projectCache; final PersonIdent serverIdent; final RebaseChangeOp.Factory rebaseFactory; final OnSubmitValidators.Factory onSubmitValidatorsFactory; final TagCache tagCache; final Provider queryProvider; final ProjectConfig.Factory projectConfigFactory; final SetPrivateOp.Factory setPrivateOpFactory; final SubmitWithStickyApprovalDiff submitWithStickyApprovalDiff; final BranchNameKey destBranch; final CodeReviewRevWalk rw; final CommitStatus commitStatus; final IdentifiedUser caller; final MergeTip mergeTip; final RevFlag canMergeFlag; final Set alreadyAccepted; final SubmissionId submissionId; final SubmitType submitType; final SubmitInput submitInput; final SubscriptionGraph subscriptionGraph; final SubmoduleCommits submoduleCommits; final ProjectState project; final MergeSorter mergeSorter; final RebaseSorter rebaseSorter; final MergeUtil mergeUtil; final boolean dryrun; @Inject Arguments( AccountCache accountCache, ApprovalsUtil approvalsUtil, ChangeMerged changeMerged, ChangeMessagesUtil cmUtil, EmailMerge.Factory mergedSenderFactory, GitRepositoryManager repoManager, LabelNormalizer labelNormalizer, MergeUtilFactory mergeUtilFactory, PatchSetInfoFactory patchSetInfoFactory, PatchSetUtil psUtil, @GerritServerConfig Config cfg, @GerritPersonIdent PersonIdent serverIdent, ProjectCache projectCache, RebaseChangeOp.Factory rebaseFactory, OnSubmitValidators.Factory onSubmitValidatorsFactory, TagCache tagCache, Provider queryProvider, ProjectConfig.Factory projectConfigFactory, SetPrivateOp.Factory setPrivateOpFactory, SubmitWithStickyApprovalDiff submitWithStickyApprovalDiff, @Assisted BranchNameKey destBranch, @Assisted CommitStatus commitStatus, @Assisted CodeReviewRevWalk rw, @Assisted IdentifiedUser caller, @Assisted MergeTip mergeTip, @Assisted RevFlag canMergeFlag, @Assisted Set alreadyAccepted, @Assisted Set incoming, @Assisted SubmissionId submissionId, @Assisted SubmitType submitType, @Assisted SubmitInput submitInput, @Assisted SubscriptionGraph subscriptionGraph, @Assisted SubmoduleCommits submoduleCommits, @Assisted boolean dryrun) { this.accountCache = accountCache; this.approvalsUtil = approvalsUtil; this.changeMerged = changeMerged; this.mergedSenderFactory = mergedSenderFactory; this.repoManager = repoManager; this.cmUtil = cmUtil; this.labelNormalizer = labelNormalizer; this.projectConfigFactory = projectConfigFactory; this.cfg = cfg; this.patchSetInfoFactory = patchSetInfoFactory; this.psUtil = psUtil; this.projectCache = projectCache; this.rebaseFactory = rebaseFactory; this.tagCache = tagCache; this.queryProvider = queryProvider; this.setPrivateOpFactory = setPrivateOpFactory; this.submitWithStickyApprovalDiff = submitWithStickyApprovalDiff; this.serverIdent = serverIdent; this.destBranch = destBranch; this.commitStatus = commitStatus; this.rw = rw; this.caller = caller; this.mergeTip = mergeTip; this.canMergeFlag = canMergeFlag; this.alreadyAccepted = alreadyAccepted; this.submissionId = submissionId; this.submitType = submitType; this.submitInput = submitInput; this.submoduleCommits = submoduleCommits; this.subscriptionGraph = subscriptionGraph; this.dryrun = dryrun; this.project = projectCache.get(destBranch.project()).orElseThrow(illegalState(destBranch.project())); this.mergeSorter = new MergeSorter(caller, rw, alreadyAccepted, canMergeFlag, queryProvider, incoming); this.rebaseSorter = new RebaseSorter( caller, rw, mergeTip.getInitialTip(), alreadyAccepted, canMergeFlag, queryProvider, incoming); this.mergeUtil = mergeUtilFactory.create(project); this.onSubmitValidatorsFactory = onSubmitValidatorsFactory; } } final Arguments args; private final Set submitStrategyOps; SubmitStrategy(Arguments args) { this.args = requireNonNull(args); this.submitStrategyOps = new HashSet<>(); } /** * Returns the updated changed after this submit strategy has been executed. * * @return the updated changes after this submit strategy has been executed */ public ImmutableMap getUpdatedChanges() { return submitStrategyOps.stream() .map(SubmitStrategyOp::getUpdatedChange) .filter(Optional::isPresent) .map(Optional::get) .collect(toImmutableMap(c -> c.getId(), c -> c)); } /** * Add operations to a batch update that execute this submit strategy. * *

Guarantees exactly one op is added to the update for each change in the input set. * * @param bu batch update to add operations to. * @param toMerge the set of submitted commits that should be merged using this submit strategy. * Implementations are responsible for ordering of commits, and will not modify the input in * place. */ public final void addOps(BatchUpdate bu, Set toMerge) { ImmutableList ops = buildOps(toMerge); Set added = Sets.newHashSetWithExpectedSize(ops.size()); for (SubmitStrategyOp op : ops) { added.add(op.getCommit()); } // First add ops for any implicitly merged changes. List difference = new ArrayList<>(Sets.difference(toMerge, added)); Collections.reverse(difference); for (CodeReviewCommit c : difference) { Change.Id id = c.change().getId(); bu.addOp(id, args.setPrivateOpFactory.create(false, null)); ImplicitIntegrateOp implicitIntegrateOp = new ImplicitIntegrateOp(args, c); logger.atFine().log("Add implicit integrate op: %s", implicitIntegrateOp); bu.addOp(id, implicitIntegrateOp); maybeAddTestHelperOp(bu, id); this.submitStrategyOps.add(implicitIntegrateOp); } // Then ops for explicitly merged changes for (SubmitStrategyOp op : ops) { logger.atFine().log("Add explicit integrate op: %s", op); bu.addOp(op.getId(), args.setPrivateOpFactory.create(false, null)); bu.addOp(op.getId(), op); maybeAddTestHelperOp(bu, op.getId()); this.submitStrategyOps.add(op); } } private void maybeAddTestHelperOp(BatchUpdate bu, Change.Id changeId) { if (args.submitInput instanceof TestSubmitInput) { bu.addOp(changeId, new TestHelperOp(changeId, args)); } } protected abstract ImmutableList buildOps(Collection toMerge); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy