Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/sshserver.py @ 11593:d054cc5c7737
protocol: unify unbundle on the server side
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Thu, 15 Jul 2010 11:24:42 -0500 |
parents | 5d907fbb9703 |
children | 67863f9d805f |
rev | line source |
---|---|
2399 | 1 # sshserver.py - ssh protocol server support for mercurial |
2396 | 2 # |
4635
63b9d2deed48
Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4258
diff
changeset
|
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
2859 | 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
2396 | 5 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8109
diff
changeset
|
6 # This software may be used and distributed according to the terms of the |
10263 | 7 # GNU General Public License version 2 or any later version. |
2396 | 8 |
3891 | 9 from i18n import _ |
6211
f89fd07fc51d
Expand import * to allow Pyflakes to find problems
Joel Rosdahl <joel@rosdahl.net>
parents:
5833
diff
changeset
|
10 from node import bin, hex |
11581
4530b3307fb9
protocol: introduce wireproto.py
Matt Mackall <mpm@selenic.com>
parents:
11580
diff
changeset
|
11 import streamclone, util, hook, pushkey, wireproto |
9713
d193cc97c4e8
hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
9198
diff
changeset
|
12 import os, sys, tempfile, urllib, copy |
2396 | 13 |
14 class sshserver(object): | |
9713
d193cc97c4e8
hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
9198
diff
changeset
|
15 |
11369 | 16 caps = 'unbundle lookup changegroupsubset branchmap pushkey'.split() |
9713
d193cc97c4e8
hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
9198
diff
changeset
|
17 |
2396 | 18 def __init__(self, ui, repo): |
19 self.ui = ui | |
20 self.repo = repo | |
21 self.lock = None | |
22 self.fin = sys.stdin | |
23 self.fout = sys.stdout | |
24 | |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4635
diff
changeset
|
25 hook.redirect(True) |
2396 | 26 sys.stdout = sys.stderr |
27 | |
28 # Prevent insertion/deletion of CRs | |
29 util.set_binary(self.fin) | |
30 util.set_binary(self.fout) | |
31 | |
11579 | 32 def getargs(self, args): |
33 data = {} | |
34 keys = args.split() | |
35 count = len(keys) | |
36 for n in xrange(len(keys)): | |
37 argline = self.fin.readline()[:-1] | |
38 arg, l = argline.split() | |
39 val = self.fin.read(int(l)) | |
40 if arg not in keys: | |
41 raise util.Abort("unexpected parameter %r" % arg) | |
42 if arg == '*': | |
43 star = {} | |
44 for n in xrange(int(l)): | |
45 arg, l = argline.split() | |
46 val = self.fin.read(int(l)) | |
47 star[arg] = val | |
48 data['*'] = star | |
49 else: | |
50 data[arg] = val | |
51 return [data[k] for k in keys] | |
52 | |
53 def getarg(self, name): | |
54 return self.getargs(name)[0] | |
2396 | 55 |
56 def respond(self, v): | |
57 self.fout.write("%d\n" % len(v)) | |
58 self.fout.write(v) | |
59 self.fout.flush() | |
60 | |
11584
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
61 def sendchangegroup(self, changegroup): |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
62 while True: |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
63 d = changegroup.read(4096) |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
64 if not d: |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
65 break |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
66 self.fout.write(d) |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
67 |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
68 self.fout.flush() |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
69 |
11585
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
70 def sendstream(self, source): |
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
71 for chunk in source: |
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
72 self.fout.write(chunk) |
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
73 self.fout.flush() |
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
74 |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
75 def getfile(self, fpout): |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
76 self.respond('') |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
77 count = int(self.fin.readline()) |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
78 while count: |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
79 fpout.write(self.fin.read(count)) |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
80 count = int(self.fin.readline()) |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
81 |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
82 def redirect(self): |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
83 pass |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
84 |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
85 def respondpush(self, ret): |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
86 self.respond('') |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
87 self.respond(str(ret)) |
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
88 |
2396 | 89 def serve_forever(self): |
8109
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
90 try: |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
91 while self.serve_one(): |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
92 pass |
8109
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
93 finally: |
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
94 if self.lock is not None: |
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
95 self.lock.release() |
2396 | 96 sys.exit(0) |
97 | |
98 def serve_one(self): | |
99 cmd = self.fin.readline()[:-1] | |
11581
4530b3307fb9
protocol: introduce wireproto.py
Matt Mackall <mpm@selenic.com>
parents:
11580
diff
changeset
|
100 if cmd and not wireproto.dispatch(self.repo, self, cmd): |
2396 | 101 impl = getattr(self, 'do_' + cmd, None) |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
102 if impl: |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
103 r = impl() |
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
104 if r is not None: |
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
105 self.respond(r) |
2397
e9d402506514
merge change to ssh protocol.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2396
diff
changeset
|
106 else: self.respond("") |
2396 | 107 return cmd != '' |
108 | |
2419
b17eebc911ae
Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents:
2399
diff
changeset
|
109 def do_hello(self): |
b17eebc911ae
Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents:
2399
diff
changeset
|
110 '''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
|
111 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
|
112 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
|
113 consists of a line in the form: |
b17eebc911ae
Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents:
2399
diff
changeset
|
114 |
b17eebc911ae
Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents:
2399
diff
changeset
|
115 capabilities: space separated list of tokens |
b17eebc911ae
Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents:
2399
diff
changeset
|
116 ''' |
9713
d193cc97c4e8
hgweb/sshserver: extract capabilities for easier modification
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
9198
diff
changeset
|
117 caps = copy.copy(self.caps) |
10377
04e1e6743809
streamclone: allow uncompressed clones by default
Matt Mackall <mpm@selenic.com>
parents:
10282
diff
changeset
|
118 if streamclone.allowed(self.repo.ui): |
4258
b11a2fb59cf5
revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents:
3891
diff
changeset
|
119 caps.append('stream=%d' % self.repo.changelog.version) |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
120 return "capabilities: %s\n" % (' '.join(caps),) |
2419
b17eebc911ae
Initial implementation of hello command for ssh
Matt Mackall <mpm@selenic.com>
parents:
2399
diff
changeset
|
121 |
2396 | 122 def do_lock(self): |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
123 '''DEPRECATED - allowing remote client to lock repo is not safe''' |
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
124 |
2396 | 125 self.lock = self.repo.lock() |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
126 return "" |
2396 | 127 |
128 def do_unlock(self): | |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
129 '''DEPRECATED''' |
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
130 |
2396 | 131 if self.lock: |
132 self.lock.release() | |
133 self.lock = None | |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
134 return "" |
2396 | 135 |
136 def do_addchangegroup(self): | |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
137 '''DEPRECATED''' |
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
138 |
2396 | 139 if not self.lock: |
140 self.respond("not locked") | |
141 return | |
142 | |
143 self.respond("") | |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
144 r = self.repo.addchangegroup(self.fin, 'serve', self._client(), |
11442
ee1ed6afac21
addchangegroup: pass in lock to release it before changegroup hook is called
Matt Mackall <mpm@selenic.com>
parents:
11369
diff
changeset
|
145 lock=self.lock) |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
146 return str(r) |
2439
e8c4f3d3df8c
extend network protocol to stop clients from locking servers
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2419
diff
changeset
|
147 |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
148 def _client(self): |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2622
diff
changeset
|
149 client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0] |
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2622
diff
changeset
|
150 return 'remote:ssh:' + client |