changeset 751:3dc67825ce0d

Emulate fast-forward merge when dstBranch is reachable from srcRevision
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Mon, 10 Feb 2014 21:22:31 +0100
parents c33aefd02111
children a0dfb5cd4477 6b7579d76fdf
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/exception/NothingToMergeException.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMergeSupport.java
diffstat 3 files changed, 61 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java	Mon Feb 10 20:50:45 2014 +0100
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandResult.java	Mon Feb 10 21:22:31 2014 +0100
@@ -211,6 +211,7 @@
     checkConnectionRefused(stderr);
     checkAbandonedTransaction(stderr);
     checkMergeWithWorkDirAncestor(stderr);
+    checkNothingToMerge(stderr);
   }
 
   private void checkUnrelatedRepository(@NotNull final String stderr) throws UnrelatedRepositoryException {
@@ -257,6 +258,11 @@
       throw new MergeWithWorkingDirAncestor();
   }
 
+  private void checkNothingToMerge(@NotNull final String stderr) throws NothingToMergeException {
+    if (stderr.startsWith("abort: nothing to merge"))
+      throw new NothingToMergeException();
+  }
+
   private static Set<Integer> setOf(Integer... ints) {
     return new HashSet<Integer>(asList(ints));
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/exception/NothingToMergeException.java	Mon Feb 10 21:22:31 2014 +0100
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * 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 jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception;
+
+import jetbrains.buildServer.vcs.VcsException;
+
+public class NothingToMergeException extends VcsException {
+
+  public NothingToMergeException() {
+    super("Nothing to merge");
+  }
+
+}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMergeSupport.java	Mon Feb 10 20:50:45 2014 +0100
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMergeSupport.java	Mon Feb 10 21:22:31 2014 +0100
@@ -21,6 +21,7 @@
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.PushCommand;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.MergeConflictException;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.MergeWithWorkingDirAncestor;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.NothingToMergeException;
 import jetbrains.buildServer.vcs.*;
 import org.jetbrains.annotations.NotNull;
 
@@ -104,6 +105,7 @@
               .setBranch(dstBranch).checkout();
 
       HgRepo repo = myHgRepoFactory.createRepo(hgRoot, tmpDir);
+      boolean bookmark = isBookmark(repo, dstBranch);
       try {
         repo.merge().withMergeTool(myConfig.getMergeTool()).revision(srcRevision).call();
       } catch (MergeConflictException e) {
@@ -116,22 +118,26 @@
                 ", revision " + srcRevision +
                 ", destination " + dstBranch, e);
         return MergeResult.createMergeNotPerformedResult("Revision " + srcRevision + " is already merged into " + dstBranch);
+      } catch (NothingToMergeException e) {
+        //happens when revision of the dstBranch is merged into srcRevision
+        if (bookmark) {
+          //emulate fast-forward merge
+          repo.updateBookmark().name(dstBranch).setRevision(srcRevision).call();
+          push(root, srcRevision, dstBranch, hgRoot, repo, bookmark);
+          LOG.info("Merge successfully finished in root " + root + ", revision " + srcRevision + ", destination " + dstBranch);
+          return MergeResult.createMergeSuccessResult();
+        } else {
+          return MergeResult.createMergeError("Revision of branch " + dstBranch + " is reachable from " + srcRevision);
+        }
       }
 
       repo.commit().by(hgRoot.getUserForTag()).message(message).call();
-      boolean bookmark = isBookmark(repo, dstBranch);
+
       if (bookmark)
         repo.updateBookmark().name(dstBranch).call();
 
-      try {
-        PushCommand push = repo.push().toRepository(hgRoot.getRepository());
-        if (bookmark)
-          push.bookmark(dstBranch);
-        push.call();
-      } catch (VcsException e) {
-        LOG.info("Error while pushing a merge commit, root " + root + ", revision " + srcRevision + ", destination " + dstBranch, e);
-        throw e;
-      }
+      push(root, srcRevision, dstBranch, hgRoot, repo, bookmark);
+
       LOG.info("Merge successfully finished in root " + root + ", revision " + srcRevision + ", destination " + dstBranch);
       return MergeResult.createMergeSuccessResult();
     } catch (Exception e) {
@@ -143,6 +149,18 @@
     }
   }
 
+  private void push(VcsRoot root, String srcRevision, String dstBranch, HgVcsRoot hgRoot, HgRepo repo, boolean bookmark) throws VcsException {
+    try {
+      PushCommand push = repo.push().toRepository(hgRoot.getRepository());
+      if (bookmark)
+        push.bookmark(dstBranch);
+      push.call();
+    } catch (VcsException e) {
+      LOG.info("Error while pushing a merge commit, root " + root + ", revision " + srcRevision + ", destination " + dstBranch, e);
+      throw e;
+    }
+  }
+
 
   private boolean isBookmark(@NotNull HgRepo repo, @NotNull String branch) throws VcsException {
     if (repo.branches().call().keySet().contains(branch))