sshserver.py
152 lines
| 4.2 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 | |||
Matt Mackall
|
r12337 | import util, hook, wireproto, changegroup | ||
Matt Mackall
|
r11596 | import os, sys | ||
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 | ||||
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: | ||||
raise util.Abort("unexpected parameter %r" % arg) | ||||
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 groupchunks(self, changegroup): | ||
Matt Mackall
|
r11584 | while True: | ||
d = changegroup.read(4096) | ||||
if not d: | ||||
break | ||||
Dirkjan Ochtman
|
r11623 | yield d | ||
Matt Mackall
|
r11584 | |||
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 | ||
Dirkjan Ochtman
|
r11625 | for chunk in source.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 != '' | ||
def do_lock(self): | ||||
Vadim Gelfer
|
r2439 | '''DEPRECATED - allowing remote client to lock repo is not safe''' | ||
Vadim Gelfer
|
r2396 | self.lock = self.repo.lock() | ||
Matt Mackall
|
r11580 | return "" | ||
Vadim Gelfer
|
r2396 | |||
def do_unlock(self): | ||||
Vadim Gelfer
|
r2439 | '''DEPRECATED''' | ||
Vadim Gelfer
|
r2396 | if self.lock: | ||
self.lock.release() | ||||
self.lock = None | ||||
Matt Mackall
|
r11580 | return "" | ||
Vadim Gelfer
|
r2396 | |||
def do_addchangegroup(self): | ||||
Vadim Gelfer
|
r2439 | '''DEPRECATED''' | ||
Vadim Gelfer
|
r2396 | if not self.lock: | ||
Dirkjan Ochtman
|
r11622 | self.sendresponse("not locked") | ||
Vadim Gelfer
|
r2396 | return | ||
Dirkjan Ochtman
|
r11622 | self.sendresponse("") | ||
Matt Mackall
|
r12337 | cg = changegroup.unbundle10(self.fin, "UN") | ||
Pierre-Yves David
|
r20933 | r = changegroup.addchangegroup(self.repo, cg, 'serve', self._client()) | ||
Pierre-Yves David
|
r15585 | self.lock.release() | ||
Matt Mackall
|
r11580 | return str(r) | ||
Vadim Gelfer
|
r2439 | |||
Matt Mackall
|
r11593 | def _client(self): | ||
Vadim Gelfer
|
r2673 | client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0] | ||
return 'remote:ssh:' + client | ||||