[PATCH 2 of 2 STABLE] merge: improve error detection and reporting

Greg Ward greg-hg at gerg.ca
Sun May 2 09:48:52 CDT 2010


# HG changeset patch
# User Greg Ward <greg-hg at gerg.ca>
# Date 1272811643 14400
# Branch stable
# Node ID 89413f695c67fc7c03814ce94dba480773c8cfde
# Parent  b344ddac6247c92150da4187b3365ab2f2442abd
merge: improve error detection and reporting.
- make hg exit with non-zero status when branch has 1 or >2 heads
- tweak the error messages for those cases
- add explicit detection of merging current changeset with itself
- rewrite messages for attempting to merge with ancestor or descendant
  of current changeset

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2225,19 +2225,20 @@
         branch = repo.changectx(None).branch()
         bheads = repo.branchheads(branch)
         if len(bheads) > 2:
-            ui.warn(_("abort: branch '%s' has %d heads - "
-                      "please merge with an explicit rev\n")
-                    % (branch, len(bheads)))
-            ui.status(_("(run 'hg heads .' to see heads)\n"))
-            return False
+            raise util.Abort(_(
+                'branch \'%s\' has %d heads -- '
+                'please merge with explicit rev\n'
+                '(run "hg heads %s" to see all branch heads)')
+                % (branch, len(bheads), branch))
 
         parent = repo.dirstate.parents()[0]
         if len(bheads) == 1:
             if len(repo.heads()) > 1:
