diff mercurial/debugcommands.py @ 36527:44dc34b8d17b

debugcommands: add debugserve command `hg serve --stdio` requires the exact command argument form `hg -R <path> serve --stdio` for security reasons. An upcoming commit will need to start an SSH protocol server process with custom settings. This commit creates a `hg debugserve` command for starting servers with custom options. There are no security restrictions and we can add options here that aren't appropriate for built-in commands. We currently only support starting an SSH protocol server using the process's stdio file descriptors. The server supports logging its I/O activity to a file descriptor number passed as a command argument. Differential Revision: https://phab.mercurial-scm.org/D2464
author Gregory Szorc <gregory.szorc@gmail.com>
date Tue, 27 Feb 2018 15:47:44 -0800
parents 6e90c59b6da1
children 72e487851a53
line wrap: on
line diff
--- a/mercurial/debugcommands.py	Sun Feb 25 11:16:09 2018 -0800
+++ b/mercurial/debugcommands.py	Tue Feb 27 15:47:44 2018 -0800
@@ -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