summaryrefslogtreecommitdiffstats
path: root/java/com/google/gerrit/server/submit/SubmitDryRun.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/gerrit/server/submit/SubmitDryRun.java')
-rw-r--r--java/com/google/gerrit/server/submit/SubmitDryRun.java157
1 files changed, 157 insertions, 0 deletions
diff --git a/java/com/google/gerrit/server/submit/SubmitDryRun.java b/java/com/google/gerrit/server/submit/SubmitDryRun.java
new file mode 100644
index 0000000000..e273652d9d
--- /dev/null
+++ b/java/com/google/gerrit/server/submit/SubmitDryRun.java
@@ -0,0 +1,157 @@
+// Copyright (C) 2015 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 java.util.stream.Collectors.toSet;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Streams;
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.extensions.client.SubmitType;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.server.git.CodeReviewCommit;
+import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
+import com.google.gerrit.server.git.MergeUtil;
+import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectState;
+import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevFlag;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTag;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/** Dry run of a submit strategy. */
+public class SubmitDryRun {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ static class Arguments {
+ final Repository repo;
+ final CodeReviewRevWalk rw;
+ final MergeUtil mergeUtil;
+ final MergeSorter mergeSorter;
+
+ Arguments(Repository repo, CodeReviewRevWalk rw, MergeUtil mergeUtil, MergeSorter mergeSorter) {
+ this.repo = repo;
+ this.rw = rw;
+ this.mergeUtil = mergeUtil;
+ this.mergeSorter = mergeSorter;
+ }
+ }
+
+ public static Set<ObjectId> getAlreadyAccepted(Repository repo) throws IOException {
+ return Streams.concat(
+ repo.getRefDatabase().getRefsByPrefix(Constants.R_HEADS).stream(),
+ repo.getRefDatabase().getRefsByPrefix(Constants.R_TAGS).stream())
+ .map(Ref::getObjectId)
+ .filter(Objects::nonNull)
+ .collect(toSet());
+ }
+
+ public static Set<RevCommit> getAlreadyAccepted(Repository repo, RevWalk rw) throws IOException {
+ Set<RevCommit> accepted = new HashSet<>();
+ addCommits(getAlreadyAccepted(repo), rw, accepted);
+ return accepted;
+ }
+
+ public static void addCommits(Iterable<ObjectId> ids, RevWalk rw, Collection<RevCommit> out)
+ throws IOException {
+ for (ObjectId id : ids) {
+ RevObject obj = rw.parseAny(id);
+ if (obj instanceof RevTag) {
+ obj = rw.peel(obj);
+ }
+ if (obj instanceof RevCommit) {
+ out.add((RevCommit) obj);
+ }
+ }
+ }
+
+ private final ProjectCache projectCache;
+ private final MergeUtil.Factory mergeUtilFactory;
+ private final Provider<InternalChangeQuery> queryProvider;
+
+ @Inject
+ SubmitDryRun(
+ ProjectCache projectCache,
+ MergeUtil.Factory mergeUtilFactory,
+ Provider<InternalChangeQuery> queryProvider) {
+ this.projectCache = projectCache;
+ this.mergeUtilFactory = mergeUtilFactory;
+ this.queryProvider = queryProvider;
+ }
+
+ public boolean run(
+ SubmitType submitType,
+ Repository repo,
+ CodeReviewRevWalk rw,
+ Branch.NameKey destBranch,
+ ObjectId tip,
+ ObjectId toMerge,
+ Set<RevCommit> alreadyAccepted)
+ throws IntegrationException, NoSuchProjectException, IOException {
+ CodeReviewCommit tipCommit = rw.parseCommit(tip);
+ CodeReviewCommit toMergeCommit = rw.parseCommit(toMerge);
+ RevFlag canMerge = rw.newFlag("CAN_MERGE");
+ toMergeCommit.add(canMerge);
+ Arguments args =
+ new Arguments(
+ repo,
+ rw,
+ mergeUtilFactory.create(getProject(destBranch)),
+ new MergeSorter(
+ rw, alreadyAccepted, canMerge, queryProvider, ImmutableSet.of(toMergeCommit)));
+
+ switch (submitType) {
+ case CHERRY_PICK:
+ return CherryPick.dryRun(args, tipCommit, toMergeCommit);
+ case FAST_FORWARD_ONLY:
+ return FastForwardOnly.dryRun(args, tipCommit, toMergeCommit);
+ case MERGE_ALWAYS:
+ return MergeAlways.dryRun(args, tipCommit, toMergeCommit);
+ case MERGE_IF_NECESSARY:
+ return MergeIfNecessary.dryRun(args, tipCommit, toMergeCommit);
+ case REBASE_IF_NECESSARY:
+ return RebaseIfNecessary.dryRun(args, repo, tipCommit, toMergeCommit);
+ case REBASE_ALWAYS:
+ return RebaseAlways.dryRun(args, repo, tipCommit, toMergeCommit);
+ case INHERIT:
+ default:
+ String errorMsg = "No submit strategy for: " + submitType;
+ logger.atSevere().log(errorMsg);
+ throw new IntegrationException(errorMsg);
+ }
+ }
+
+ private ProjectState getProject(Branch.NameKey branch) throws NoSuchProjectException {
+ ProjectState p = projectCache.get(branch.getParentKey());
+ if (p == null) {
+ throw new NoSuchProjectException(branch.getParentKey());
+ }
+ return p;
+ }
+}