checkheads: drop upstreamed code
authorPierre-Yves David <pierre-yves.david@octobus.net>
Thu, 22 Mar 2018 10:35:27 +0100
changeset 3605 f60afeb28192
parent 3604 d24ba168a532
child 3606 9f2ba8ef517b
checkheads: drop upstreamed code Mercurial 4.2 has all the code that used to live in the evolve extensions so we can drop it now.
hgext3rd/evolve/__init__.py
hgext3rd/evolve/checkheads.py
--- a/hgext3rd/evolve/__init__.py	Thu Mar 22 10:34:44 2018 +0100
+++ b/hgext3rd/evolve/__init__.py	Thu Mar 22 10:35:27 2018 +0100
@@ -299,7 +299,6 @@
 from mercurial.node import nullid
 
 from . import (
-    checkheads,
     compat,
     debugcmd,
     cmdrewrite,
@@ -357,7 +356,6 @@
 eh.merge(debugcmd.eh)
 eh.merge(evolvecmd.eh)
 eh.merge(obsexchange.eh)
-eh.merge(checkheads.eh)
 eh.merge(safeguard.eh)
 eh.merge(obscache.eh)
 eh.merge(obshistory.eh)
--- a/hgext3rd/evolve/checkheads.py	Thu Mar 22 10:34:44 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-# Code dedicated to the postprocessing new heads check with obsolescence
-#
-# Copyright 2017 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-
-import functools
-
-from mercurial import (
-    discovery,
-    error,
-    extensions,
-    node as nodemod,
-    phases,
-    util,
-)
-
-from mercurial.i18n import _
-
-from . import exthelper
-
-nullid = nodemod.nullid
-short = nodemod.short
-_headssummary = discovery._headssummary
-_oldheadssummary = discovery._oldheadssummary
-_nowarnheads = discovery._nowarnheads
-
-eh = exthelper.exthelper()
-
-@eh.uisetup
-def setupcheckheadswrapper(ui):
-    if not util.safehasattr(discovery, '_postprocessobsolete'):
-        # hg-4.2+ has all the code natively
-        extensions.wrapfunction(discovery, 'checkheads',
-                                checkheadsfulloverlay)
-
-# have dedicated wrapper to keep the rest as close as core as possible
-def checkheadsfulloverlay(orig, pushop):
-    if pushop.repo.obsstore:
-        return corecheckheads(pushop)
-    else:
-        return orig(pushop)
-
-# copied from mercurial.discovery.checkheads as in a5bad127128d (4.1)
-#
-# The only differences are:
-# * the _postprocessobsolete section have been extracted,
-# * minor test adjustment to please flake8
-def corecheckheads(pushop):
-    """Check that a push won't add any outgoing head
-
-    raise Abort error and display ui message as needed.
-    """
-
-    repo = pushop.repo.unfiltered()
-    remote = pushop.remote
-    outgoing = pushop.outgoing
-    remoteheads = pushop.remoteheads
-    newbranch = pushop.newbranch
-    inc = bool(pushop.incoming)
-
-    # Check for each named branch if we're creating new remote heads.
-    # To be a remote head after push, node must be either:
-    # - unknown locally
-    # - a local outgoing head descended from update
-    # - a remote head that's known locally and not
-    #   ancestral to an outgoing head
-    if remoteheads == [nullid]:
-        # remote is empty, nothing to check.
-        return
-
-    if remote.capable('branchmap'):
-        headssum = _headssummary(repo, remote, outgoing)
-    else:
-        headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
-    newbranches = [branch for branch, heads in headssum.iteritems()
-                   if heads[0] is None]
-    # 1. Check for new branches on the remote.
-    if newbranches and not newbranch:  # new branch requires --new-branch
-        branchnames = ', '.join(sorted(newbranches))
-        raise error.Abort(_("push creates new remote branches: %s!")
-                          % branchnames,
-                          hint=_("use 'hg push --new-branch' to create"
-                                 " new remote branches"))
-
-    # 2. Find heads that we need not warn about
-    nowarnheads = _nowarnheads(pushop)
-
-    # 3. Check for new heads.
-    # If there are more heads after the push than before, a suitable
-    # error message, depending on unsynced status, is displayed.
-    errormsg = None
-    # If there is no obsstore, allfuturecommon won't be used, so no
-    # need to compute it.
-    if repo.obsstore:
-        allmissing = set(outgoing.missing)
-        cctx = repo.set('%ld', outgoing.common)
-        allfuturecommon = set(c.node() for c in cctx)
-        allfuturecommon.update(allmissing)
-    for branch, heads in sorted(headssum.iteritems()):
-        remoteheads, newheads, unsyncedheads = heads
-        candidate_newhs = set(newheads)
-        # add unsynced data
-        if remoteheads is None:
-            oldhs = set()
-        else:
-            oldhs = set(remoteheads)
-        oldhs.update(unsyncedheads)
-        candidate_newhs.update(unsyncedheads)
-        dhs = None # delta heads, the new heads on branch
-        if not repo.obsstore:
-            discardedheads = set()
-            newhs = candidate_newhs
-        else:
-            newhs, discardedheads = _postprocessobsolete(pushop,
-                                                         allfuturecommon,
-                                                         candidate_newhs)
-        unsynced = sorted(h for h in unsyncedheads if h not in discardedheads)
-        if unsynced:
-            if None in unsynced:
-                # old remote, no heads data
-                heads = None
-            elif len(unsynced) <= 4 or repo.ui.verbose:
-                heads = ' '.join(short(h) for h in unsynced)
-            else:
-                heads = (' '.join(short(h) for h in unsynced[:4]) +
-                         ' ' + _("and %s others") % (len(unsynced) - 4))
-            if heads is None:
-                repo.ui.status(_("remote has heads that are "
-                                 "not known locally\n"))
-            elif branch is None:
-                repo.ui.status(_("remote has heads that are "
-                                 "not known locally: %s\n") % heads)
-            else:
-                repo.ui.status(_("remote has heads on branch '%s' that are "
-                                 "not known locally: %s\n") % (branch, heads))
-        if remoteheads is None:
-            if len(newhs) > 1:
-                dhs = list(newhs)
-                if errormsg is None:
-                    errormsg = (_("push creates new branch '%s' "
-                                  "with multiple heads") % (branch))
-                    hint = _("merge or"
-                             " see 'hg help push' for details about"
-                             " pushing new heads")
-        elif len(newhs) > len(oldhs):
-            # remove bookmarked or existing remote heads from the new heads list
-            dhs = sorted(newhs - nowarnheads - oldhs)
-        if dhs:
-            if errormsg is None:
-                if branch not in ('default', None):
-                    errormsg = _("push creates new remote head %s "
-                                 "on branch '%s'!") % (short(dhs[0]), branch)
-                elif repo[dhs[0]].bookmarks():
-                    errormsg = (_("push creates new remote head %s "
-                                  "with bookmark '%s'!")
-                                % (short(dhs[0]), repo[dhs[0]].bookmarks()[0]))
-                else:
-                    errormsg = _("push creates new remote head %s!"
-                                 ) % short(dhs[0])
-                if unsyncedheads:
-                    hint = _("pull and merge or"
-                             " see 'hg help push' for details about"
-                             " pushing new heads")
-                else:
-                    hint = _("merge or"
-                             " see 'hg help push' for details about"
-                             " pushing new heads")
-            if branch is None:
-                repo.ui.note(_("new remote heads:\n"))
-            else:
-                repo.ui.note(_("new remote heads on branch '%s':\n") % branch)
-            for h in dhs:
-                repo.ui.note((" %s\n") % short(h))
-    if errormsg:
-        raise error.Abort(errormsg, hint=hint)
-
-def _postprocessobsolete(pushop, futurecommon, candidate):
-    """post process the list of new heads with obsolescence information
-
-    Exist as a subfunction to contains the complexity and allow extensions to
-    experiment with smarter logic.
-    Returns (newheads, discarded_heads) tuple
-    """
-    # remove future heads which are actually obsoleted by another
-    # pushed element:
-    #
-    # known issue
-    #
-    # * We "silently" skip processing on all changeset unknown locally
-    #
-    # * if <nh> is public on the remote, it won't be affected by obsolete
-    #     marker and a new is created
-    repo = pushop.repo
-    unfi = repo.unfiltered()
-    tonode = unfi.changelog.node
-    public = phases.public
-    getphase = unfi._phasecache.phase
-    ispublic = (lambda r: getphase(unfi, r) == public)
-    hasoutmarker = functools.partial(pushingmarkerfor, unfi.obsstore, futurecommon)
-    successorsmarkers = unfi.obsstore.successors
-    newhs = set()
-    discarded = set()
-    # I leave the print in the code because they are so handy at debugging
-    # and I keep getting back to this piece of code.
-    #
-    localcandidate = set()
-    unknownheads = set()
-    for h in candidate:
-        if h in unfi:
-            localcandidate.add(h)
-        else:
-            if successorsmarkers.get(h) is not None:
-                msg = ('checkheads: remote head unknown locally has'
-                       ' local marker: %s\n')
-                repo.ui.debug(msg % nodemod.hex(h))
-            unknownheads.add(h)
-    if len(localcandidate) == 1:
-        return unknownheads | set(candidate), set()
-    while localcandidate:
-        nh = localcandidate.pop()
-        # run this check early to skip the revset on the whole branch
-        if (nh in futurecommon
-                or unfi[nh].phase() <= public):
-            newhs.add(nh)
-            continue
-        # XXX there is a corner case if there is a merge in the branch. we
-        # might end up with -more- heads.  However, these heads are not "added"
-        # by the push, but more by the "removal" on the remote so I think is a
-        # okay to ignore them,
-        branchrevs = unfi.revs('only(%n, (%ln+%ln))',
-                               nh, localcandidate, newhs)
-        branchnodes = [tonode(r) for r in branchrevs]
-
-        # The branch will still exist on the remote if
-        # * any part of it is public,
-        # * any part of it is considered part of the result by previous logic,
-        # * if we have no markers to push to obsolete it.
-        if (any(ispublic(r) for r in branchrevs)
-                or any(n in futurecommon for n in branchnodes)
-                or any(not hasoutmarker(n) for n in branchnodes)):
-            newhs.add(nh)
-        else:
-            discarded.add(nh)
-    newhs |= unknownheads
-    return newhs, discarded
-
-def pushingmarkerfor(obsstore, pushset, node):
-    """True if some markers are to be pushed for node
-
-    We cannot just look in to the pushed obsmarkers from the pushop because
-    discover might have filtered relevant markers. In addition listing all
-    markers relevant to all changeset in the pushed set would be too expensive.
-
-    The is probably some cache opportunity in this function. but it would
-    requires a two dimentions stack.
-    """
-    successorsmarkers = obsstore.successors
-    stack = [node]
-    seen = set(stack)
-    while stack:
-        current = stack.pop()
-        if current in pushset:
-            return True
-        markers = successorsmarkers.get(current, ())
-        # markers fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents')
-        for m in markers:
-            nexts = m[1] # successors
-            if not nexts: # this is a prune marker
-                nexts = m[5] # parents
-            for n in nexts:
-                if n not in seen:
-                    seen.add(n)
-                    stack.append(n)
-    return False