-                ui.warn(_("abort: branch '%s' has one head - "
-                          "please merge with an explicit rev\n" % branch))
-                ui.status(_("(run 'hg heads' to see all heads)\n"))
-                return False
+                raise util.Abort(_(
+                    'branch \'%s\' has one head -- '
+                    'please merge with explicit rev\n'
+                    '(run "hg heads -t" to see all repository heads)')
+                    % branch)
             msg = _('there is nothing to merge')
             if parent != repo.lookup(repo[None].branch()):
                 msg = _('%s - use "hg update" instead') % msg
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -408,7 +408,7 @@
 
 def update(repo, node, branchmerge, force, partial):
     """
-    Perform a merge between the working directory and the given node
+    Perform a merge between the working directory and the given node.
 
     node = the node to update to, or None if unspecified
     branchmerge = whether to merge between branches
@@ -461,18 +461,28 @@
         fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
         fastforward = False
 
+        errprefix = _('nothing to merge')
+        errself = _('attempt to merge current changeset with itself')
+        errancestor = _('attempt to merge with an ancestor of the working dir')
+        errdesc = _('attempt to merge with a descendant of the working dir')
+
         ### check phase
         if not overwrite and len(pl) > 1:
             raise util.Abort(_("outstanding uncommitted merges"))
         if branchmerge:
-            if pa == p2:
-                raise util.Abort(_("can't merge with ancestor"))
+            if p1 == p2:
+                raise util.Abort('%s\n(%s)' % (errprefix, errself))
+            elif pa == p2:
+                raise util.Abort('%s\n(%s)' % (errprefix, errancestor))
             elif pa == p1:
                 if p1.branch() != p2.branch():
                     fastforward = True
                 else:
-                    raise util.Abort(_("nothing to merge (use 'hg update'"
-                                       " or check 'hg heads')"))
+                    # we could advise the user to update to the latest branch
+                    # head, but we should check that there is a later branch
+                    # head first
+                    raise util.Abort('%s\n(%s)' % (errprefix, errdesc))
+
             if not force and (wc.files() or wc.deleted()):
                 raise util.Abort(_("outstanding uncommitted changes "
                                    "(use 'hg status' to list changes)"))
diff --git a/tests/test-issue619.out b/tests/test-issue619.out
--- a/tests/test-issue619.out
+++ b/tests/test-issue619.out
@@ -6,5 +6,6 @@
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 (branch merge, don't forget to commit)
 bogus fast-forward should fail
-abort: can't merge with ancestor
+abort: nothing to merge
+(attempt to merge with an ancestor of the working dir)
 done
diff --git a/tests/test-merge-closedheads.out b/tests/test-merge-closedheads.out
--- a/tests/test-merge-closedheads.out
+++ b/tests/test-merge-closedheads.out
@@ -7,8 +7,8 @@
 created new head
 % fail with three heads
 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-abort: branch 'default' has 3 heads - please merge with an explicit rev
-(run 'hg heads .' to see heads)
+abort: branch 'default' has 3 heads -- please merge with explicit rev
+(run "hg heads default" to see all branch heads)
 % close one of the heads
 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
 % succeed with two open heads
diff --git a/tests/test-merge-default.out b/tests/test-merge-default.out
--- a/tests/test-merge-default.out
+++ b/tests/test-merge-default.out
@@ -5,12 +5,12 @@
 created new head
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 % should fail because not at a head
-abort: branch 'default' has 3 heads - please merge with an explicit rev
-(run 'hg heads .' to see heads)
+abort: branch 'default' has 3 heads -- please merge with explicit rev
+(run "hg heads default" to see all branch heads)
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 % should fail because > 2 heads
-abort: branch 'default' has 3 heads - please merge with an explicit rev
-(run 'hg heads .' to see heads)
+abort: branch 'default' has 3 heads -- please merge with explicit rev
+(run "hg heads default" to see all branch heads)
 % should succeed
 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
 (branch merge, don't forget to commit)
@@ -32,8 +32,8 @@
 marked working directory as branch foobranch
 created new head
 % should fail because merge with other branch
-abort: branch 'foobranch' has one head - please merge with an explicit rev
-(run 'hg heads' to see all heads)
+abort: branch 'foobranch' has one head -- please merge with explicit rev
+(run "hg heads -t" to see all repository heads)
 % merge preview not affected by common ancestor
 2:2d95304fed5d
 4:f25cbe84d8b3
diff --git a/tests/test-merge-errors.out b/tests/test-merge-errors.out
--- a/tests/test-merge-errors.out
+++ b/tests/test-merge-errors.out
@@ -6,17 +6,20 @@
 
 % refuse to merge with ancestor of current changeset
 hg merge 0
-abort: can't merge with ancestor
+abort: nothing to merge
+(attempt to merge with an ancestor of the working dir)
 status=255
 
 % refuse to merge with self
 hg merge 2
-abort: can't merge with ancestor
+abort: nothing to merge
+(attempt to merge current changeset with itself)
 status=255
 
 % refuse to merge with descendant
 hg merge 1
-abort: nothing to merge (use 'hg update' or check 'hg heads')
+abort: nothing to merge
+(attempt to merge with a descendant of the working dir)
 status=255
 
 % create named branch with only one head
@@ -24,9 +27,9 @@
 
 % refuse to merge when only one branch head
 hg merge
-abort: branch 'foo' has one head - please merge with an explicit rev
-(run 'hg heads' to see all heads)
-status=0
+abort: branch 'foo' has one head -- please merge with explicit rev
+(run "hg heads -t" to see all repository heads)
+status=255
 
 % turn branch foo into a 3-head monster
 adding d
@@ -37,6 +40,6 @@
 
 % refuse to merge when > 2 heads
 hg merge
-abort: branch 'foo' has 3 heads - please merge with an explicit rev
-(run 'hg heads .' to see heads)
-status=0
+abort: branch 'foo' has 3 heads -- please merge with explicit rev
+(run "hg heads foo" to see all branch heads)
+status=255
diff --git a/tests/test-newbranch.out b/tests/test-newbranch.out
--- a/tests/test-newbranch.out
+++ b/tests/test-newbranch.out
@@ -167,12 +167,12 @@
 summary:     a
 
 % implicit merge with test branch as parent
-abort: branch 'test' has one head - please merge with an explicit rev
-(run 'hg heads' to see all heads)
+abort: branch 'test' has one head -- please merge with explicit rev
+(run "hg heads -t" to see all repository heads)
 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
 % implicit merge with default branch as parent
-abort: branch 'default' has 3 heads - please merge with an explicit rev
-(run 'hg heads .' to see heads)
+abort: branch 'default' has 3 heads -- please merge with explicit rev
+(run "hg heads default" to see all branch heads)
 % 3 branch heads, explicit merge required
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 (branch merge, don't forget to commit)


More information about the Mercurial-devel mailing list