@@ -183,13 +183,23 @@ msgdestmerge = {
'notatheads':
{'merge':
(_('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)
curhead = repo[repo._activebookmark].node()
if len(bmheads) == 2:
@@ -204,30 +214,42 @@ def _destmergebook(repo, action='merge')
msg, hint = msgdestmerge['nootherbookmarks'][action]
raise error.Abort(msg, hint=hint)
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:
msg, hint = msgdestmerge['nootherheadsbehind'][action]
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]
+ 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
#
# This means that there will be more than 1 candidate. This is
# ambiguous. We abort asking the user to pick as explicit destination
@@ -251,21 +273,21 @@ def _destmergebranch(repo, action='merge
else:
node = nbhs[0]
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)
: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())'
def desthistedit(ui, repo):
@@ -539,12 +539,14 @@ def _destupdate(repo, subset, x):
return subset & baseset([destutil.destupdate(repo, **args)[0]])
@predicate('_destmerge')
def _destmerge(repo, subset, x):
# experimental revset for merge destination
- getargs(x, 0, 0, _("_mergedefaultdest takes no arguments"))
- return subset & baseset([destutil.destmerge(repo)])
+ sourceset = None
+ if x is not None:
+ sourceset = getset(repo, fullreposet(repo), x)
+ return subset & baseset([destutil.destmerge(repo, sourceset=sourceset)])
@predicate('adds(pattern)', safe=True)
def adds(repo, subset, x):
"""Changesets that add a file matching pattern.
@@ -114,5 +114,38 @@ Test experimental destination revset
$ hg log -r '_destmerge()'
abort: branch 'foobranch' has one head - please merge with an explicit rev
(run 'hg heads' to see all heads)
[255]
+(on a branch with a two heads)
+
+ $ hg up 5
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ echo f >> a
+ $ hg commit -mf
+ created new head
+ $ hg log -r '_destmerge()'
+ changeset: 6:e88e33f3bf62
+ parent: 5:a431fabd6039
+ parent: 3:ea9ff125ff88
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: m2
+
+
+(from the other head)
+
+ $ hg log -r '_destmerge(e88e33f3bf62)'
+ changeset: 8:b613918999e2
+ tag: tip
+ parent: 5:a431fabd6039
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: f
+
+
+(from unrelated branch)
+
+ $ hg log -r '_destmerge(foobranch)'
+ abort: branch 'foobranch' has one head - please merge with an explicit rev
+ (run 'hg heads' to see all heads)
+ [255]