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