Show More
@@ -7,7 +7,7 b'' | |||||
7 |
|
7 | |||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | import struct |
|
9 | import struct | |
10 | import os, errno, traceback, SocketServer |
|
10 | import sys, os, errno, traceback, SocketServer | |
11 | import dispatch, encoding, util |
|
11 | import dispatch, encoding, util | |
12 |
|
12 | |||
13 | logfile = None |
|
13 | logfile = None | |
@@ -248,6 +248,29 b' class server(object):' | |||||
248 |
|
248 | |||
249 | return 0 |
|
249 | return 0 | |
250 |
|
250 | |||
|
251 | def _protectio(ui): | |||
|
252 | """ duplicates streams and redirect original to null if ui uses stdio """ | |||
|
253 | ui.flush() | |||
|
254 | newfiles = [] | |||
|
255 | nullfd = os.open(os.devnull, os.O_RDWR) | |||
|
256 | for f, sysf, mode in [(ui.fin, sys.stdin, 'rb'), | |||
|
257 | (ui.fout, sys.stdout, 'wb')]: | |||
|
258 | if f is sysf: | |||
|
259 | newfd = os.dup(f.fileno()) | |||
|
260 | os.dup2(nullfd, f.fileno()) | |||
|
261 | f = os.fdopen(newfd, mode) | |||
|
262 | newfiles.append(f) | |||
|
263 | os.close(nullfd) | |||
|
264 | return tuple(newfiles) | |||
|
265 | ||||
|
266 | def _restoreio(ui, fin, fout): | |||
|
267 | """ restores streams from duplicated ones """ | |||
|
268 | ui.flush() | |||
|
269 | for f, uif in [(fin, ui.fin), (fout, ui.fout)]: | |||
|
270 | if f is not uif: | |||
|
271 | os.dup2(f.fileno(), uif.fileno()) | |||
|
272 | f.close() | |||
|
273 | ||||
251 | class pipeservice(object): |
|
274 | class pipeservice(object): | |
252 | def __init__(self, ui, repo, opts): |
|
275 | def __init__(self, ui, repo, opts): | |
253 | self.ui = ui |
|
276 | self.ui = ui | |
@@ -258,8 +281,14 b' class pipeservice(object):' | |||||
258 |
|
281 | |||
259 | def run(self): |
|
282 | def run(self): | |
260 | ui = self.ui |
|
283 | ui = self.ui | |
261 | sv = server(ui, self.repo, ui.fin, ui.fout) |
|
284 | # redirect stdio to null device so that broken extensions or in-process | |
|
285 | # hooks will never cause corruption of channel protocol. | |||
|
286 | fin, fout = _protectio(ui) | |||
|
287 | try: | |||
|
288 | sv = server(ui, self.repo, fin, fout) | |||
262 | return sv.serve() |
|
289 | return sv.serve() | |
|
290 | finally: | |||
|
291 | _restoreio(ui, fin, fout) | |||
263 |
|
292 | |||
264 | class _requesthandler(SocketServer.StreamRequestHandler): |
|
293 | class _requesthandler(SocketServer.StreamRequestHandler): | |
265 | def handle(self): |
|
294 | def handle(self): |
@@ -492,6 +492,7 b' check that local configs for the cached ' | |||||
492 | foo |
|
492 | foo | |
493 |
|
493 | |||
494 | $ cat <<EOF > dbgui.py |
|
494 | $ cat <<EOF > dbgui.py | |
|
495 | > import os, sys | |||
495 | > from mercurial import cmdutil, commands |
|
496 | > from mercurial import cmdutil, commands | |
496 | > cmdtable = {} |
|
497 | > cmdtable = {} | |
497 | > command = cmdutil.command(cmdtable) |
|
498 | > command = cmdutil.command(cmdtable) | |
@@ -501,6 +502,14 b' check that local configs for the cached ' | |||||
501 | > @command("debugprompt", norepo=True) |
|
502 | > @command("debugprompt", norepo=True) | |
502 | > def debugprompt(ui): |
|
503 | > def debugprompt(ui): | |
503 | > ui.write("%s\\n" % ui.prompt("prompt:")) |
|
504 | > ui.write("%s\\n" % ui.prompt("prompt:")) | |
|
505 | > @command("debugreadstdin", norepo=True) | |||
|
506 | > def debugreadstdin(ui): | |||
|
507 | > ui.write("read: %r\n" % sys.stdin.read(1)) | |||
|
508 | > @command("debugwritestdout", norepo=True) | |||
|
509 | > def debugwritestdout(ui): | |||
|
510 | > os.write(1, "low-level stdout fd and\n") | |||
|
511 | > sys.stdout.write("stdout should be redirected to /dev/null\n") | |||
|
512 | > sys.stdout.flush() | |||
504 | > EOF |
|
513 | > EOF | |
505 | $ cat <<EOF >> .hg/hgrc |
|
514 | $ cat <<EOF >> .hg/hgrc | |
506 | > [extensions] |
|
515 | > [extensions] | |
@@ -518,10 +527,15 b' check that local configs for the cached ' | |||||
518 | ... runcommand(server, ['debugprompt', '--config', |
|
527 | ... runcommand(server, ['debugprompt', '--config', | |
519 | ... 'ui.interactive=True'], |
|
528 | ... 'ui.interactive=True'], | |
520 | ... input=cStringIO.StringIO('5678\n')) |
|
529 | ... input=cStringIO.StringIO('5678\n')) | |
|
530 | ... runcommand(server, ['debugreadstdin']) | |||
|
531 | ... runcommand(server, ['debugwritestdout']) | |||
521 | *** runcommand debuggetpass --config ui.interactive=True |
|
532 | *** runcommand debuggetpass --config ui.interactive=True | |
522 | password: 1234 |
|
533 | password: 1234 | |
523 | *** runcommand debugprompt --config ui.interactive=True |
|
534 | *** runcommand debugprompt --config ui.interactive=True | |
524 | prompt: 5678 |
|
535 | prompt: 5678 | |
|
536 | *** runcommand debugreadstdin | |||
|
537 | read: '' | |||
|
538 | *** runcommand debugwritestdout | |||
525 |
|
539 | |||
526 |
|
540 | |||
527 | run commandserver in commandserver, which is silly but should work: |
|
541 | run commandserver in commandserver, which is silly but should work: |
General Comments 0
You need to be logged in to leave comments.
Login now