hgext3rd/evolve/headchecking.py
author Pierre-Yves David <pierre-yves.david@octobus.net>
Mon, 06 Apr 2020 07:26:40 +0200
branchstable
changeset 5273 f560d23639e1
parent 5272 b20d04641c0f
permissions -rw-r--r--
head-checking: ignore obsoleted section when checking head creation locally Same as for the server side check, these do not need to be taken in account.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     1
from __future__ import absolute_import
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     2
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     3
import functools
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     4
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     5
from mercurial import (
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     6
    discovery,
5272
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
     7
    error,
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     8
    extensions,
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
     9
    phases,
5272
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
    10
    scmutil,
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
    11
    util,
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    12
)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    13
5272
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
    14
from mercurial.i18n import _
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
    15
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    16
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    17
from . import (
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    18
    compat,
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    19
    exthelper,
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    20
)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    21
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    22
eh = exthelper.exthelper()
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    23
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    24
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    25
@eh.uisetup
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    26
def uisetup(ui):
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    27
    extensions.wrapfunction(discovery, '_postprocessobsolete', _postprocessobsolete)
5272
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
    28
    extensions.wrapfunction(scmutil, 'enforcesinglehead', enforcesinglehead)
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    29
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    30
def branchinfo(pushop, repo, node):
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    31
    return repo[node].branch()
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    32
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    33
# taken from 7d5455b988ec + branchinfo abstraction.
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    34
def _postprocessobsolete(orig, pushop, futurecommon, candidate_newhs):
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    35
    """post process the list of new heads with obsolescence information
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    36
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    37
    Exists as a sub-function to contain the complexity and allow extensions to
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    38
    experiment with smarter logic.
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    39
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    40
    Returns (newheads, discarded_heads) tuple
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    41
    """
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    42
    pushingmarkerfor = discovery.pushingmarkerfor
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    43
    # known issue
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    44
    #
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    45
    # * We "silently" skip processing on all changeset unknown locally
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    46
    #
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    47
    # * if <nh> is public on the remote, it won't be affected by obsolete
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    48
    #     marker and a new is created
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    49
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    50
    # define various utilities and containers
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    51
    repo = pushop.repo
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    52
    unfi = repo.unfiltered()
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    53
    torev = compat.getgetrev(unfi.changelog)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    54
    public = phases.public
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    55
    getphase = unfi._phasecache.phase
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    56
    ispublic = lambda r: getphase(unfi, r) == public
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    57
    ispushed = lambda n: torev(n) in futurecommon
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    58
    hasoutmarker = functools.partial(pushingmarkerfor, unfi.obsstore, ispushed)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    59
    successorsmarkers = unfi.obsstore.successors
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    60
    newhs = set()  # final set of new heads
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    61
    discarded = set()  # new head of fully replaced branch
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    62
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    63
    localcandidate = set()  # candidate heads known locally
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    64
    unknownheads = set()  # candidate heads unknown locally
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    65
    for h in candidate_newhs:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    66
        if h in unfi:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    67
            localcandidate.add(h)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    68
        else:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    69
            if successorsmarkers.get(h) is not None:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    70
                msg = (
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    71
                    b'checkheads: remote head unknown locally has'
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    72
                    b' local marker: %s\n'
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    73
                )
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    74
                repo.ui.debug(msg % hex(h))
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    75
            unknownheads.add(h)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    76
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    77
    # fast path the simple case
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    78
    if len(localcandidate) == 1:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    79
        return unknownheads | set(candidate_newhs), set()
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    80
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    81
    # actually process branch replacement
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    82
    while localcandidate:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    83
        nh = localcandidate.pop()
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    84
        current_branch = branchinfo(pushop, unfi, nh)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    85
        # run this check early to skip the evaluation of the whole branch
