Mercurial > hg
comparison hgext/fastannotate/protocol.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 876494fd967d |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
20 ) | 20 ) |
21 from . import context | 21 from . import context |
22 | 22 |
23 # common | 23 # common |
24 | 24 |
25 | |
25 def _getmaster(ui): | 26 def _getmaster(ui): |
26 """get the mainbranch, and enforce it is set""" | 27 """get the mainbranch, and enforce it is set""" |
27 master = ui.config('fastannotate', 'mainbranch') | 28 master = ui.config('fastannotate', 'mainbranch') |
28 if not master: | 29 if not master: |
29 raise error.Abort(_('fastannotate.mainbranch is required ' | 30 raise error.Abort( |
30 'for both the client and the server')) | 31 _( |
32 'fastannotate.mainbranch is required ' | |
33 'for both the client and the server' | |
34 ) | |
35 ) | |
31 return master | 36 return master |
32 | 37 |
38 | |
33 # server-side | 39 # server-side |
40 | |
34 | 41 |
35 def _capabilities(orig, repo, proto): | 42 def _capabilities(orig, repo, proto): |
36 result = orig(repo, proto) | 43 result = orig(repo, proto) |
37 result.append('getannotate') | 44 result.append('getannotate') |
38 return result | 45 return result |
46 | |
39 | 47 |
40 def _getannotate(repo, proto, path, lastnode): | 48 def _getannotate(repo, proto, path, lastnode): |
41 # output: | 49 # output: |
42 # FILE := vfspath + '\0' + str(size) + '\0' + content | 50 # FILE := vfspath + '\0' + str(size) + '\0' + content |
43 # OUTPUT := '' | FILE + OUTPUT | 51 # OUTPUT := '' | FILE + OUTPUT |
44 result = '' | 52 result = '' |
45 buildondemand = repo.ui.configbool('fastannotate', 'serverbuildondemand', | 53 buildondemand = repo.ui.configbool( |
46 True) | 54 'fastannotate', 'serverbuildondemand', True |
55 ) | |
47 with context.annotatecontext(repo, path) as actx: | 56 with context.annotatecontext(repo, path) as actx: |
48 if buildondemand: | 57 if buildondemand: |
49 # update before responding to the client | 58 # update before responding to the client |
50 master = _getmaster(repo.ui) | 59 master = _getmaster(repo.ui) |
51 try: | 60 try: |
55 # non-fast-forward move or corrupted. rebuild automically. | 64 # non-fast-forward move or corrupted. rebuild automically. |
56 actx.rebuild() | 65 actx.rebuild() |
57 try: | 66 try: |
58 actx.annotate(master, master) | 67 actx.annotate(master, master) |
59 except Exception: | 68 except Exception: |
60 actx.rebuild() # delete files | 69 actx.rebuild() # delete files |
61 finally: | 70 finally: |
62 # although the "with" context will also do a close/flush, we | 71 # although the "with" context will also do a close/flush, we |
63 # need to do it early so we can send the correct respond to | 72 # need to do it early so we can send the correct respond to |
64 # client. | 73 # client. |
65 actx.close() | 74 actx.close() |
76 vfsbaselen = len(repo.vfs.base + '/') | 85 vfsbaselen = len(repo.vfs.base + '/') |
77 relpath = p[vfsbaselen:] | 86 relpath = p[vfsbaselen:] |
78 result += '%s\0%d\0%s' % (relpath, len(content), content) | 87 result += '%s\0%d\0%s' % (relpath, len(content), content) |
79 return result | 88 return result |
80 | 89 |
90 | |
81 def _registerwireprotocommand(): | 91 def _registerwireprotocommand(): |
82 if 'getannotate' in wireprotov1server.commands: | 92 if 'getannotate' in wireprotov1server.commands: |
83 return | 93 return |
84 wireprotov1server.wireprotocommand( | 94 wireprotov1server.wireprotocommand('getannotate', 'path lastnode')( |
85 'getannotate', 'path lastnode')(_getannotate) | 95 _getannotate |
96 ) | |
97 | |
86 | 98 |
87 def serveruisetup(ui): | 99 def serveruisetup(ui): |
88 _registerwireprotocommand() | 100 _registerwireprotocommand() |
89 extensions.wrapfunction(wireprotov1server, '_capabilities', _capabilities) | 101 extensions.wrapfunction(wireprotov1server, '_capabilities', _capabilities) |
90 | 102 |
103 | |
91 # client-side | 104 # client-side |
105 | |
92 | 106 |
93 def _parseresponse(payload): | 107 def _parseresponse(payload): |
94 result = {} | 108 result = {} |
95 i = 0 | 109 i = 0 |
96 l = len(payload) - 1 | 110 l = len(payload) - 1 |
97 state = 0 # 0: vfspath, 1: size | 111 state = 0 # 0: vfspath, 1: size |
98 vfspath = size = '' | 112 vfspath = size = '' |
99 while i < l: | 113 while i < l: |
100 ch = payload[i:i + 1] | 114 ch = payload[i : i + 1] |
101 if ch == '\0': | 115 if ch == '\0': |
102 if state == 1: | 116 if state == 1: |
103 result[vfspath] = payload[i + 1:i + 1 + int(size)] | 117 result[vfspath] = payload[i + 1 : i + 1 + int(size)] |
104 i += int(size) | 118 i += int(size) |
105 state = 0 | 119 state = 0 |
106 vfspath = size = '' | 120 vfspath = size = '' |
107 elif state == 0: | 121 elif state == 0: |
108 state = 1 | 122 state = 1 |
111 size += ch | 125 size += ch |
112 elif state == 0: | 126 elif state == 0: |
113 vfspath += ch | 127 vfspath += ch |
114 i += 1 | 128 i += 1 |
115 return result | 129 return result |
130 | |
116 | 131 |
117 def peersetup(ui, peer): | 132 def peersetup(ui, peer): |
118 class fastannotatepeer(peer.__class__): | 133 class fastannotatepeer(peer.__class__): |
119 @wireprotov1peer.batchable | 134 @wireprotov1peer.batchable |
120 def getannotate(self, path, lastnode=None): | 135 def getannotate(self, path, lastnode=None): |
124 else: | 139 else: |
125 args = {'path': path, 'lastnode': lastnode or ''} | 140 args = {'path': path, 'lastnode': lastnode or ''} |
126 f = wireprotov1peer.future() | 141 f = wireprotov1peer.future() |
127 yield args, f | 142 yield args, f |
128 yield _parseresponse(f.value) | 143 yield _parseresponse(f.value) |
144 | |
129 peer.__class__ = fastannotatepeer | 145 peer.__class__ = fastannotatepeer |
146 | |
130 | 147 |
131 @contextlib.contextmanager | 148 @contextlib.contextmanager |
132 def annotatepeer(repo): | 149 def annotatepeer(repo): |
133 ui = repo.ui | 150 ui = repo.ui |
134 | 151 |
135 remotepath = ui.expandpath( | 152 remotepath = ui.expandpath( |
136 ui.config('fastannotate', 'remotepath', 'default')) | 153 ui.config('fastannotate', 'remotepath', 'default') |
154 ) | |
137 peer = hg.peer(ui, {}, remotepath) | 155 peer = hg.peer(ui, {}, remotepath) |
138 | 156 |
139 try: | 157 try: |
140 yield peer | 158 yield peer |
141 finally: | 159 finally: |
142 peer.close() | 160 peer.close() |
161 | |
143 | 162 |
144 def clientfetch(repo, paths, lastnodemap=None, peer=None): | 163 def clientfetch(repo, paths, lastnodemap=None, peer=None): |
145 """download annotate cache from the server for paths""" | 164 """download annotate cache from the server for paths""" |
146 if not paths: | 165 if not paths: |
147 return | 166 return |
156 ui = repo.ui | 175 ui = repo.ui |
157 results = [] | 176 results = [] |
158 with peer.commandexecutor() as batcher: | 177 with peer.commandexecutor() as batcher: |
159 ui.debug('fastannotate: requesting %d files\n' % len(paths)) | 178 ui.debug('fastannotate: requesting %d files\n' % len(paths)) |
160 for p in paths: | 179 for p in paths: |
161 results.append(batcher.callcommand( | 180 results.append( |
162 'getannotate', | 181 batcher.callcommand( |
163 {'path': p, 'lastnode':lastnodemap.get(p)})) | 182 'getannotate', {'path': p, 'lastnode': lastnodemap.get(p)} |
183 ) | |
184 ) | |
164 | 185 |
165 for result in results: | 186 for result in results: |
166 r = result.result() | 187 r = result.result() |
167 # TODO: pconvert these paths on the server? | 188 # TODO: pconvert these paths on the server? |
168 r = {util.pconvert(p): v for p, v in r.iteritems()} | 189 r = {util.pconvert(p): v for p, v in r.iteritems()} |
169 for path in sorted(r): | 190 for path in sorted(r): |
170 # ignore malicious paths | 191 # ignore malicious paths |
171 if (not path.startswith('fastannotate/') | 192 if not path.startswith('fastannotate/') or '/../' in ( |
172 or '/../' in (path + '/')): | 193 path + '/' |
194 ): | |
173 ui.debug('fastannotate: ignored malicious path %s\n' % path) | 195 ui.debug('fastannotate: ignored malicious path %s\n' % path) |
174 continue | 196 continue |
175 content = r[path] | 197 content = r[path] |
176 if ui.debugflag: | 198 if ui.debugflag: |
177 ui.debug('fastannotate: writing %d bytes to %s\n' | 199 ui.debug( |
178 % (len(content), path)) | 200 'fastannotate: writing %d bytes to %s\n' |
201 % (len(content), path) | |
202 ) | |
179 repo.vfs.makedirs(os.path.dirname(path)) | 203 repo.vfs.makedirs(os.path.dirname(path)) |
180 with repo.vfs(path, 'wb') as f: | 204 with repo.vfs(path, 'wb') as f: |
181 f.write(content) | 205 f.write(content) |
206 | |
182 | 207 |
183 def _filterfetchpaths(repo, paths): | 208 def _filterfetchpaths(repo, paths): |
184 """return a subset of paths whose history is long and need to fetch linelog | 209 """return a subset of paths whose history is long and need to fetch linelog |
185 from the server. works with remotefilelog and non-remotefilelog repos. | 210 from the server. works with remotefilelog and non-remotefilelog repos. |
186 """ | 211 """ |
191 result = [] | 216 result = [] |
192 for path in paths: | 217 for path in paths: |
193 try: | 218 try: |
194 if len(repo.file(path)) >= threshold: | 219 if len(repo.file(path)) >= threshold: |
195 result.append(path) | 220 result.append(path) |
196 except Exception: # file not found etc. | 221 except Exception: # file not found etc. |
197 result.append(path) | 222 result.append(path) |
198 | 223 |
199 return result | 224 return result |
225 | |
200 | 226 |
201 def localreposetup(ui, repo): | 227 def localreposetup(ui, repo): |
202 class fastannotaterepo(repo.__class__): | 228 class fastannotaterepo(repo.__class__): |
203 def prefetchfastannotate(self, paths, peer=None): | 229 def prefetchfastannotate(self, paths, peer=None): |
204 master = _getmaster(self.ui) | 230 master = _getmaster(self.ui) |
213 if needupdatepaths: | 239 if needupdatepaths: |
214 clientfetch(self, needupdatepaths, lastnodemap, peer) | 240 clientfetch(self, needupdatepaths, lastnodemap, peer) |
215 except Exception as ex: | 241 except Exception as ex: |
216 # could be directory not writable or so, not fatal | 242 # could be directory not writable or so, not fatal |
217 self.ui.debug('fastannotate: prefetch failed: %r\n' % ex) | 243 self.ui.debug('fastannotate: prefetch failed: %r\n' % ex) |
244 | |
218 repo.__class__ = fastannotaterepo | 245 repo.__class__ = fastannotaterepo |
246 | |
219 | 247 |
220 def clientreposetup(ui, repo): | 248 def clientreposetup(ui, repo): |
221 _registerwireprotocommand() | 249 _registerwireprotocommand() |
222 if repo.local(): | 250 if repo.local(): |
223 localreposetup(ui, repo) | 251 localreposetup(ui, repo) |