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