Mercurial > evolve
view hgext3rd/topic/server.py @ 5150:e0c091b199bc stable
topic: extend topic gating to descendant
If a changeset with topic as descendant without topic, we need to exclude them
too when using: topic.server-gate-topic-changesets.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Wed, 04 Mar 2020 17:08:05 +0100 |
parents | 366f6e4108d6 |
children | 515d425c0a05 |
line wrap: on
line source
# topic/server.py - server specific behavior with topic # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from mercurial import ( extensions, repoview, wireprototypes, wireprotov1peer, wireprotov1server, ) try: from mercurial.utils import ( repoviewutil, ) repoviewutil.subsettable except (AttributeError, ImportError): # hg <= 4.8 from mercurial import branchmap as repoviewutil from . import ( common, constants, ) ### Visibility restriction # # Serving draft changesets with topics to clients without topic extension can # confuse them, because they won't see the topic label and will consider them # normal anonymous heads. Instead we have the option to not serve changesets # with topics to clients without topic support. # # To achieve this, we alter the behavior of the standard `heads` commands and # introduce a new `heads` command that only clients with topic will know about. # compat version of the wireprotocommand decorator, taken from evolve compat FILTERNAME = b'served-no-topic' def computeunservedtopic(repo, visibilityexceptions=None): assert not repo.changelog.filteredrevs filteredrevs = repoview.filtertable[b'served'](repo, visibilityexceptions).copy() mutable = repoview.filtertable[b'immutable'](repo, visibilityexceptions) consider = mutable - filteredrevs cl = repo.changelog extrafiltered = set() for r in consider: if cl.changelogrevision(r).extra.get(constants.extrakey, b''): extrafiltered.add(r) if extrafiltered: extrafiltered = set(repo.revs('%ld::%ld', extrafiltered, consider)) filteredrevs = frozenset(filteredrevs | extrafiltered) return filteredrevs def wireprotocommand(name, args=b'', permission=b'pull'): try: from mercurial.wireprotov1server import wireprotocommand except (ImportError, AttributeError): # hg <= 4.6 (b4d85bc122bd) from mercurial.wireproto import wireprotocommand return wireprotocommand(name, args, permission=permission) def wrapheads(orig, repo, proto): """wrap head to hide topic^W draft changeset to old client""" hidetopics = repo.ui.configbool(b'experimental', b'topic.server-gate-topic-changesets') if common.hastopicext(repo) and hidetopics: h = repo.filtered(FILTERNAME).heads() return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b'\n') return orig(repo, proto) def topicheads(repo, proto): """Same as the normal wireprotocol command, but accessing with a different end point.""" h = repo.heads() return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b'\n') def wireprotocaps(orig, repo, proto): """advertise the new topic specific `head` command for client with topic""" caps = orig(repo, proto) if common.hastopicext(repo) and repo.peer().capable(b'topics'): caps.append(b'_exttopics_heads') return caps def setupserver(ui): extensions.wrapfunction(wireprotov1server, 'heads', wrapheads) wireprotov1server.commands.pop(b'heads') wireprotocommand(b'heads', permission=b'pull')(wireprotov1server.heads) wireprotocommand(b'_exttopics_heads', permission=b'pull')(topicheads) extensions.wrapfunction(wireprotov1server, '_capabilities', wireprotocaps) class topicpeerexecutor(wireprotov1peer.peerexecutor): def callcommand(self, command, args): if command == b'heads': if self._peer.capable(b'_exttopics_heads'): command = b'_exttopics_heads' if getattr(self._peer, '_exttopics_heads', None) is None: self._peer._exttopics_heads = self._peer.heads s = super(topicpeerexecutor, self) return s.callcommand(command, args) wireprotov1peer.peerexecutor = topicpeerexecutor if FILTERNAME not in repoview.filtertable: repoview.filtertable[FILTERNAME] = computeunservedtopic repoviewutil.subsettable[FILTERNAME] = b'immutable' repoviewutil.subsettable[b'served'] = FILTERNAME