diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -73,6 +73,7 @@ url as urlmod, util, vfs as vfsmod, + wireprotoserver, ) release = lockmod.release @@ -2230,6 +2231,37 @@ for c in revs: ui.write("%d\n" % c) +@command('debugserve', [ + ('', 'sshstdio', False, _('run an SSH server bound to process handles')), + ('', 'logiofd', '', _('file descriptor to log server I/O to')), + ('', 'logiofile', '', _('file to log server I/O to')), +], '') +def debugserve(ui, repo, **opts): + """run a server with advanced settings + + This command is similar to :hg:`serve`. It exists partially as a + workaround to the fact that ``hg serve --stdio`` must have specific + arguments for security reasons. + """ + opts = pycompat.byteskwargs(opts) + + if not opts['sshstdio']: + raise error.Abort(_('only --sshstdio is currently supported')) + + logfh = None + + if opts['logiofd'] and opts['logiofile']: + raise error.Abort(_('cannot use both --logiofd and --logiofile')) + + if opts['logiofd']: + # Line buffered because output is line based. + logfh = os.fdopen(int(opts['logiofd']), 'ab', 1) + elif opts['logiofile']: + logfh = open(opts['logiofile'], 'ab', 1) + + s = wireprotoserver.sshserver(ui, repo, logfh=logfh) + s.serve_forever() + @command('debugsetparents', [], _('REV1 [REV2]')) def debugsetparents(ui, repo, rev1, rev2=None): """manually set the parents of the current working directory diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -111,6 +111,7 @@ debugrename debugrevlog debugrevspec + debugserve debugsetparents debugssl debugsub @@ -291,6 +292,7 @@ debugrename: rev debugrevlog: changelog, manifest, dir, dump debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized + debugserve: sshstdio, logiofd, logiofile debugsetparents: debugssl: debugsub: rev diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -967,6 +967,7 @@ debugrename dump rename information debugrevlog show data and statistics about a revlog debugrevspec parse and apply a revision specification + debugserve run a server with advanced settings debugsetparents manually set the parents of the current working directory debugssl test a secure connection to a server diff --git a/tests/test-ssh-proto.t b/tests/test-ssh-proto.t --- a/tests/test-ssh-proto.t +++ b/tests/test-ssh-proto.t @@ -39,6 +39,43 @@ 384 capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN +`hg debugserve --sshstdio` works + + $ cd server + $ hg debugserve --sshstdio << EOF + > hello + > EOF + 384 + capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN + +I/O logging works + + $ hg debugserve --sshstdio --logiofd 1 << EOF + > hello + > EOF + o> write(4) -> None: + o> 384\n + o> write(384) -> None: + o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n + 384 + capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN + o> flush() -> None + + $ hg debugserve --sshstdio --logiofile $TESTTMP/io << EOF + > hello + > EOF + 384 + capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN + + $ cat $TESTTMP/io + o> write(4) -> None: + o> 384\n + o> write(384) -> None: + o> capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN\n + o> flush() -> None + + $ cd .. + >=0.9.1 clients send a "hello" + "between" for the null range as part of handshake. Server should reply with capabilities and should send "1\n\n" as a successful reply with empty response to the "between".