2600 [ |
2601 [ |
2601 ('', 'localssh', False, _('start an SSH server for this repo')), |
2602 ('', 'localssh', False, _('start an SSH server for this repo')), |
2602 ('', 'peer', '', _('construct a specific version of the peer')), |
2603 ('', 'peer', '', _('construct a specific version of the peer')), |
2603 ('', 'noreadstderr', False, _('do not read from stderr of the remote')), |
2604 ('', 'noreadstderr', False, _('do not read from stderr of the remote')), |
2604 ] + cmdutil.remoteopts, |
2605 ] + cmdutil.remoteopts, |
2605 _('[REPO]'), |
2606 _('[PATH]'), |
2606 optionalrepo=True) |
2607 optionalrepo=True) |
2607 def debugwireproto(ui, repo, **opts): |
2608 def debugwireproto(ui, repo, path=None, **opts): |
2608 """send wire protocol commands to a server |
2609 """send wire protocol commands to a server |
2609 |
2610 |
2610 This command can be used to issue wire protocol commands to remote |
2611 This command can be used to issue wire protocol commands to remote |
2611 peers and to debug the raw data being exchanged. |
2612 peers and to debug the raw data being exchanged. |
2612 |
2613 |
2738 |
2739 |
2739 if opts['peer'] and opts['peer'] not in ('raw', 'ssh1', 'ssh2'): |
2740 if opts['peer'] and opts['peer'] not in ('raw', 'ssh1', 'ssh2'): |
2740 raise error.Abort(_('invalid value for --peer'), |
2741 raise error.Abort(_('invalid value for --peer'), |
2741 hint=_('valid values are "raw", "ssh1", and "ssh2"')) |
2742 hint=_('valid values are "raw", "ssh1", and "ssh2"')) |
2742 |
2743 |
|
2744 if path and opts['localssh']: |
|
2745 raise error.Abort(_('cannot specify --localssh with an explicit ' |
|
2746 'path')) |
|
2747 |
2743 if ui.interactive(): |
2748 if ui.interactive(): |
2744 ui.write(_('(waiting for commands on stdin)\n')) |
2749 ui.write(_('(waiting for commands on stdin)\n')) |
2745 |
2750 |
2746 blocks = list(_parsewirelangblocks(ui.fin)) |
2751 blocks = list(_parsewirelangblocks(ui.fin)) |
2747 |
2752 |
2748 proc = None |
2753 proc = None |
|
2754 stdin = None |
|
2755 stdout = None |
|
2756 stderr = None |
2749 |
2757 |
2750 if opts['localssh']: |
2758 if opts['localssh']: |
2751 # We start the SSH server in its own process so there is process |
2759 # We start the SSH server in its own process so there is process |
2752 # separation. This prevents a whole class of potential bugs around |
2760 # separation. This prevents a whole class of potential bugs around |
2753 # shared state from interfering with server operation. |
2761 # shared state from interfering with server operation. |
2791 else: |
2799 else: |
2792 ui.write(_('creating ssh peer from handshake results\n')) |
2800 ui.write(_('creating ssh peer from handshake results\n')) |
2793 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr, |
2801 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr, |
2794 autoreadstderr=autoreadstderr) |
2802 autoreadstderr=autoreadstderr) |
2795 |
2803 |
|
2804 elif path: |
|
2805 # We bypass hg.peer() so we can proxy the sockets. |
|
2806 # TODO consider not doing this because we skip |
|
2807 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality. |
|
2808 u = util.url(path) |
|
2809 if u.scheme != 'http': |
|
2810 raise error.Abort(_('only http:// paths are currently supported')) |
|
2811 |
|
2812 url, authinfo = u.authinfo() |
|
2813 openerargs = {} |
|
2814 |
|
2815 # Turn pipes/sockets into observers so we can log I/O. |
|
2816 if ui.verbose: |
|
2817 openerargs = { |
|
2818 r'loggingfh': ui, |
|
2819 r'loggingname': b's', |
|
2820 r'loggingopts': { |
|
2821 r'logdata': True, |
|
2822 }, |
|
2823 } |
|
2824 |
|
2825 opener = urlmod.opener(ui, authinfo, **openerargs) |
|
2826 |
|
2827 if opts['peer'] == 'raw': |
|
2828 ui.write(_('using raw connection to peer\n')) |
|
2829 peer = None |
|
2830 elif opts['peer']: |
|
2831 raise error.Abort(_('--peer %s not supported with HTTP peers') % |
|
2832 opts['peer']) |
|
2833 else: |
|
2834 peer = httppeer.httppeer(ui, path, url, opener) |
|
2835 peer._fetchcaps() |
|
2836 |
|
2837 # We /could/ populate stdin/stdout with sock.makefile()... |
2796 else: |
2838 else: |
2797 raise error.Abort(_('only --localssh is currently supported')) |
2839 raise error.Abort(_('unsupported connection configuration')) |
2798 |
2840 |
2799 batchedcommands = None |
2841 batchedcommands = None |
2800 |
2842 |
2801 # Now perform actions based on the parsed wire language instructions. |
2843 # Now perform actions based on the parsed wire language instructions. |
2802 for action, lines in blocks: |
2844 for action, lines in blocks: |
2803 if action in ('raw', 'raw+'): |
2845 if action in ('raw', 'raw+'): |
|
2846 if not stdin: |
|
2847 raise error.Abort(_('cannot call raw/raw+ on this peer')) |
|
2848 |
2804 # Concatenate the data together. |
2849 # Concatenate the data together. |
2805 data = ''.join(l.lstrip() for l in lines) |
2850 data = ''.join(l.lstrip() for l in lines) |
2806 data = util.unescapestr(data) |
2851 data = util.unescapestr(data) |
2807 stdin.write(data) |
2852 stdin.write(data) |
2808 |
2853 |
2809 if action == 'raw+': |
2854 if action == 'raw+': |
2810 stdin.flush() |
2855 stdin.flush() |
2811 elif action == 'flush': |
2856 elif action == 'flush': |
|
2857 if not stdin: |
|
2858 raise error.Abort(_('cannot call flush on this peer')) |
2812 stdin.flush() |
2859 stdin.flush() |
2813 elif action.startswith('command'): |
2860 elif action.startswith('command'): |
2814 if not peer: |
2861 if not peer: |
2815 raise error.Abort(_('cannot send commands unless peer instance ' |
2862 raise error.Abort(_('cannot send commands unless peer instance ' |
2816 'is available')) |
2863 'is available')) |
2863 |
2910 |
2864 batchedcommands = None |
2911 batchedcommands = None |
2865 elif action == 'close': |
2912 elif action == 'close': |
2866 peer.close() |
2913 peer.close() |
2867 elif action == 'readavailable': |
2914 elif action == 'readavailable': |
|
2915 if not stdout or not stderr: |
|
2916 raise error.Abort(_('readavailable not available on this peer')) |
|
2917 |
2868 stdin.close() |
2918 stdin.close() |
2869 stdout.read() |
2919 stdout.read() |
2870 stderr.read() |
2920 stderr.read() |
|
2921 |
2871 elif action == 'readline': |
2922 elif action == 'readline': |
|
2923 if not stdout: |
|
2924 raise error.Abort(_('readline not available on this peer')) |
2872 stdout.readline() |
2925 stdout.readline() |
2873 elif action == 'ereadline': |
2926 elif action == 'ereadline': |
|
2927 if not stderr: |
|
2928 raise error.Abort(_('ereadline not available on this peer')) |
2874 stderr.readline() |
2929 stderr.readline() |
2875 elif action.startswith('read '): |
2930 elif action.startswith('read '): |
2876 count = int(action.split(' ', 1)[1]) |
2931 count = int(action.split(' ', 1)[1]) |
|
2932 if not stdout: |
|
2933 raise error.Abort(_('read not available on this peer')) |
2877 stdout.read(count) |
2934 stdout.read(count) |
2878 elif action.startswith('eread '): |
2935 elif action.startswith('eread '): |
2879 count = int(action.split(' ', 1)[1]) |
2936 count = int(action.split(' ', 1)[1]) |
|
2937 if not stderr: |
|
2938 raise error.Abort(_('eread not available on this peer')) |
2880 stderr.read(count) |
2939 stderr.read(count) |
2881 else: |
2940 else: |
2882 raise error.Abort(_('unknown action: %s') % action) |
2941 raise error.Abort(_('unknown action: %s') % action) |
2883 |
2942 |
2884 if batchedcommands is not None: |
2943 if batchedcommands is not None: |