Mercurial > evolve
comparison hgext3rd/topic/server.py @ 6548:445240ccb701
topic: add experimental.tns-default-pull-namespaces config option
This config option controls what topic namespaces get pulled by default.
The current default option is '*', which means all namespaces get pulled.
author | Anton Shestakov <av6@dwimlabs.net> |
---|---|
date | Thu, 27 Jul 2023 16:39:43 -0300 |
parents | a87abe69a2f8 |
children | 2d3771d61068 |
comparison
equal
deleted
inserted
replaced
6547:d13cfd9eb6c0 | 6548:445240ccb701 |
---|---|
1 # topic/server.py - server specific behavior with topic | 1 # topic/server.py - server specific behavior with topic |
2 # | 2 # |
3 # This software may be used and distributed according to the terms of the | 3 # This software may be used and distributed according to the terms of the |
4 # GNU General Public License version 2 or any later version. | 4 # GNU General Public License version 2 or any later version. |
5 from mercurial.i18n import _ | |
6 | |
5 from mercurial import ( | 7 from mercurial import ( |
6 branchmap, | 8 branchmap, |
9 error, | |
7 extensions, | 10 extensions, |
11 localrepo, | |
8 repoview, | 12 repoview, |
9 wireprototypes, | 13 wireprototypes, |
10 wireprotov1peer, | 14 wireprotov1peer, |
11 wireprotov1server, | 15 wireprotov1server, |
12 ) | 16 ) |
56 def topicheads(repo, proto): | 60 def topicheads(repo, proto): |
57 """Same as the normal wireprotocol command, but accessing with a different end point.""" | 61 """Same as the normal wireprotocol command, but accessing with a different end point.""" |
58 h = repo.heads() | 62 h = repo.heads() |
59 return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b'\n') | 63 return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b'\n') |
60 | 64 |
65 def tns_heads(repo, proto, namespaces): | |
66 """wireprotocol command to filter heads based on topic namespaces""" | |
67 if not common.hastopicext(repo): | |
68 return topicheads(repo, proto) | |
69 | |
70 namespaces = wireprototypes.decodelist(namespaces) | |
71 if b'*' in namespaces: | |
72 # pulling all topic namespaces, all changesets are visible | |
73 h = repo.heads() | |
74 else: | |
75 # only changesets in the selected topic namespaces are visible | |
76 h = [] | |
77 for branch, nodes in repo.branchmaptns().items(): | |
78 namedbranch, tns, topic = common.parsefqbn(branch) | |
79 if tns == b'none' or tns in namespaces: | |
80 h.extend(nodes) | |
81 return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + b'\n') | |
82 | |
61 def wireprotocaps(orig, repo, proto): | 83 def wireprotocaps(orig, repo, proto): |
62 """advertise the new topic specific `head` command for client with topic""" | 84 """advertise the new topic specific `head` command for client with topic""" |
63 caps = orig(repo, proto) | 85 caps = orig(repo, proto) |
64 if common.hastopicext(repo) and repo.peer().capable(b'topics'): | 86 if common.hastopicext(repo) and repo.peer().capable(b'topics'): |
65 caps.append(b'_exttopics_heads') | 87 caps.append(b'_exttopics_heads') |
68 elif repo.ui.configbool(b'experimental', b'topic.publish-bare-branch'): | 90 elif repo.ui.configbool(b'experimental', b'topic.publish-bare-branch'): |
69 mode = b'auto' | 91 mode = b'auto' |
70 else: | 92 else: |
71 mode = b'none' | 93 mode = b'none' |
72 caps.append(b'ext-topics-publish=%s' % mode) | 94 caps.append(b'ext-topics-publish=%s' % mode) |
95 caps.append(b'ext-topics-tns-heads') | |
73 return caps | 96 return caps |
74 | 97 |
75 def setupserver(ui): | 98 def setupserver(ui): |
76 extensions.wrapfunction(wireprotov1server, 'heads', wrapheads) | 99 extensions.wrapfunction(wireprotov1server, 'heads', wrapheads) |
77 wireprotov1server.commands.pop(b'heads') | 100 wireprotov1server.commands.pop(b'heads') |
78 wireprotov1server.wireprotocommand(b'heads', permission=b'pull')(wireprotov1server.heads) | 101 wireprotov1server.wireprotocommand(b'heads', permission=b'pull')(wireprotov1server.heads) |
79 wireprotov1server.wireprotocommand(b'_exttopics_heads', permission=b'pull')(topicheads) | 102 wireprotov1server.wireprotocommand(b'_exttopics_heads', permission=b'pull')(topicheads) |
103 wireprotov1server.wireprotocommand(b'tns_heads', b'namespaces', permission=b'pull')(tns_heads) | |
80 extensions.wrapfunction(wireprotov1server, '_capabilities', wireprotocaps) | 104 extensions.wrapfunction(wireprotov1server, '_capabilities', wireprotocaps) |
105 | |
106 class tnspeer(wireprotov1peer.wirepeer): | |
107 @wireprotov1peer.batchable | |
108 def tns_heads(self, namespaces): | |
109 def decode(d): | |
110 try: | |
111 return wireprototypes.decodelist(d[:-1]) | |
112 except ValueError: | |
113 self._abort(error.ResponseError(_(b"unexpected response:"), d)) | |
114 | |
115 return {b'namespaces': wireprototypes.encodelist(namespaces)}, decode | |
116 | |
117 wireprotov1peer.wirepeer = tnspeer | |
81 | 118 |
82 class topicpeerexecutor(wireprotov1peer.peerexecutor): | 119 class topicpeerexecutor(wireprotov1peer.peerexecutor): |
83 | 120 |
84 def callcommand(self, command, args): | 121 def callcommand(self, command, args): |
85 if command == b'heads': | 122 if command == b'heads': |
86 if self._peer.capable(b'_exttopics_heads'): | 123 if self._peer.capable(b'ext-topics-tns-heads'): |
124 command = b'tns_heads' | |
125 args[b'namespaces'] = self._peer.ui.configlist(b'experimental', b'tns-default-pull-namespaces', [b'*']) | |
126 elif self._peer.capable(b'_exttopics_heads'): | |
87 command = b'_exttopics_heads' | 127 command = b'_exttopics_heads' |
88 if getattr(self._peer, '_exttopics_heads', None) is None: | 128 if getattr(self._peer, '_exttopics_heads', None) is None: |
89 self._peer._exttopics_heads = self._peer.heads | 129 self._peer._exttopics_heads = self._peer.heads |
90 s = super(topicpeerexecutor, self) | 130 s = super(topicpeerexecutor, self) |
91 return s.callcommand(command, args) | 131 return s.callcommand(command, args) |
92 | 132 |
93 wireprotov1peer.peerexecutor = topicpeerexecutor | 133 wireprotov1peer.peerexecutor = topicpeerexecutor |
94 | 134 |
135 class topiccommandexecutor(localrepo.localcommandexecutor): | |
136 def callcommand(self, command, args): | |
137 if command == b'heads': | |
138 if self._peer.capable(b'ext-topics-tns-heads'): | |
139 command = b'tns_heads' | |
140 args[b'namespaces'] = self._peer.ui.configlist(b'experimental', b'tns-default-pull-namespaces', [b'*']) | |
141 s = super(topiccommandexecutor, self) | |
142 return s.callcommand(command, args) | |
143 | |
144 localrepo.localcommandexecutor = topiccommandexecutor | |
145 | |
95 if FILTERNAME not in repoview.filtertable: | 146 if FILTERNAME not in repoview.filtertable: |
96 repoview.filtertable[FILTERNAME] = computeunservedtopic | 147 repoview.filtertable[FILTERNAME] = computeunservedtopic |
97 # hg <= 4.9 (caebe5e7f4bd) | 148 # hg <= 4.9 (caebe5e7f4bd) |
98 branchmap.subsettable[FILTERNAME] = b'immutable' | 149 branchmap.subsettable[FILTERNAME] = b'immutable' |
99 branchmap.subsettable[b'served'] = FILTERNAME | 150 branchmap.subsettable[b'served'] = FILTERNAME |