5273
f560d23639e1 head-checking: ignore obsoleted section when checking head creation locally
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5272
diff changeset
    86
        if ispublic(torev(nh)) or not unfi[nh].obsolete():
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    87
            newhs.add(nh)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    88
            continue
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    89
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    90
        # Get all revs/nodes on the branch exclusive to this head
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    91
        # (already filtered heads are "ignored"))
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    92
        branchrevs = unfi.revs(
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    93
            b'only(%n, (%ln+%ln))', nh, localcandidate, newhs
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    94
        )
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    95
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    96
        branchnodes = []
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    97
        for r in branchrevs:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    98
            ctx = unfi[r]
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
    99
            if ctx.branch() == current_branch:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   100
                branchnodes.append(ctx.node())
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   101
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   102
        # The branch won't be hidden on the remote if
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   103
        # * any part of it is public,
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   104
        # * any part of it is considered part of the result by previous logic,
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   105
        # * if we have no markers to push to obsolete it.
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   106
        if (
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   107
            any(ispublic(torev(n)) for n in branchnodes)
5273
f560d23639e1 head-checking: ignore obsoleted section when checking head creation locally
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5272
diff changeset
   108
            or (any(torev(n) in futurecommon and not unfi[n].obsolete() for n in branchnodes))
f560d23639e1 head-checking: ignore obsoleted section when checking head creation locally
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5272
diff changeset
   109
            # XXX `hasoutmarker` does not guarantee the changeset to be
f560d23639e1 head-checking: ignore obsoleted section when checking head creation locally
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5272
diff changeset
   110
            # obsolete, nor obsoleted by the push.
5268
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   111
            or any(not hasoutmarker(n) for n in branchnodes)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   112
        ):
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   113
            newhs.add(nh)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   114
        else:
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   115
            # note: there is a corner case if there is a merge in the branch.
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   116
            # we might end up with -more- heads.  However, these heads are not
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   117
            # "added" by the push, but more by the "removal" on the remote so I
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   118
            # think is a okay to ignore them,
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   119
            discarded.add(nh)
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   120
    newhs |= unknownheads
11c359b4071d head-checking: backport fix from 7d5455b988ec
Pierre-Yves David <pierre-yves.david@octobus.net>
parents:
diff changeset
   121
    return newhs, discarded
5272
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   122
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   123
def _get_branch_name(ctx):
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   124
    # make it easy for extension with the branch logic there
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   125
    branch = ctx.branch()
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   126
    if util.safehasattr(ctx, 'topic'):
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   127
        topic = ctx.topic()
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   128
        if topic:
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   129
            branch = "%s:%s" % (branch, topic)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   130
    return branch
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   131
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   132
def _filter_obsolete_heads(repo, heads):
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   133
    """filter heads to return non-obsolete ones
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   134
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   135
    Given a list of heads (on the same named branch) return a new list of heads
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   136
    where the obsolete part have been skimmed out.
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   137
    """
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   138
    new_heads = []
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   139
    old_heads = heads[:]
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   140
    while old_heads:
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   141
        rh = old_heads.pop()
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   142
        ctx = repo[rh]
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   143
        current_name = _get_branch_name(ctx)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   144
        # run this check early to skip the evaluation of the whole branch
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   145
        if not ctx.obsolete():
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   146
            new_heads.append(rh)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   147
            continue
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   148
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   149
        # Get all revs/nodes on the branch exclusive to this head
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   150
        # (already filtered heads are "ignored"))
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   151
        sections_revs = repo.revs(
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   152
            b'only(%d, (%ld+%ld))', rh, old_heads, new_heads,
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   153
        )
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   154
        keep_revs = []
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   155
        for r in sections_revs:
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   156
            ctx = repo[r]
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   157
            if ctx.obsolete():
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   158
                continue
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   159
            if _get_branch_name(ctx) != current_name:
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   160
                continue
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   161
            keep_revs.append(r)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   162
        for h in repo.revs(b'heads(%ld and (::%ld))', sections_revs, keep_revs):
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   163
            new_heads.append(h)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   164
    new_heads.sort()
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   165
    return new_heads
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   166
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   167
def enforcesinglehead(orig, repo, tr, desc, accountclosed=False):
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   168
    """check that no named branch has multiple heads"""
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   169
    nodesummaries = scmutil.nodesummaries
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   170
    if desc in (b'strip', b'repair'):
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   171
        # skip the logic during strip
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   172
        return
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   173
    visible = repo.filtered(b'visible')
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   174
    # possible improvement: we could restrict the check to affected branch
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   175
    bm = visible.branchmap()
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   176
    cl = repo.changelog
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   177
    to_rev = cl.rev
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   178
    to_node = cl.node
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   179
    for name in bm:
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   180
        all_heads = bm.branchheads(name, closed=accountclosed)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   181
        all_heads = [to_rev(n) for n in all_heads]
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   182
        heads = _filter_obsolete_heads(repo, all_heads)
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   183
        heads = [to_node(r) for r in heads]
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   184
        if len(heads) > 1:
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   185
            msg = _(b'rejecting multiple heads on branch "%s"')
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   186
            msg %= name
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   187
            hint = _(b'%d heads: %s')
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   188
            hint %= (len(heads), nodesummaries(repo, heads))
b20d04641c0f head-checking: ignore obsolete section when checking for single heads
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 5268
diff changeset
   189
            raise error.Abort(msg, hint=hint)