# HG changeset patch # User Pierre-Yves David # Date 2016-04-30 16:41:08 # Node ID cf7de4aeb86b87d93f23c3b99303f8bab005980c # Parent 693b856a4d45567a1a0dc653540294e93a8d692d destutil: add the ability to specify a search space for rebase destination In the 'hg pull --rebase', we don't want to pick a rebase destination unrelated to the pull, we lay down basic infrastructure to allow such restriction on stable (before 3.8 release) in this case. See issue 5214 for details. Actual usage and test will be in the next patch. diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -69,12 +69,12 @@ def _makeextrafn(copiers): c(ctx, extra) return extrafn -def _destrebase(repo, sourceset): +def _destrebase(repo, sourceset, destspace=None): """small wrapper around destmerge to pass the right extra args Please wrap destutil.destmerge instead.""" return destutil.destmerge(repo, action='rebase', sourceset=sourceset, - onheadcheck=False) + onheadcheck=False, destspace=destspace) revsetpredicate = registrar.revsetpredicate() @@ -222,6 +222,9 @@ def rebase(ui, repo, **opts): srcf = opts.get('source', None) basef = opts.get('base', None) revf = opts.get('rev', []) + # search default destination in this space + # used in the 'hg pull --rebase' case, see issue 5214. + destspace = opts.get('_destspace') contf = opts.get('continue') abortf = opts.get('abort') collapsef = opts.get('collapse', False) @@ -296,7 +299,8 @@ def rebase(ui, repo, **opts): _checkobsrebase(repo, ui, rebaseobsrevs, rebasesetrevs, rebaseobsskipped) else: - dest, rebaseset = _definesets(ui, repo, destf, srcf, basef, revf) + dest, rebaseset = _definesets(ui, repo, destf, srcf, basef, revf, + destspace=destspace) if dest is None: return _nothingtorebase() @@ -525,9 +529,12 @@ def rebase(ui, repo, **opts): finally: release(lock, wlock) -def _definesets(ui, repo, destf=None, srcf=None, basef=None, revf=[]): +def _definesets(ui, repo, destf=None, srcf=None, basef=None, revf=[], + destspace=None): """use revisions argument to define destination and rebase set """ + # destspace is here to work around issues with `hg pull --rebase` see + # issue5214 for details if srcf and basef: raise error.Abort(_('cannot specify both a source and a base')) if revf and basef: @@ -560,7 +567,7 @@ def _definesets(ui, repo, destf=None, sr "can't compute rebase set\n")) return None, None if not destf: - dest = repo[_destrebase(repo, base)] + dest = repo[_destrebase(repo, base, destspace=destspace)] destf = str(dest) commonanc = repo.revs('ancestor(%ld, %d)', base, dest).first() @@ -598,7 +605,7 @@ def _definesets(ui, repo, destf=None, sr return None, None if not destf: - dest = repo[_destrebase(repo, rebaseset)] + dest = repo[_destrebase(repo, rebaseset, destspace=destspace)] destf = str(dest) return dest, rebaseset diff --git a/mercurial/destutil.py b/mercurial/destutil.py --- a/mercurial/destutil.py +++ b/mercurial/destutil.py @@ -256,7 +256,7 @@ msgdestmerge = { }, } -def _destmergebook(repo, action='merge', sourceset=None): +def _destmergebook(repo, action='merge', sourceset=None, destspace=None): """find merge destination in the active bookmark case""" node = None bmheads = repo.bookmarkheads(repo._activebookmark) @@ -275,7 +275,8 @@ def _destmergebook(repo, action='merge', assert node is not None return node -def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True): +def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True, + destspace=None): """find merge destination based on branch heads""" node = None @@ -308,6 +309,12 @@ def _destmergebranch(repo, action='merge bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset)) # filters out bookmarked heads nbhs = list(repo.revs('%ld - bookmark()', bheads)) + + if destspace is not None: + # restrict search space + # used in the 'hg pull --rebase' case, see issue 5214. + nbhs = list(repo.revs('%ld and %ld', destspace, nbhs)) + if len(nbhs) > 1: # Case B: There is more than 1 other anonymous heads # @@ -339,18 +346,22 @@ def _destmergebranch(repo, action='merge assert node is not None return node -def destmerge(repo, action='merge', sourceset=None, onheadcheck=True): +def destmerge(repo, action='merge', sourceset=None, onheadcheck=True, + destspace=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 """ + # destspace is here to work around issues with `hg pull --rebase` see + # issue5214 for details if repo._activebookmark: - node = _destmergebook(repo, action=action, sourceset=sourceset) + node = _destmergebook(repo, action=action, sourceset=sourceset, + destspace=destspace) else: node = _destmergebranch(repo, action=action, sourceset=sourceset, - onheadcheck=onheadcheck) + onheadcheck=onheadcheck, destspace=destspace) return repo[node].rev() histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'