mercurial/sshserver.py
author Vadim Gelfer <vadim.gelfer@gmail.com>
Thu, 15 Jun 2006 12:57:59 -0700
changeset 2435 ff2bac730b99
parent 2419 b17eebc911ae
child 2439 e8c4f3d3df8c
permissions -rw-r--r--
http client: support persistent connections. uses keepalive module from urlgrabber package. tested against "hg serve", cgi server, and through http proxy. used ethereal to verify that only one tcp connection used during entire "hg pull" sequence. if server supports keepalive, this makes latency of "hg pull" much lower.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2399
cc90dcbdf053 fix comment.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2397
diff changeset
     1
# sshserver.py - ssh protocol server support for mercurial
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     2
#
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     3
# Copyright 2005 Matt Mackall <mpm@selenic.com>
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     4
#
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     7
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     8
from demandload import demandload
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     9
from i18n import gettext as _
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    10
from node import *
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    11
demandload(globals(), "sys util")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    12
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    13
class sshserver(object):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    14
    def __init__(self, ui, repo):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    15
        self.ui = ui
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    16
        self.repo = repo
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    17
        self.lock = None
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    18
        self.fin = sys.stdin
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    19
        self.fout = sys.stdout
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    20
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    21
        sys.stdout = sys.stderr
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    22
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    23
        # Prevent insertion/deletion of CRs
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    24
        util.set_binary(self.fin)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    25
        util.set_binary(self.fout)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    26
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    27
    def getarg(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    28
        argline = self.fin.readline()[:-1]
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    29
        arg, l = argline.split()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    30
        val = self.fin.read(int(l))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    31
        return arg, val
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    32
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    33
    def respond(self, v):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    34
        self.fout.write("%d\n" % len(v))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    35
        self.fout.write(v)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    36
        self.fout.flush()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    37
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    38
    def serve_forever(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    39
        while self.serve_one(): pass
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    40
        sys.exit(0)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    41
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    42
    def serve_one(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    43
        cmd = self.fin.readline()[:-1]
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    44
        if cmd:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    45
            impl = getattr(self, 'do_' + cmd, None)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    46
            if impl: impl()
2397
e9d402506514 merge change to ssh protocol.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2396
diff changeset
    47
            else: self.respond("")
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    48
        return cmd != ''
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    49
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    50
    def do_heads(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    51
        h = self.repo.heads()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    52
        self.respond(" ".join(map(hex, h)) + "\n")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    53
2419
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    54
    def do_hello(self):
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    55
        '''the hello command returns a set of lines describing various
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    56
        interesting things about the server, in an RFC822-like format.
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    57
        Currently the only one defined is "capabilities", which
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    58
        consists of a line in the form:
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    59
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    60
        capabilities: space separated list of tokens
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    61
        '''
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    62
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    63
        r = "capabilities:\n"
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    64
        self.respond(r)
b17eebc911ae Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents: 2399
diff changeset
    65
2396
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    66
    def do_lock(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    67
        self.lock = self.repo.lock()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    68
        self.respond("")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    69
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    70
    def do_unlock(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    71
        if self.lock:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    72
            self.lock.release()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    73
        self.lock = None
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    74
        self.respond("")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    75
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    76
    def do_branches(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    77
        arg, nodes = self.getarg()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    78
        nodes = map(bin, nodes.split(" "))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    79
        r = []
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    80
        for b in self.repo.branches(nodes):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    81
            r.append(" ".join(map(hex, b)) + "\n")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    82
        self.respond("".join(r))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    83
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    84
    def do_between(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    85
        arg, pairs = self.getarg()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    86
        pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    87
        r = []
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    88
        for b in self.repo.between(pairs):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    89
            r.append(" ".join(map(hex, b)) + "\n")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    90
        self.respond("".join(r))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    91
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    92
    def do_changegroup(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    93
        nodes = []
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    94
        arg, roots = self.getarg()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    95
        nodes = map(bin, roots.split(" "))
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    96
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    97
        cg = self.repo.changegroup(nodes, 'serve')
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    98
        while True:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    99
            d = cg.read(4096)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   100
            if not d:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   101
                break
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   102
            self.fout.write(d)
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   103
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   104
        self.fout.flush()
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   105
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   106
    def do_addchangegroup(self):
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   107
        if not self.lock:
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   108
            self.respond("not locked")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   109
            return
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   110
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   111
        self.respond("")
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   112
        r = self.repo.addchangegroup(self.fin, 'serve')
8d44649df03b refactor ssh server.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   113
        self.respond(str(r))