annotate mercurial/sshserver.py @ 2435:ff2bac730b99

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.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Thu, 15 Jun 2006 12:57:59 -0700
parents b17eebc911ae
children e8c4f3d3df8c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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))