D789: merge: add option to abort merge process on failure

ryanmce (Ryan McElroy) phabricator at mercurial-scm.org
Fri Sep 22 11:28:40 UTC 2017


ryanmce created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Traditionally, the merge process attempts to merge all unresolved files
  using the merge tool of choice, regardless of whether previous file merge
  attempts succeeded or failed. Setting the merge.abortonfailure option to
  True changes this behavior so that a failed merge will immediately abort
  the merge operation, leaving the user in a normal unresolved merge state.
  
  This is particularly useful when there may be many files to be merged and the
  user just wants to abort the process by exiting their editor with an error.

TEST PLAN
  Added a new test

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D789

AFFECTED FILES
  mercurial/configitems.py
  mercurial/filemerge.py
  mercurial/help/config.txt
  tests/test-filemerge-abort.t

CHANGE DETAILS

diff --git a/tests/test-filemerge-abort.t b/tests/test-filemerge-abort.t
new file mode 100644
--- /dev/null
+++ b/tests/test-filemerge-abort.t
@@ -0,0 +1,36 @@
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > rebase=
+  > [phases]
+  > publish=False
+  > [merge]
+  > abortonfailure=True
+  > EOF
+
+  $ hg init repo
+  $ cd repo
+  $ echo a > a
+  $ echo b > b
+  $ hg commit -qAm ab
+  $ echo c >> a
+  $ echo c >> b
+  $ hg commit -qAm c
+  $ hg up -q .^
+  $ echo d >> a
+  $ echo d >> b
+  $ hg commit -qAm d
+  $ hg rebase -s 1 -d 2 --tool false
+  rebasing 1:1f28a51c3c9b "c"
+  merging a
+  merging b
+  abort: merge aborted due to nonrzero mergetool return code
+  [255]
+  $ hg rebase --abort
+  rebase aborted
+  $ hg rebase -s 1 -d 2 --tool true
+  rebasing 1:1f28a51c3c9b "c"
+  merging a
+  merging b
+  note: rebase of 1:1f28a51c3c9b created no changes to commit
+  saved backup bundle to $TESTTMP/repo/.hg/strip-backup/1f28a51c3c9b-5312ccf5-rebase.hg (glob)
+
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -1239,6 +1239,14 @@
    different contents. Similar to ``merge.checkignored``, except for files that
    are not ignored. (default: ``abort``)
 
+``abortonfailure``
+   Traditionally, the merge process attempts to merge all unresolved files
+   using the merge tool of choice, regardless of whether previous file merge
+   attempts succeeded or failed. Setting the ``merge.abortonfailure`` option to
+   True changes this behavior so that a failed merge will immediately abort
+   the merge operation, leaving the user in a normal unresolved merge state.
+   (default: ``False``)
+
 ``merge-patterns``
 ------------------
 
diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -514,13 +514,30 @@
             repo.ui.status(_('running merge tool %s for file %s\n') %
                            (tool, fcd.path()))
         repo.ui.debug('launching merge tool: %s\n' % cmd)
-        r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool')
+        onerr = getmergeerrorhandler(repo)
+        r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool',
+                      onerr=onerr)
         repo.ui.debug('merge tool returned: %s\n' % r)
         return True, r, False
     finally:
         util.unlink(b)
         util.unlink(c)
 
+def getmergeerrorhandler(repo):
+    """
+    Traditionally, the merge process attempts to merge all unresolved files
+    using the merge tool of choice, regardless of whether previous file merge
+    attempts succeeded or failed. Setting the merge.abortonfailure option to
+    True changes this behavior so that a failed merge will immediately abort
+    the merge operation, leaving the user in a normal unresolved merge state.
+    """
+    onerr = None
+    if repo.ui.configbool('merge', 'abortonfailure'):
+        def onerr(*args):
+            msg = _('merge aborted due to nonrzero mergetool return code')
+            raise error.Abort(msg)
+    return onerr
+
 def _formatconflictmarker(repo, ctx, template, label, pad):
     """Applies the given template to the ctx, prefixed by the label.
 
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -296,6 +296,9 @@
 coreconfigitem('merge', 'followcopies',
     default=True,
 )
+coreconfigitem('merge', 'abortonfailure',
+    default=False,
+)
 coreconfigitem('pager', 'ignore',
     default=list,
 )



To: ryanmce, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list