mercurial/sshserver.py
branchstable
changeset 37788 ed5448edcbfa
parent 37287 fb92df8b634c
parent 37787 92213f6745ed
child 37789 bfd32db06952
equal deleted inserted replaced
37287:fb92df8b634c 37788:ed5448edcbfa
     1 # sshserver.py - ssh protocol server support for mercurial
       
     2 #
       
     3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
       
     4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
       
     5 #
       
     6 # This software may be used and distributed according to the terms of the
       
     7 # GNU General Public License version 2 or any later version.
       
     8 
       
     9 from __future__ import absolute_import
       
    10 
       
    11 import sys
       
    12 
       
    13 from .i18n import _
       
    14 from . import (
       
    15     encoding,
       
    16     error,
       
    17     hook,
       
    18     util,
       
    19     wireproto,
       
    20 )
       
    21 
       
    22 class sshserver(wireproto.abstractserverproto):
       
    23     def __init__(self, ui, repo):
       
    24         self.ui = ui
       
    25         self.repo = repo
       
    26         self.lock = None
       
    27         self.fin = ui.fin
       
    28         self.fout = ui.fout
       
    29         self.name = 'ssh'
       
    30 
       
    31         hook.redirect(True)
       
    32         ui.fout = repo.ui.fout = ui.ferr
       
    33 
       
    34         # Prevent insertion/deletion of CRs
       
    35         util.setbinary(self.fin)
       
    36         util.setbinary(self.fout)
       
    37 
       
    38     def getargs(self, args):
       
    39         data = {}
       
    40         keys = args.split()
       
    41         for n in xrange(len(keys)):
       
    42             argline = self.fin.readline()[:-1]
       
    43             arg, l = argline.split()
       
    44             if arg not in keys:
       
    45                 raise error.Abort(_("unexpected parameter %r") % arg)
       
    46             if arg == '*':
       
    47                 star = {}
       
    48                 for k in xrange(int(l)):
       
    49                     argline = self.fin.readline()[:-1]
       
    50                     arg, l = argline.split()
       
    51                     val = self.fin.read(int(l))
       
    52                     star[arg] = val
       
    53                 data['*'] = star
       
    54             else:
       
    55                 val = self.fin.read(int(l))
       
    56                 data[arg] = val
       
    57         return [data[k] for k in keys]
       
    58 
       
    59     def getarg(self, name):
       
    60         return self.getargs(name)[0]
       
    61 
       
    62     def getfile(self, fpout):
       
    63         self.sendresponse('')
       
    64         count = int(self.fin.readline())
       
    65         while count:
       
    66             fpout.write(self.fin.read(count))
       
    67             count = int(self.fin.readline())
       
    68 
       
    69     def redirect(self):
       
    70         pass
       
    71 
       
    72     def sendresponse(self, v):
       
    73         self.fout.write("%d\n" % len(v))
       
    74         self.fout.write(v)
       
    75         self.fout.flush()
       
    76 
       
    77     def sendstream(self, source):
       
    78         write = self.fout.write
       
    79         for chunk in source.gen:
       
    80             write(chunk)
       
    81         self.fout.flush()
       
    82 
       
    83     def sendpushresponse(self, rsp):
       
    84         self.sendresponse('')
       
    85         self.sendresponse(str(rsp.res))
       
    86 
       
    87     def sendpusherror(self, rsp):
       
    88         self.sendresponse(rsp.res)
       
    89 
       
    90     def sendooberror(self, rsp):
       
    91         self.ui.ferr.write('%s\n-\n' % rsp.message)
       
    92         self.ui.ferr.flush()
       
    93         self.fout.write('\n')
       
    94         self.fout.flush()
       
    95 
       
    96     def serve_forever(self):
       
    97         try:
       
    98             while self.serve_one():
       
    99                 pass
       
   100         finally:
       
   101             if self.lock is not None:
       
   102                 self.lock.release()
       
   103         sys.exit(0)
       
   104 
       
   105     handlers = {
       
   106         str: sendresponse,
       
   107         wireproto.streamres: sendstream,
       
   108         wireproto.streamres_legacy: sendstream,
       
   109         wireproto.pushres: sendpushresponse,
       
   110         wireproto.pusherr: sendpusherror,
       
   111         wireproto.ooberror: sendooberror,
       
   112     }
       
   113 
       
   114     def serve_one(self):
       
   115         cmd = self.fin.readline()[:-1]
       
   116         if cmd and cmd in wireproto.commands:
       
   117             rsp = wireproto.dispatch(self.repo, self, cmd)
       
   118             self.handlers[rsp.__class__](self, rsp)
       
   119         elif cmd:
       
   120             impl = getattr(self, 'do_' + cmd, None)
       
   121             if impl:
       
   122                 r = impl()
       
   123                 if r is not None:
       
   124                     self.sendresponse(r)
       
   125             else:
       
   126                 self.sendresponse("")
       
   127         return cmd != ''
       
   128 
       
   129     def _client(self):
       
   130         client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
       
   131         return 'remote:ssh:' + client