[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