src/topic/destination.py
author Pierre-Yves David <pierre-yves.david@fb.com>
Sat, 12 Mar 2016 18:42:16 +0000
changeset 1887 68125d026b07
parent 1878 c44f161575ba
child 1891 077c40f206d1
permissions -rw-r--r--
push: hackish handeling of new branch head from phase move The current head checking mechanism is not expecting "head change" from phase movement. Topic allows that, changeset with a topic moving to public can create a new head. We introduce a hack to double check that no head were added at the transaction level to work around this.

from mercurial import error
from mercurial import util
from mercurial import destutil
from mercurial import extensions
from mercurial.i18n import _

def _destmergebranch(orig, repo, action='merge', sourceset=None, onheadcheck=True):
    p1 = repo['.']
    top = p1.topic()
    if top:
        heads = repo.revs('heads(topic(.)::topic(.))')
        if p1.rev() not in heads:
            raise error.Abort(_("not at topic head, update or explicit"))
        elif 1 == len(heads):
            # should look at all branch involved but... later
            bhead = ngtip(repo, p1.branch(), all=True)
            if not bhead:
                raise error.Abort(_("nothing to merge"))
            elif 1 == len(bhead):
                return bhead.first()
            else:
                raise error.Abort(_("branch '%s' has %d heads - "
                                   "please merge with an explicit rev")
                                 % (p1.branch(), len(bhead)),
                                 hint=_("run 'hg heads .' to see heads"))
        elif 2 == len(heads):
            heads = [r for r in heads if r != p1.rev()]
            # XXX: bla bla bla bla bla
            if 1 < len(heads):
                raise error.Abort(_('working directory not at a head revision'),
                                 hint=_("use 'hg update' or merge with an "
                                        "explicit revision"))
            return heads[0]
        elif 2 < len(heads):
            raise error.Abort(_("topic '%s' has %d heads - "
                                "please merge with an explicit rev")
                              % (top, len(heads)))
        else:
            assert False # that's impossible
    if orig.func_default: # version above hg-3.7
        return orig(repo, action, sourceset, onheadcheck)
    else:
        return orig(repo)

def setupdest():
    if util.safehasattr(destutil, '_destmergebranch'):
        extensions.wrapfunction(destutil, '_destmergebranch', _destmergebranch)

def ngtip(repo, branch, all=False):
    """tip new generation"""
    ## search for untopiced heads of branch
    # could be heads((::branch(x) - topic()))
    # but that is expensive
    #
    # we should write plain code instead
    subquery = '''heads(
                    parents(
                       ancestor(
                         (head() and branch(%s)
                         or (topic() and branch(%s)))))
                   ::(head() and branch(%s))
                   - topic())'''
    if not all:
        subquery = 'max(%s)' % subquery
    return repo.revs(subquery, branch, branch, branch)