MergeUtil: Create an optimized canFastForwardOrMerge

This method de-duplicates the potentially expensive
hasMissingDependencies() call for callers that needed to do
`canFastForward() || canMerge()`.

Change-Id: If4b5a1244b79d84103af8939e621b503ba587cc3
Release-Notes: Improved performance for conflicts: operator and other mergability checks when submit type is Merge-If-Necessary
diff --git a/java/com/google/gerrit/server/git/MergeUtil.java b/java/com/google/gerrit/server/git/MergeUtil.java
index c1333cb..fac05d2 100644
--- a/java/com/google/gerrit/server/git/MergeUtil.java
+++ b/java/com/google/gerrit/server/git/MergeUtil.java
@@ -679,6 +679,10 @@
       return false;
     }
 
+    return canMerge(mergeTip, repo, toMerge);
+  }
+
+  private boolean canMerge(CodeReviewCommit mergeTip, Repository repo, CodeReviewCommit toMerge) {
     try (ObjectInserter ins = new InMemoryInserter(repo)) {
       return newThreeWayMerger(ins, repo.getConfig()).merge(mergeTip, toMerge);
     } catch (LargeObjectException e) {
@@ -700,6 +704,11 @@
       return false;
     }
 
+    return canFastForward(mergeTip, rw, toMerge);
+  }
+
+  private boolean canFastForward(
+      CodeReviewCommit mergeTip, CodeReviewRevWalk rw, CodeReviewCommit toMerge) {
     try {
       return mergeTip == null
           || rw.isMergedInto(mergeTip, toMerge)
@@ -709,6 +718,19 @@
     }
   }
 
+  public boolean canFastForwardOrMerge(
+      MergeSorter mergeSorter,
+      CodeReviewCommit mergeTip,
+      CodeReviewRevWalk rw,
+      Repository repo,
+      CodeReviewCommit toMerge) {
+    if (hasMissingDependencies(mergeSorter, toMerge)) {
+      return false;
+    }
+
+    return canFastForward(mergeTip, rw, toMerge) || canMerge(mergeTip, repo, toMerge);
+  }
+
   public boolean canCherryPick(
       MergeSorter mergeSorter,
       Repository repo,
@@ -751,8 +773,7 @@
     // by an equivalent merge with a different first parent. So
     // instead behave as though MERGE_IF_NECESSARY was configured.
     //
-    return canFastForward(mergeSorter, mergeTip, rw, toMerge)
-        || canMerge(mergeSorter, repo, mergeTip, toMerge);
+    return canFastForwardOrMerge(mergeSorter, mergeTip, rw, repo, toMerge);
   }
 
   public boolean hasMissingDependencies(MergeSorter mergeSorter, CodeReviewCommit toMerge) {
diff --git a/java/com/google/gerrit/server/submit/MergeIfNecessary.java b/java/com/google/gerrit/server/submit/MergeIfNecessary.java
index 30f1661..c6877d2 100644
--- a/java/com/google/gerrit/server/submit/MergeIfNecessary.java
+++ b/java/com/google/gerrit/server/submit/MergeIfNecessary.java
@@ -48,7 +48,7 @@
 
   static boolean dryRun(
       SubmitDryRun.Arguments args, CodeReviewCommit mergeTip, CodeReviewCommit toMerge) {
-    return args.mergeUtil.canFastForward(args.mergeSorter, mergeTip, args.rw, toMerge)
-        || args.mergeUtil.canMerge(args.mergeSorter, args.repo, mergeTip, toMerge);
+    return args.mergeUtil.canFastForwardOrMerge(
+        args.mergeSorter, mergeTip, args.rw, args.repo, toMerge);
   }
 }