Show More
@@ -251,32 +251,20 b' class commanddict(dict):' | |||
|
251 | 251 | |
|
252 | 252 | return True |
|
253 | 253 | |
|
254 | # Constants specifying which transports a wire protocol command should be | |
|
255 | # available on. For use with @wireprotocommand. | |
|
256 | POLICY_V1_ONLY = 'v1-only' | |
|
257 | POLICY_V2_ONLY = 'v2-only' | |
|
258 | ||
|
259 | 254 | # For version 1 transports. |
|
260 | 255 | commands = commanddict() |
|
261 | 256 | |
|
262 | 257 | # For version 2 transports. |
|
263 | 258 | commandsv2 = commanddict() |
|
264 | 259 | |
|
265 |
def wireprotocommand(name, args=None, |
|
|
266 | permission='push'): | |
|
260 | def wireprotocommand(name, args=None, permission='push'): | |
|
267 | 261 | """Decorator to declare a wire protocol command. |
|
268 | 262 | |
|
269 | 263 | ``name`` is the name of the wire protocol command being provided. |
|
270 | 264 | |
|
271 | 265 | ``args`` defines the named arguments accepted by the command. It is |
|
272 | ideally a dict mapping argument names to their types. For backwards | |
|
273 | compatibility, it can be a space-delimited list of argument names. For | |
|
274 | version 1 transports, ``*`` denotes a special value that says to accept | |
|
275 | all named arguments. | |
|
276 | ||
|
277 | ``transportpolicy`` is a POLICY_* constant denoting which transports | |
|
278 | this wire protocol command should be exposed to. By default, commands | |
|
279 | are exposed to all wire protocol transports. | |
|
266 | a space-delimited list of argument names. ``*`` denotes a special value | |
|
267 | that says to accept all named arguments. | |
|
280 | 268 | |
|
281 | 269 | ``permission`` defines the permission type needed to run this command. |
|
282 | 270 | Can be ``push`` or ``pull``. These roughly map to read-write and read-only, |
@@ -284,17 +272,8 b' def wireprotocommand(name, args=None, tr' | |||
|
284 | 272 | because otherwise commands not declaring their permissions could modify |
|
285 | 273 | a repository that is supposed to be read-only. |
|
286 | 274 | """ |
|
287 | if transportpolicy == POLICY_V1_ONLY: | |
|
288 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() | |
|
289 | if v['version'] == 1} | |
|
290 | transportversion = 1 | |
|
291 | elif transportpolicy == POLICY_V2_ONLY: | |
|
292 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() | |
|
293 | if v['version'] == 2} | |
|
294 | transportversion = 2 | |
|
295 | else: | |
|
296 | raise error.ProgrammingError('invalid transport policy value: %s' % | |
|
297 | transportpolicy) | |
|
275 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() | |
|
276 | if v['version'] == 1} | |
|
298 | 277 | |
|
299 | 278 | # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to |
|
300 | 279 | # SSHv2. |
@@ -307,40 +286,20 b' def wireprotocommand(name, args=None, tr' | |||
|
307 | 286 | 'got %s; expected "push" or "pull"' % |
|
308 | 287 | permission) |
|
309 | 288 | |
|
310 | if transportversion == 1: | |
|
311 |
|
|
|
312 | args = '' | |
|
289 | if args is None: | |
|
290 | args = '' | |
|
313 | 291 | |
|
314 |
|
|
|
315 |
|
|
|
316 |
|
|
|
317 | elif transportversion == 2: | |
|
318 | if args is None: | |
|
319 | args = {} | |
|
320 | ||
|
321 | if not isinstance(args, dict): | |
|
322 | raise error.ProgrammingError('arguments for version 2 commands ' | |
|
323 | 'must be declared as dicts') | |
|
292 | if not isinstance(args, bytes): | |
|
293 | raise error.ProgrammingError('arguments for version 1 commands ' | |
|
294 | 'must be declared as bytes') | |
|
324 | 295 | |
|
325 | 296 | def register(func): |
|
326 | if transportversion == 1: | |
|
327 | if name in commands: | |
|
328 | raise error.ProgrammingError('%s command already registered ' | |
|
329 | 'for version 1' % name) | |
|
330 | commands[name] = commandentry(func, args=args, | |
|
331 |
|
|
|
332 | permission=permission) | |
|
333 | elif transportversion == 2: | |
|
334 | if name in commandsv2: | |
|
335 | raise error.ProgrammingError('%s command already registered ' | |
|
336 | 'for version 2' % name) | |
|
337 | ||
|
338 | commandsv2[name] = commandentry(func, args=args, | |
|
339 | transports=transports, | |
|
340 | permission=permission) | |
|
341 | else: | |
|
342 | raise error.ProgrammingError('unhandled transport version: %d' % | |
|
343 | transportversion) | |
|
297 | if name in commands: | |
|
298 | raise error.ProgrammingError('%s command already registered ' | |
|
299 | 'for version 1' % name) | |
|
300 | commands[name] = commandentry(func, args=args, | |
|
301 | transports=transports, | |
|
302 | permission=permission) | |
|
344 | 303 | |
|
345 | 304 | return func |
|
346 | 305 | return register |
@@ -405,10 +405,43 b' def _capabilitiesv2(repo, proto):' | |||
|
405 | 405 | |
|
406 | 406 | return proto.addcapabilities(repo, caps) |
|
407 | 407 | |
|
408 |
def wireprotocommand( |
|
|
408 | def wireprotocommand(name, args=None, permission='push'): | |
|
409 | """Decorator to declare a wire protocol command. | |
|
410 | ||
|
411 | ``name`` is the name of the wire protocol command being provided. | |
|
412 | ||
|
413 | ``args`` is a dict of argument names to example values. | |
|
414 | ||
|
415 | ``permission`` defines the permission type needed to run this command. | |
|
416 | Can be ``push`` or ``pull``. These roughly map to read-write and read-only, | |
|
417 | respectively. Default is to assume command requires ``push`` permissions | |
|
418 | because otherwise commands not declaring their permissions could modify | |
|
419 | a repository that is supposed to be read-only. | |
|
420 | """ | |
|
421 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() | |
|
422 | if v['version'] == 2} | |
|
423 | ||
|
424 | if permission not in ('push', 'pull'): | |
|
425 | raise error.ProgrammingError('invalid wire protocol permission; ' | |
|
426 | 'got %s; expected "push" or "pull"' % | |
|
427 | permission) | |
|
428 | ||
|
429 | if args is None: | |
|
430 | args = {} | |
|
431 | ||
|
432 | if not isinstance(args, dict): | |
|
433 | raise error.ProgrammingError('arguments for version 2 commands ' | |
|
434 | 'must be declared as dicts') | |
|
435 | ||
|
409 | 436 | def register(func): |
|
410 |
|
|
|
411 | *args, transportpolicy=wireproto.POLICY_V2_ONLY, **kwargs)(func) | |
|
437 | if name in wireproto.commandsv2: | |
|
438 | raise error.ProgrammingError('%s command already registered ' | |
|
439 | 'for version 2' % name) | |
|
440 | ||
|
441 | wireproto.commandsv2[name] = wireproto.commandentry( | |
|
442 | func, args=args, transports=transports, permission=permission) | |
|
443 | ||
|
444 | return func | |
|
412 | 445 | |
|
413 | 446 | return register |
|
414 | 447 |
@@ -16,6 +16,7 b' sendhttpv2peerhandshake() {' | |||
|
16 | 16 | cat > dummycommands.py << EOF |
|
17 | 17 | from mercurial import ( |
|
18 | 18 | wireprototypes, |
|
19 | wireprotov2server, | |
|
19 | 20 | wireproto, |
|
20 | 21 | ) |
|
21 | 22 | |
@@ -23,8 +24,7 b' from mercurial import (' | |||
|
23 | 24 | def customreadonlyv1(repo, proto): |
|
24 | 25 | return wireprototypes.bytesresponse(b'customreadonly bytes response') |
|
25 | 26 | |
|
26 |
@wireproto.wireprotocommand('customreadonly', permission='pull' |
|
|
27 | transportpolicy=wireproto.POLICY_V2_ONLY) | |
|
27 | @wireprotov2server.wireprotocommand('customreadonly', permission='pull') | |
|
28 | 28 | def customreadonlyv2(repo, proto): |
|
29 | 29 | return wireprototypes.cborresponse(b'customreadonly bytes response') |
|
30 | 30 | |
@@ -32,8 +32,7 b' def customreadonlyv2(repo, proto):' | |||
|
32 | 32 | def customreadwrite(repo, proto): |
|
33 | 33 | return wireprototypes.bytesresponse(b'customreadwrite bytes response') |
|
34 | 34 | |
|
35 |
@wireproto.wireprotocommand('customreadwrite', permission='push' |
|
|
36 | transportpolicy=wireproto.POLICY_V2_ONLY) | |
|
35 | @wireprotov2server.wireprotocommand('customreadwrite', permission='push') | |
|
37 | 36 | def customreadwritev2(repo, proto): |
|
38 | 37 | return wireprototypes.cborresponse(b'customreadwrite bytes response') |
|
39 | 38 | EOF |
General Comments 0
You need to be logged in to leave comments.
Login now