comparison mercurial/wireprototypes.py @ 43077:687b865b95ad

formatting: byteify all mercurial/ and hgext/ string literals Done with python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py') black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**') # skip-blame mass-reformatting only Differential Revision: https://phab.mercurial-scm.org/D6972
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:48:39 -0400
parents 2372284d9457
children c59eb1560c44
comparison
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
17 ) 17 )
18 from .interfaces import util as interfaceutil 18 from .interfaces import util as interfaceutil
19 from .utils import compression 19 from .utils import compression
20 20
21 # Names of the SSH protocol implementations. 21 # Names of the SSH protocol implementations.
22 SSHV1 = 'ssh-v1' 22 SSHV1 = b'ssh-v1'
23 # These are advertised over the wire. Increment the counters at the end 23 # These are advertised over the wire. Increment the counters at the end
24 # to reflect BC breakages. 24 # to reflect BC breakages.
25 SSHV2 = 'exp-ssh-v2-0003' 25 SSHV2 = b'exp-ssh-v2-0003'
26 HTTP_WIREPROTO_V2 = 'exp-http-v2-0003' 26 HTTP_WIREPROTO_V2 = b'exp-http-v2-0003'
27 27
28 NARROWCAP = 'exp-narrow-1' 28 NARROWCAP = b'exp-narrow-1'
29 ELLIPSESCAP1 = 'exp-ellipses-1' 29 ELLIPSESCAP1 = b'exp-ellipses-1'
30 ELLIPSESCAP = 'exp-ellipses-2' 30 ELLIPSESCAP = b'exp-ellipses-2'
31 SUPPORTED_ELLIPSESCAP = (ELLIPSESCAP1, ELLIPSESCAP) 31 SUPPORTED_ELLIPSESCAP = (ELLIPSESCAP1, ELLIPSESCAP)
32 32
33 # All available wire protocol transports. 33 # All available wire protocol transports.
34 TRANSPORTS = { 34 TRANSPORTS = {
35 SSHV1: {'transport': 'ssh', 'version': 1,}, 35 SSHV1: {b'transport': b'ssh', b'version': 1,},
36 SSHV2: { 36 SSHV2: {
37 'transport': 'ssh', 37 b'transport': b'ssh',
38 # TODO mark as version 2 once all commands are implemented. 38 # TODO mark as version 2 once all commands are implemented.
39 'version': 1, 39 b'version': 1,
40 }, 40 },
41 'http-v1': {'transport': 'http', 'version': 1,}, 41 b'http-v1': {b'transport': b'http', b'version': 1,},
42 HTTP_WIREPROTO_V2: {'transport': 'http', 'version': 2,}, 42 HTTP_WIREPROTO_V2: {b'transport': b'http', b'version': 2,},
43 } 43 }
44 44
45 45
46 class bytesresponse(object): 46 class bytesresponse(object):
47 """A wire protocol response consisting of raw bytes.""" 47 """A wire protocol response consisting of raw bytes."""
114 def __init__(self, gen=None): 114 def __init__(self, gen=None):
115 self.gen = gen 115 self.gen = gen
116 116
117 117
118 # list of nodes encoding / decoding 118 # list of nodes encoding / decoding
119 def decodelist(l, sep=' '): 119 def decodelist(l, sep=b' '):
120 if l: 120 if l:
121 return [bin(v) for v in l.split(sep)] 121 return [bin(v) for v in l.split(sep)]
122 return [] 122 return []
123 123
124 124
125 def encodelist(l, sep=' '): 125 def encodelist(l, sep=b' '):
126 try: 126 try:
127 return sep.join(map(hex, l)) 127 return sep.join(map(hex, l))
128 except TypeError: 128 except TypeError:
129 raise 129 raise
130 130
132 # batched call argument encoding 132 # batched call argument encoding
133 133
134 134
135 def escapebatcharg(plain): 135 def escapebatcharg(plain):
136 return ( 136 return (
137 plain.replace(':', ':c') 137 plain.replace(b':', b':c')
138 .replace(',', ':o') 138 .replace(b',', b':o')
139 .replace(';', ':s') 139 .replace(b';', b':s')
140 .replace('=', ':e') 140 .replace(b'=', b':e')
141 ) 141 )
142 142
143 143
144 def unescapebatcharg(escaped): 144 def unescapebatcharg(escaped):
145 return ( 145 return (
146 escaped.replace(':e', '=') 146 escaped.replace(b':e', b'=')
147 .replace(':s', ';') 147 .replace(b':s', b';')
148 .replace(':o', ',') 148 .replace(b':o', b',')
149 .replace(':c', ':') 149 .replace(b':c', b':')
150 ) 150 )
151 151
152 152
153 # mapping of options accepted by getbundle and their types 153 # mapping of options accepted by getbundle and their types
154 # 154 #
160 # :nodes: list of binary nodes, transmitted as space-separated hex nodes 160 # :nodes: list of binary nodes, transmitted as space-separated hex nodes
161 # :csv: list of values, transmitted as comma-separated values 161 # :csv: list of values, transmitted as comma-separated values
162 # :scsv: set of values, transmitted as comma-separated values 162 # :scsv: set of values, transmitted as comma-separated values
163 # :plain: string with no transformation needed. 163 # :plain: string with no transformation needed.
164 GETBUNDLE_ARGUMENTS = { 164 GETBUNDLE_ARGUMENTS = {
165 'heads': 'nodes', 165 b'heads': b'nodes',
166 'bookmarks': 'boolean', 166 b'bookmarks': b'boolean',
167 'common': 'nodes', 167 b'common': b'nodes',
168 'obsmarkers': 'boolean', 168 b'obsmarkers': b'boolean',
169 'phases': 'boolean', 169 b'phases': b'boolean',
170 'bundlecaps': 'scsv', 170 b'bundlecaps': b'scsv',
171 'listkeys': 'csv', 171 b'listkeys': b'csv',
172 'cg': 'boolean', 172 b'cg': b'boolean',
173 'cbattempted': 'boolean', 173 b'cbattempted': b'boolean',
174 'stream': 'boolean', 174 b'stream': b'boolean',
175 'includepats': 'csv', 175 b'includepats': b'csv',
176 'excludepats': 'csv', 176 b'excludepats': b'csv',
177 } 177 }
178 178
179 179
180 class baseprotocolhandler(interfaceutil.Interface): 180 class baseprotocolhandler(interfaceutil.Interface):
181 """Abstract base class for wire protocol handlers. 181 """Abstract base class for wire protocol handlers.
251 """Represents a declared wire protocol command.""" 251 """Represents a declared wire protocol command."""
252 252
253 def __init__( 253 def __init__(
254 self, 254 self,
255 func, 255 func,
256 args='', 256 args=b'',
257 transports=None, 257 transports=None,
258 permission='push', 258 permission=b'push',
259 cachekeyfn=None, 259 cachekeyfn=None,
260 extracapabilitiesfn=None, 260 extracapabilitiesfn=None,
261 ): 261 ):
262 self.func = func 262 self.func = func
263 self.args = args 263 self.args = args
290 if i == 0: 290 if i == 0:
291 return self.func 291 return self.func
292 elif i == 1: 292 elif i == 1:
293 return self.args 293 return self.args
294 else: 294 else:
295 raise IndexError('can only access elements 0 and 1') 295 raise IndexError(b'can only access elements 0 and 1')
296 296
297 297
298 class commanddict(dict): 298 class commanddict(dict):
299 """Container for registered wire protocol commands. 299 """Container for registered wire protocol commands.
300 300
306 if isinstance(v, commandentry): 306 if isinstance(v, commandentry):
307 pass 307 pass
308 # Cast 2-tuples to commandentry instances. 308 # Cast 2-tuples to commandentry instances.
309 elif isinstance(v, tuple): 309 elif isinstance(v, tuple):
310 if len(v) != 2: 310 if len(v) != 2:
311 raise ValueError('command tuples must have exactly 2 elements') 311 raise ValueError(b'command tuples must have exactly 2 elements')
312 312
313 # It is common for extensions to wrap wire protocol commands via 313 # It is common for extensions to wrap wire protocol commands via
314 # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers 314 # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
315 # doing this aren't aware of the new API that uses objects to store 315 # doing this aren't aware of the new API that uses objects to store
316 # command entries, we automatically merge old state with new. 316 # command entries, we automatically merge old state with new.
320 # Use default values from @wireprotocommand. 320 # Use default values from @wireprotocommand.
321 v = commandentry( 321 v = commandentry(
322 v[0], 322 v[0],
323 args=v[1], 323 args=v[1],
324 transports=set(TRANSPORTS), 324 transports=set(TRANSPORTS),
325 permission='push', 325 permission=b'push',
326 ) 326 )
327 else: 327 else:
328 raise ValueError( 328 raise ValueError(
329 'command entries must be commandentry instances ' 'or 2-tuples' 329 b'command entries must be commandentry instances '
330 b'or 2-tuples'
330 ) 331 )
331 332
332 return super(commanddict, self).__setitem__(k, v) 333 return super(commanddict, self).__setitem__(k, v)
333 334
334 def commandavailable(self, command, proto): 335 def commandavailable(self, command, proto):
352 353
353 compengines = compression.compengines.supportedwireengines(role) 354 compengines = compression.compengines.supportedwireengines(role)
354 355
355 # Allow config to override default list and ordering. 356 # Allow config to override default list and ordering.
356 if role == compression.SERVERROLE: 357 if role == compression.SERVERROLE:
357 configengines = ui.configlist('server', 'compressionengines') 358 configengines = ui.configlist(b'server', b'compressionengines')
358 config = 'server.compressionengines' 359 config = b'server.compressionengines'
359 else: 360 else:
360 # This is currently implemented mainly to facilitate testing. In most 361 # This is currently implemented mainly to facilitate testing. In most
361 # cases, the server should be in charge of choosing a compression engine 362 # cases, the server should be in charge of choosing a compression engine
362 # because a server has the most to lose from a sub-optimal choice. (e.g. 363 # because a server has the most to lose from a sub-optimal choice. (e.g.
363 # CPU DoS due to an expensive engine or a network DoS due to poor 364 # CPU DoS due to an expensive engine or a network DoS due to poor
364 # compression ratio). 365 # compression ratio).
365 configengines = ui.configlist( 366 configengines = ui.configlist(
366 'experimental', 'clientcompressionengines' 367 b'experimental', b'clientcompressionengines'
367 ) 368 )
368 config = 'experimental.clientcompressionengines' 369 config = b'experimental.clientcompressionengines'
369 370
370 # No explicit config. Filter out the ones that aren't supposed to be 371 # No explicit config. Filter out the ones that aren't supposed to be
371 # advertised and return default ordering. 372 # advertised and return default ordering.
372 if not configengines: 373 if not configengines:
373 attr = 'serverpriority' if role == util.SERVERROLE else 'clientpriority' 374 attr = (
375 b'serverpriority' if role == util.SERVERROLE else b'clientpriority'
376 )
374 return [ 377 return [
375 e for e in compengines if getattr(e.wireprotosupport(), attr) > 0 378 e for e in compengines if getattr(e.wireprotosupport(), attr) > 0
376 ] 379 ]
377 380
378 # If compression engines are listed in the config, assume there is a good 381 # If compression engines are listed in the config, assume there is a good
381 # unusable compression engines. 384 # unusable compression engines.
382 validnames = set(e.name() for e in compengines) 385 validnames = set(e.name() for e in compengines)
383 invalidnames = set(e for e in configengines if e not in validnames) 386 invalidnames = set(e for e in configengines if e not in validnames)
384 if invalidnames: 387 if invalidnames:
385 raise error.Abort( 388 raise error.Abort(
386 _('invalid compression engine defined in %s: %s') 389 _(b'invalid compression engine defined in %s: %s')
387 % (config, ', '.join(sorted(invalidnames))) 390 % (config, b', '.join(sorted(invalidnames)))
388 ) 391 )
389 392
390 compengines = [e for e in compengines if e.name() in configengines] 393 compengines = [e for e in compengines if e.name() in configengines]
391 compengines = sorted( 394 compengines = sorted(
392 compengines, key=lambda e: configengines.index(e.name()) 395 compengines, key=lambda e: configengines.index(e.name())
393 ) 396 )
394 397
395 if not compengines: 398 if not compengines:
396 raise error.Abort( 399 raise error.Abort(
397 _( 400 _(
398 '%s config option does not specify any known ' 401 b'%s config option does not specify any known '
399 'compression engines' 402 b'compression engines'
400 ) 403 )
401 % config, 404 % config,
402 hint=_('usable compression engines: %s') % ', '.sorted(validnames), 405 hint=_(b'usable compression engines: %s')
406 % b', '.sorted(validnames),
403 ) 407 )
404 408
405 return compengines 409 return compengines
406 410
407 411