D2726: debugcommands: support connecting to HTTP peers
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Tue Mar 13 00:08:27 UTC 2018
indygreg updated this revision to Diff 6977.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D2726?vs=6721&id=6977
REVISION DETAIL
https://phab.mercurial-scm.org/D2726
AFFECTED FILES
mercurial/debugcommands.py
tests/test-http-protocol.t
CHANGE DETAILS
diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -161,3 +161,68 @@
0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
0020: 78 |x|
+
+ $ killdaemons.py
+ $ cd ..
+
+Test listkeys for listing namespaces
+
+ $ hg init empty
+ $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
+ $ cat hg.pid > $DAEMON_PIDS
+ $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
+ > command listkeys
+ > namespace namespaces
+ > EOF
+ s> sendall(*, 0): (glob)
+ s> GET /?cmd=capabilities HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> accept: application/mercurial-0.1\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
+ s> \r\n
+ s> makefile('rb', None)
+ s> readline() -> 36:
+ s> HTTP/1.1 200 Script output follows\r\n
+ s> readline() -> *: (glob)
+ s> Server: *\r\n (glob)
+ s> readline() -> *: (glob)
+ s> Date: *\r\n (glob)
+ s> readline() -> 41:
+ s> Content-Type: application/mercurial-0.1\r\n
+ s> readline() -> 21:
+ s> Content-Length: *\r\n (glob)
+ s> readline() -> 2:
+ s> \r\n
+ s> read(*) -> *: lookup branchmap pushkey known getbundle unbundlehash batch changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx compression=$BUNDLE2_COMPRESSIONS$ (glob)
+ sending listkeys command
+ s> sendall(*, 0): (glob)
+ s> GET /?cmd=listkeys HTTP/1.1\r\n
+ s> Accept-Encoding: identity\r\n
+ s> vary: X-HgArg-1,X-HgProto-1\r\n
+ s> x-hgarg-1: namespace=namespaces\r\n
+ s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$\r\n
+ s> accept: application/mercurial-0.1\r\n
+ s> host: $LOCALIP:$HGPORT\r\n (glob)
+ s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
+ s> \r\n
+ s> makefile('rb', None)
+ s> readline() -> 36:
+ s> HTTP/1.1 200 Script output follows\r\n
+ s> readline() -> 36:
+ s> Server: *\r\n (glob)
+ s> readline() -> *: (glob)
+ s> Date: *\r\n (glob)
+ s> readline() -> 41:
+ s> Content-Type: application/mercurial-0.1\r\n
+ s> readline() -> 20:
+ s> Content-Length: 30\r\n
+ s> readline() -> 2:
+ s> \r\n
+ s> read(30) -> 30:
+ s> bookmarks \n
+ s> namespaces \n
+ s> phases
+ response: bookmarks \nnamespaces \nphases
+
+ $ killdaemons.py
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -48,6 +48,7 @@
fileset,
formatter,
hg,
+ httppeer,
localrepo,
lock as lockmod,
logcmdutil,
@@ -2588,9 +2589,9 @@
('', 'peer', '', _('construct a specific version of the peer')),
('', 'noreadstderr', False, _('do not read from stderr of the remote')),
] + cmdutil.remoteopts,
- _('[REPO]'),
+ _('[PATH]'),
optionalrepo=True)
-def debugwireproto(ui, repo, **opts):
+def debugwireproto(ui, repo, path=None, **opts):
"""send wire protocol commands to a server
This command can be used to issue wire protocol commands to remote
@@ -2726,12 +2727,19 @@
raise error.Abort(_('invalid value for --peer'),
hint=_('valid values are "raw", "ssh1", and "ssh2"'))
+ if path and opts['localssh']:
+ raise error.Abort(_('cannot specify --localssh with an explicit '
+ 'path'))
+
if ui.interactive():
ui.write(_('(waiting for commands on stdin)\n'))
blocks = list(_parsewirelangblocks(ui.fin))
proc = None
+ stdin = None
+ stdout = None
+ stderr = None
if opts['localssh']:
# We start the SSH server in its own process so there is process
@@ -2779,22 +2787,55 @@
peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
autoreadstderr=autoreadstderr)
+ elif path:
+ # We bypass hg.peer() so we can proxy the sockets.
+ # TODO consider not doing this because we skip
+ # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
+ u = util.url(path)
+ if u.scheme != 'http':
+ raise error.Abort(_('only http:// paths are currently supported'))
+
+ if opts['peer']:
+ raise error.Abort(_('--peer is not supported with HTTP peers'))
+
+ url, authinfo = u.authinfo()
+ openerargs = {}
+
+ # Turn pipes/sockets into observers so we can log I/O.
+ if ui.verbose:
+ openerargs = {
+ r'loggingfh': ui,
+ r'loggingname': b's',
+ r'loggingopts': {
+ r'logdata': True,
+ },
+ }
+
+ opener = urlmod.opener(ui, authinfo, **openerargs)
+ peer = httppeer.httppeer(ui, path, url, opener)
+ peer._fetchcaps()
+ # We /could/ populate stdin/stdout with sock.makefile()...
else:
- raise error.Abort(_('only --localssh is currently supported'))
+ raise error.Abort(_('unsupported connection configuration'))
batchedcommands = None
# Now perform actions based on the parsed wire language instructions.
for action, lines in blocks:
if action in ('raw', 'raw+'):
+ if not stdin:
+ raise error.Abort(_('cannot call raw/raw+ on this peer'))
+
# Concatenate the data together.
data = ''.join(l.lstrip() for l in lines)
data = util.unescapestr(data)
stdin.write(data)
if action == 'raw+':
stdin.flush()
elif action == 'flush':
+ if not stdin:
+ raise error.Abort(_('cannot call flush on this peer'))
stdin.flush()
elif action.startswith('command'):
if not peer:
@@ -2851,18 +2892,30 @@
elif action == 'close':
peer.close()
elif action == 'readavailable':
+ if not stdout or not stderr:
+ raise error.Abort(_('readavailable not available on this peer'))
+
stdin.close()
stdout.read()
stderr.read()
+
elif action == 'readline':
+ if not stdout:
+ raise error.Abort(_('readline not available on this peer'))
stdout.readline()
elif action == 'ereadline':
+ if not stderr:
+ raise error.Abort(_('ereadline not available on this peer'))
stderr.readline()
elif action.startswith('read '):
count = int(action.split(' ', 1)[1])
+ if not stdout:
+ raise error.Abort(_('read not available on this peer'))
stdout.read(count)
elif action.startswith('eread '):
count = int(action.split(' ', 1)[1])
+ if not stderr:
+ raise error.Abort(_('eread not available on this peer'))
stderr.read(count)
else:
raise error.Abort(_('unknown action: %s') % action)
To: indygreg, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list