comparison mercurial/debugcommands.py @ 36559:bde0bd50f368

debugcommands: allow sending of simple commands with debugwireproto Previously, we only had support for low-level "raw" operations. A goal of `hg debugwireproto` is to allow easily performing higher-level primitives, such as sending a wire protocol command and reading its response. We implement a "command" action that does just this. Currently, we only support simple commands (those without payloads). We have basic support for sending command arguments. We don't yet support sending dictionary arguments. This will be implemented later. To prove it works, we add tests to test-ssh-proto.t that send some "listkeys" commands. Note: we don't observe/report os.read() events because these may not be deterministic. We instead observe/report the read() and readline() operations on the bufferedinputpipe. These *should* be deterministic. Differential Revision: https://phab.mercurial-scm.org/D2406
author Gregory Szorc <gregory.szorc@gmail.com>
date Thu, 01 Mar 2018 08:27:30 -0800
parents 72e487851a53
children 097ad1079192
comparison
equal deleted inserted replaced
36558:33c6f8f0388d 36559:bde0bd50f368
2612 raw+ 2612 raw+
2613 ---- 2613 ----
2614 2614
2615 Behaves like ``raw`` except flushes output afterwards. 2615 Behaves like ``raw`` except flushes output afterwards.
2616 2616
2617 command <X>
2618 -----------
2619
2620 Send a request to run a named command, whose name follows the ``command``
2621 string.
2622
2623 Arguments to the command are defined as lines in this block. The format of
2624 each line is ``<key> <value>``. e.g.::
2625
2626 command listkeys
2627 namespace bookmarks
2628
2629 Values are interpreted as Python b'' literals. This allows encoding
2630 special byte sequences via backslash escaping.
2631
2617 close 2632 close
2618 ----- 2633 -----
2619 2634
2620 Close the connection to the server. 2635 Close the connection to the server.
2621 2636
2711 2726
2712 if action == 'raw+': 2727 if action == 'raw+':
2713 stdin.flush() 2728 stdin.flush()
2714 elif action == 'flush': 2729 elif action == 'flush':
2715 stdin.flush() 2730 stdin.flush()
2731 elif action.startswith('command'):
2732 if not peer:
2733 raise error.Abort(_('cannot send commands unless peer instance '
2734 'is available'))
2735
2736 command = action.split(' ', 1)[1]
2737
2738 args = {}
2739 for line in lines:
2740 # We need to allow empty values.
2741 fields = line.lstrip().split(' ', 1)
2742 if len(fields) == 1:
2743 key = fields[0]
2744 value = ''
2745 else:
2746 key, value = fields
2747
2748 args[key] = util.unescapestr(value)
2749
2750 ui.status(_('sending %s command\n') % command)
2751 res = peer._call(command, **args)
2752 ui.status(_('response: %s\n') % util.escapedata(res))
2753
2716 elif action == 'close': 2754 elif action == 'close':
2717 peer.close() 2755 peer.close()
2718 elif action == 'readavailable': 2756 elif action == 'readavailable':
2719 fds = util.poll([stdout.fileno(), stderr.fileno()]) 2757 fds = util.poll([stdout.fileno(), stderr.fileno()])
2720 2758