--- a/mercurial/destutil.py Mon Feb 08 18:12:06 2016 +0100
+++ b/mercurial/destutil.py Mon Feb 08 19:32:29 2016 +0100
@@ -185,9 +185,19 @@
(_('working directory not at a head revision'),
_("use 'hg update' or merge with an explicit revision"))
},
+ 'emptysourceset':
+ {'merge':
+ (_('source set is empty'),
+ None)
+ },
+ 'multiplebranchessourceset':
+ {'merge':
+ (_('source set is rooted in multiple branches'),
+ None)
+ },
}
-def _destmergebook(repo, action='merge'):
+def _destmergebook(repo, action='merge', sourceset=None):
"""find merge destination in the active bookmark case"""
node = None
bmheads = repo.bookmarkheads(repo._activebookmark)
@@ -206,15 +216,27 @@
assert node is not None
return node
-def _destmergebranch(repo, action='merge'):
+def _destmergebranch(repo, action='merge', sourceset=None):
"""find merge destination based on branch heads"""
node = None
- parent = repo.dirstate.p1()
- branch = repo.dirstate.branch()
+
+ if sourceset is None:
+ sourceset = [repo[repo.dirstate.p1()].rev()]
+ branch = repo.dirstate.branch()
+ elif not sourceset:
+ msg, hint = msgdestmerge['emptysourceset'][action]
+ raise error.Abort(msg, hint=hint)
+ else:
+ branch = None
+ for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
+ if branch is not None and ctx.branch() != branch:
+ msg, hint = msgdestmerge['multiplebranchessourceset'][action]
+ raise error.Abort(msg, hint=hint)
+ branch = ctx.branch()
+
bheads = repo.branchheads(branch)
-
- if parent not in bheads:
- # Case A: working copy if not on a head.
+ if not repo.revs('%ld and %ln', sourceset, bheads):
+ # Case A: working copy if not on a head. (merge only)
#
# This is probably a user mistake We bailout pointing at 'hg update'
if len(repo.heads()) <= 1:
@@ -222,10 +244,10 @@
else:
msg, hint = msgdestmerge['notatheads'][action]
raise error.Abort(msg, hint=hint)
- # remove current head from the set
- bheads = [bh for bh in bheads if bh != parent]
+ # remove heads descendants of source from the set
+ bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
# filters out bookmarked heads
- nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
+ nbhs = list(repo.revs('%ld - bookmark()', bheads))
if len(nbhs) > 1:
# Case B: There is more than 1 other anonymous heads
#
@@ -253,7 +275,7 @@
assert node is not None
return node
-def destmerge(repo, action='merge'):
+def destmerge(repo, action='merge', sourceset=None):
"""return the default destination for a merge
(or raise exception about why it can't pick one)
@@ -261,9 +283,9 @@
:action: the action being performed, controls emitted error message
"""
if repo._activebookmark:
- node = _destmergebook(repo, action=action)
+ node = _destmergebook(repo, action=action, sourceset=sourceset)
else:
- node = _destmergebranch(repo, action=action)
+ node = _destmergebranch(repo, action=action, sourceset=sourceset)
return repo[node].rev()
histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'