view hgext3rd/topic/destination.py @ 2922:66357d4d03b2

topic: centralize compatibility logic between hg versions into compat module This patch can delay loading obsutil and obsolete modules until they are actually used at "hg topics" or so, if demandimport of Mercurial is enabled.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Sun, 10 Sep 2017 22:41:54 +0900
parents b18d2b2f18a6
children
line wrap: on
line source

from __future__ import absolute_import

from mercurial.i18n import _
from mercurial import (
    bookmarks,
    destutil,
    error,
    extensions,
    util,
)
from . import topicmap
from .evolvebits import builddependencies

def _destmergebranch(orig, repo, action='merge', sourceset=None,
                     onheadcheck=True, destspace=None):
    # XXX: take destspace into account
    if sourceset is None:
        p1 = repo['.']
    else:
        # XXX: using only the max here is flacky. That code should eventually
        # be updated to take care of the whole sourceset.
        p1 = repo[max(sourceset)]
    top = p1.topic()
    if top:
        revs = repo.revs('topic(%s) - obsolete()', top)
        deps, rdeps = builddependencies(repo, revs)
        heads = [r for r in revs if not rdeps[r]]
        if onheadcheck and p1.rev() not in heads:
            raise error.Abort(_("not at topic head, update or explicit"))

        # prune heads above the source
        otherheads = set(heads)
        pool = set([p1.rev()])
        while pool:
            current = pool.pop()
            otherheads.discard(current)
            pool.update(rdeps[current])
        if not otherheads:
            # nothing to do at the topic level
            bhead = ngtip(repo, p1.branch(), all=True)
            if not bhead:
                raise error.NoMergeDestAbort(_("nothing to merge"))
            elif 1 == len(bhead):
                return bhead[0]
            else:
                msg = _("branch '%s' has %d heads "
                        "- please merge with an explicit rev")
                hint = _("run 'hg heads .' to see heads")
                raise error.ManyMergeDestAbort(msg % (p1.branch(), len(bhead)),
                                               hint=hint)
        elif len(otherheads) == 1:
            return otherheads.pop()
        else:
            msg = _("topic '%s' has %d heads "
                    "- please merge with an explicit rev") % (top, len(heads))
            raise error.ManyMergeDestAbort(msg)
    if len(getattr(orig, 'func_defaults', ())) == 3: # version hg-3.7
        return orig(repo, action, sourceset, onheadcheck)
    if 3 < len(getattr(orig, 'func_defaults', ())): # version hg-3.8 and above
        return orig(repo, action, sourceset, onheadcheck, destspace=destspace)
    else:
        return orig(repo)

def _destupdatetopic(repo, clean, check=None):
    """decide on an update destination from current topic"""
    movemark = node = None
    topic = repo.currenttopic
    revs = repo.revs('.::topic("%s")' % topic)
    if not revs:
        return None, None, None
    node = revs.last()
    if bookmarks.isactivewdirparent(repo):
        movemark = repo['.'].node()
    return node, movemark, None

def desthistedit(orig, ui, repo):
    if not (ui.config('histedit', 'defaultrev', None) is None
            and repo.currenttopic):
        return orig(ui, repo)
    revs = repo.revs('::. and stack()')
    if revs:
        return revs.min()
    return None

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

    tmap = topicmap.gettopicrepo(repo).branchmap()
    if branch not in tmap:
        return []
    elif all:
        return tmap.branchheads(branch)
    else:
        return [tmap.branchtip(branch)]

def modsetup(ui):
    """run a uisetup time to install all destinations wrapping"""
    if util.safehasattr(destutil, '_destmergebranch'):
        extensions.wrapfunction(destutil, '_destmergebranch', _destmergebranch)
    try:
        rebase = extensions.find('rebase')
    except KeyError:
        rebase = None

    # Mercurial 4.4 rename _definesets into _definedestmap
    rebasebefore38 = not util.safehasattr(rebase, '_definesets')
    rebasebefore44 = not util.safehasattr(rebase, '_definedestmap')

    if (util.safehasattr(rebase, '_destrebase')
            # logic not shared with merge yet < hg-3.8
            and rebasebefore38 and rebasebefore44):
        extensions.wrapfunction(rebase, '_destrebase', _destmergebranch)
    if util.safehasattr(destutil, 'destupdatesteps'):
        bridx = destutil.destupdatesteps.index('branch')
        destutil.destupdatesteps.insert(bridx, 'topic')
        destutil.destupdatestepmap['topic'] = _destupdatetopic
    if util.safehasattr(destutil, 'desthistedit'):
        extensions.wrapfunction(destutil, 'desthistedit', desthistedit)