##// END OF EJS Templates
cmdserver: add service that listens on unix domain socket and forks process...
Yuya Nishihara -
r22994:840be5ca default
parent child Browse files
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 sys, os
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
@@ -256,8 +256,59 b' class pipeservice(object):'
256 def run(self):
256 def run(self):
257 return self.server.serve()
257 return self.server.serve()
258
258
259 class _requesthandler(SocketServer.StreamRequestHandler):
260 def handle(self):
261 ui = self.server.ui
262 repo = self.server.repo
263 sv = server(ui, repo, self.rfile, self.wfile)
264 try:
265 try:
266 sv.serve()
267 # handle exceptions that may be raised by command server. most of
268 # known exceptions are caught by dispatch.
269 except util.Abort, inst:
270 ui.warn(_('abort: %s\n') % inst)
271 except IOError, inst:
272 if inst.errno != errno.EPIPE:
273 raise
274 except KeyboardInterrupt:
275 pass
276 except: # re-raises
277 # also write traceback to error channel. otherwise client cannot
278 # see it because it is written to server's stderr by default.
279 traceback.print_exc(file=sv.cerr)
280 raise
281
282 class unixservice(object):
283 """
284 Listens on unix domain socket and forks server per connection
285 """
286 def __init__(self, ui, repo, opts):
287 self.ui = ui
288 self.repo = repo
289 self.address = opts['address']
290 if not util.safehasattr(SocketServer, 'UnixStreamServer'):
291 raise util.Abort(_('unsupported platform'))
292 if not self.address:
293 raise util.Abort(_('no socket path specified with --address'))
294
295 def init(self):
296 class cls(SocketServer.ForkingMixIn, SocketServer.UnixStreamServer):
297 ui = self.ui
298 repo = self.repo
299 self.server = cls(self.address, _requesthandler)
300 self.ui.status(_('listening at %s\n') % self.address)
301 self.ui.flush() # avoid buffering of status message
302
303 def run(self):
304 try:
305 self.server.serve_forever()
306 finally:
307 os.unlink(self.address)
308
259 _servicemap = {
309 _servicemap = {
260 'pipe': pipeservice,
310 'pipe': pipeservice,
311 'unix': unixservice,
261 }
312 }
262
313
263 def createservice(ui, repo, opts):
314 def createservice(ui, repo, opts):
@@ -1,5 +1,6 b''
1 import os, stat
1 import os, stat
2 import re
2 import re
3 import socket
3 import sys
4 import sys
4 import tempfile
5 import tempfile
5
6
@@ -258,6 +259,10 b' def has_unix_permissions():'
258 finally:
259 finally:
259 os.rmdir(d)
260 os.rmdir(d)
260
261
262 @check("unix-socket", "AF_UNIX socket family")
263 def has_unix_socket():
264 return getattr(socket, 'AF_UNIX', None) is not None
265
261 @check("root", "root permissions")
266 @check("root", "root permissions")
262 def has_root():
267 def has_root():
263 return getattr(os, 'geteuid', None) and os.geteuid() == 0
268 return getattr(os, 'geteuid', None) and os.geteuid() == 0
@@ -545,3 +545,63 b' start without repository:'
545 *** runcommand init repo2
545 *** runcommand init repo2
546 *** runcommand id -R repo2
546 *** runcommand id -R repo2
547 000000000000 tip
547 000000000000 tip
548
549
550 unix domain socket:
551
552 $ cd repo
553 $ hg update -q
554
555 #if unix-socket
556
557 >>> import cStringIO
558 >>> from hgclient import unixserver, readchannel, runcommand, check
559 >>> server = unixserver('.hg/server.sock', '.hg/server.log')
560 >>> def hellomessage(conn):
561 ... ch, data = readchannel(conn)
562 ... print '%c, %r' % (ch, data)
563 ... runcommand(conn, ['id'])
564 >>> check(hellomessage, server.connect)
565 o, 'capabilities: getencoding runcommand\nencoding: *' (glob)
566 *** runcommand id
567 eff892de26ec tip bm1/bm2/bm3
568 >>> def unknowncommand(conn):
569 ... readchannel(conn)
570 ... conn.stdin.write('unknowncommand\n')
571 >>> check(unknowncommand, server.connect) # error sent to server.log
572 >>> def serverinput(conn):
573 ... readchannel(conn)
574 ... patch = """
575 ... # HG changeset patch
576 ... # User test
577 ... # Date 0 0
578 ... 2
579 ...
580 ... diff -r eff892de26ec -r 1ed24be7e7a0 a
581 ... --- a/a
582 ... +++ b/a
583 ... @@ -1,1 +1,2 @@
584 ... 1
585 ... +2
586 ... """
587 ... runcommand(conn, ['import', '-'], input=cStringIO.StringIO(patch))
588 ... runcommand(conn, ['log', '-rtip', '-q'])
589 >>> check(serverinput, server.connect)
590 *** runcommand import -
591 applying patch from stdin
592 *** runcommand log -rtip -q
593 2:1ed24be7e7a0
594 >>> server.shutdown()
595
596 $ cat .hg/server.log
597 listening at .hg/server.sock
598 abort: unknown command unknowncommand
599 killed!
600
601 #else
602
603 $ hg serve --cmdserver unix -a .hg/server.sock
604 abort: unsupported platform
605 [255]
606
607 #endif
General Comments 0
You need to be logged in to leave comments. Login now