sshserver.py
134 lines
| 3.6 KiB
| text/x-python
|
PythonLexer
/ mercurial / sshserver.py
|
r2399 | # sshserver.py - ssh protocol server support for mercurial | ||
|
r2396 | # | ||
|
r4635 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> | ||
|
r2859 | # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | ||
|
r2396 | # | ||
|
r8225 | # This software may be used and distributed according to the terms of the | ||
|
r10263 | # GNU General Public License version 2 or any later version. | ||
|
r2396 | |||
|
r25976 | from __future__ import absolute_import | ||
import os | ||||
import sys | ||||
|
r29389 | from .i18n import _ | ||
|
r25976 | from . import ( | ||
|
r26587 | error, | ||
|
r25976 | hook, | ||
util, | ||||
wireproto, | ||||
) | ||||
|
r2396 | |||
|
r20903 | class sshserver(wireproto.abstractserverproto): | ||
|
r2396 | def __init__(self, ui, repo): | ||
self.ui = ui | ||||
self.repo = repo | ||||
self.lock = None | ||||
|
r14614 | self.fin = ui.fin | ||
self.fout = ui.fout | ||||
|
r2396 | |||
|
r5833 | hook.redirect(True) | ||
|
r14614 | ui.fout = repo.ui.fout = ui.ferr | ||
|
r2396 | |||
# Prevent insertion/deletion of CRs | ||||
|
r14233 | util.setbinary(self.fin) | ||
util.setbinary(self.fout) | ||||
|
r2396 | |||
|
r11579 | def getargs(self, args): | ||
data = {} | ||||
keys = args.split() | ||||
for n in xrange(len(keys)): | ||||
argline = self.fin.readline()[:-1] | ||||
arg, l = argline.split() | ||||
if arg not in keys: | ||||
|
r29389 | raise error.Abort(_("unexpected parameter %r") % arg) | ||
|
r11579 | if arg == '*': | ||
star = {} | ||||
|
r13721 | for k in xrange(int(l)): | ||
argline = self.fin.readline()[:-1] | ||||
|
r11579 | arg, l = argline.split() | ||
val = self.fin.read(int(l)) | ||||
star[arg] = val | ||||
data['*'] = star | ||||
else: | ||||
|
r13721 | val = self.fin.read(int(l)) | ||
|
r11579 | data[arg] = val | ||
return [data[k] for k in keys] | ||||
def getarg(self, name): | ||||
return self.getargs(name)[0] | ||||
|
r2396 | |||
|
r11621 | def getfile(self, fpout): | ||
|
r11622 | self.sendresponse('') | ||
|
r11621 | count = int(self.fin.readline()) | ||
while count: | ||||
fpout.write(self.fin.read(count)) | ||||
count = int(self.fin.readline()) | ||||
def redirect(self): | ||||
pass | ||||
|
r11623 | def sendresponse(self, v): | ||
self.fout.write("%d\n" % len(v)) | ||||
self.fout.write(v) | ||||
|
r11584 | self.fout.flush() | ||
|
r11585 | def sendstream(self, source): | ||
|
r17563 | write = self.fout.write | ||
|
r30466 | |||
if source.reader: | ||||
gen = iter(lambda: source.reader.read(4096), '') | ||||
else: | ||||
gen = source.gen | ||||
for chunk in gen: | ||||
|
r17563 | write(chunk) | ||
|
r11585 | self.fout.flush() | ||
|
r11625 | def sendpushresponse(self, rsp): | ||
|
r11622 | self.sendresponse('') | ||
|
r11625 | self.sendresponse(str(rsp.res)) | ||
|
r11593 | |||
|
r12703 | def sendpusherror(self, rsp): | ||
self.sendresponse(rsp.res) | ||||
|
r15017 | def sendooberror(self, rsp): | ||
self.ui.ferr.write('%s\n-\n' % rsp.message) | ||||
self.ui.ferr.flush() | ||||
self.fout.write('\n') | ||||
self.fout.flush() | ||||
|
r2396 | def serve_forever(self): | ||
|
r8109 | try: | ||
|
r10282 | while self.serve_one(): | ||
pass | ||||
|
r8109 | finally: | ||
if self.lock is not None: | ||||
self.lock.release() | ||||
|
r2396 | sys.exit(0) | ||
|
r11625 | handlers = { | ||
str: sendresponse, | ||||
wireproto.streamres: sendstream, | ||||
wireproto.pushres: sendpushresponse, | ||||
|
r12703 | wireproto.pusherr: sendpusherror, | ||
|
r15017 | wireproto.ooberror: sendooberror, | ||
|
r11625 | } | ||
|
r2396 | def serve_one(self): | ||
cmd = self.fin.readline()[:-1] | ||||
|
r11618 | if cmd and cmd in wireproto.commands: | ||
|
r11625 | rsp = wireproto.dispatch(self.repo, self, cmd) | ||
self.handlers[rsp.__class__](self, rsp) | ||||
|
r11618 | elif cmd: | ||
|
r2396 | impl = getattr(self, 'do_' + cmd, None) | ||
|
r10282 | if impl: | ||
|
r11580 | r = impl() | ||
if r is not None: | ||||
|
r11622 | self.sendresponse(r) | ||
else: self.sendresponse("") | ||||
|
r2396 | return cmd != '' | ||
|
r11593 | def _client(self): | ||
|
r2673 | client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0] | ||
return 'remote:ssh:' + client | ||||