Show More
@@ -53,12 +53,12 b' from . import (' | |||||
53 | rewriteutil, |
|
53 | rewriteutil, | |
54 | scmutil, |
|
54 | scmutil, | |
55 | server, |
|
55 | server, | |
56 | sshserver, |
|
|||
57 | streamclone, |
|
56 | streamclone, | |
58 | tags as tagsmod, |
|
57 | tags as tagsmod, | |
59 | templatekw, |
|
58 | templatekw, | |
60 | ui as uimod, |
|
59 | ui as uimod, | |
61 | util, |
|
60 | util, | |
|
61 | wireprotoserver, | |||
62 | ) |
|
62 | ) | |
63 |
|
63 | |||
64 | release = lockmod.release |
|
64 | release = lockmod.release | |
@@ -4756,7 +4756,7 b' def serve(ui, repo, **opts):' | |||||
4756 | if repo is None: |
|
4756 | if repo is None: | |
4757 | raise error.RepoError(_("there is no Mercurial repository here" |
|
4757 | raise error.RepoError(_("there is no Mercurial repository here" | |
4758 | " (.hg not found)")) |
|
4758 | " (.hg not found)")) | |
4759 |
s = |
|
4759 | s = wireprotoserver.sshserver(ui, repo) | |
4760 | s.serve_forever() |
|
4760 | s.serve_forever() | |
4761 |
|
4761 | |||
4762 | service = server.createservice(ui, repo, opts) |
|
4762 | service = server.createservice(ui, repo, opts) |
@@ -8,9 +8,13 b' from __future__ import absolute_import' | |||||
8 |
|
8 | |||
9 | import cgi |
|
9 | import cgi | |
10 | import struct |
|
10 | import struct | |
|
11 | import sys | |||
11 |
|
12 | |||
|
13 | from .i18n import _ | |||
12 | from . import ( |
|
14 | from . import ( | |
|
15 | encoding, | |||
13 | error, |
|
16 | error, | |
|
17 | hook, | |||
14 | pycompat, |
|
18 | pycompat, | |
15 | util, |
|
19 | util, | |
16 | wireproto, |
|
20 | wireproto, | |
@@ -197,3 +201,114 b' def callhttp(repo, req, cmd):' | |||||
197 | req.respond(HTTP_OK, HGERRTYPE, body=rsp) |
|
201 | req.respond(HTTP_OK, HGERRTYPE, body=rsp) | |
198 | return [] |
|
202 | return [] | |
199 | raise error.ProgrammingError('hgweb.protocol internal failure', rsp) |
|
203 | raise error.ProgrammingError('hgweb.protocol internal failure', rsp) | |
|
204 | ||||
|
205 | class sshserver(wireproto.abstractserverproto): | |||
|
206 | def __init__(self, ui, repo): | |||
|
207 | self.ui = ui | |||
|
208 | self.repo = repo | |||
|
209 | self.lock = None | |||
|
210 | self.fin = ui.fin | |||
|
211 | self.fout = ui.fout | |||
|
212 | self.name = 'ssh' | |||
|
213 | ||||
|
214 | hook.redirect(True) | |||
|
215 | ui.fout = repo.ui.fout = ui.ferr | |||
|
216 | ||||
|
217 | # Prevent insertion/deletion of CRs | |||
|
218 | util.setbinary(self.fin) | |||
|
219 | util.setbinary(self.fout) | |||
|
220 | ||||
|
221 | def getargs(self, args): | |||
|
222 | data = {} | |||
|
223 | keys = args.split() | |||
|
224 | for n in xrange(len(keys)): | |||
|
225 | argline = self.fin.readline()[:-1] | |||
|
226 | arg, l = argline.split() | |||
|
227 | if arg not in keys: | |||
|
228 | raise error.Abort(_("unexpected parameter %r") % arg) | |||
|
229 | if arg == '*': | |||
|
230 | star = {} | |||
|
231 | for k in xrange(int(l)): | |||
|
232 | argline = self.fin.readline()[:-1] | |||
|
233 | arg, l = argline.split() | |||
|
234 | val = self.fin.read(int(l)) | |||
|
235 | star[arg] = val | |||
|
236 | data['*'] = star | |||
|
237 | else: | |||
|
238 | val = self.fin.read(int(l)) | |||
|
239 | data[arg] = val | |||
|
240 | return [data[k] for k in keys] | |||
|
241 | ||||
|
242 | def getarg(self, name): | |||
|
243 | return self.getargs(name)[0] | |||
|
244 | ||||
|
245 | def getfile(self, fpout): | |||
|
246 | self.sendresponse('') | |||
|
247 | count = int(self.fin.readline()) | |||
|
248 | while count: | |||
|
249 | fpout.write(self.fin.read(count)) | |||
|
250 | count = int(self.fin.readline()) | |||
|
251 | ||||
|
252 | def redirect(self): | |||
|
253 | pass | |||
|
254 | ||||
|
255 | def sendresponse(self, v): | |||
|
256 | self.fout.write("%d\n" % len(v)) | |||
|
257 | self.fout.write(v) | |||
|
258 | self.fout.flush() | |||
|
259 | ||||
|
260 | def sendstream(self, source): | |||
|
261 | write = self.fout.write | |||
|
262 | for chunk in source.gen: | |||
|
263 | write(chunk) | |||
|
264 | self.fout.flush() | |||
|
265 | ||||
|
266 | def sendpushresponse(self, rsp): | |||
|
267 | self.sendresponse('') | |||
|
268 | self.sendresponse(str(rsp.res)) | |||
|
269 | ||||
|
270 | def sendpusherror(self, rsp): | |||
|
271 | self.sendresponse(rsp.res) | |||
|
272 | ||||
|
273 | def sendooberror(self, rsp): | |||
|
274 | self.ui.ferr.write('%s\n-\n' % rsp.message) | |||
|
275 | self.ui.ferr.flush() | |||
|
276 | self.fout.write('\n') | |||
|
277 | self.fout.flush() | |||
|
278 | ||||
|
279 | def serve_forever(self): | |||
|
280 | try: | |||
|
281 | while self.serve_one(): | |||
|
282 | pass | |||
|
283 | finally: | |||
|
284 | if self.lock is not None: | |||
|
285 | self.lock.release() | |||
|
286 | sys.exit(0) | |||
|
287 | ||||
|
288 | handlers = { | |||
|
289 | str: sendresponse, | |||
|
290 | wireproto.streamres: sendstream, | |||
|
291 | wireproto.streamres_legacy: sendstream, | |||
|
292 | wireproto.pushres: sendpushresponse, | |||
|
293 | wireproto.pusherr: sendpusherror, | |||
|
294 | wireproto.ooberror: sendooberror, | |||
|
295 | } | |||
|
296 | ||||
|
297 | def serve_one(self): | |||
|
298 | cmd = self.fin.readline()[:-1] | |||
|
299 | if cmd and cmd in wireproto.commands: | |||
|
300 | rsp = wireproto.dispatch(self.repo, self, cmd) | |||
|
301 | self.handlers[rsp.__class__](self, rsp) | |||
|
302 | elif cmd: | |||
|
303 | impl = getattr(self, 'do_' + cmd, None) | |||
|
304 | if impl: | |||
|
305 | r = impl() | |||
|
306 | if r is not None: | |||
|
307 | self.sendresponse(r) | |||
|
308 | else: | |||
|
309 | self.sendresponse("") | |||
|
310 | return cmd != '' | |||
|
311 | ||||
|
312 | def _client(self): | |||
|
313 | client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0] | |||
|
314 | return 'remote:ssh:' + client |
@@ -6,9 +6,9 b' import unittest' | |||||
6 | import silenttestrunner |
|
6 | import silenttestrunner | |
7 |
|
7 | |||
8 | from mercurial import ( |
|
8 | from mercurial import ( | |
9 | sshserver, |
|
|||
10 | util, |
|
9 | util, | |
11 | wireproto, |
|
10 | wireproto, | |
|
11 | wireprotoserver, | |||
12 | ) |
|
12 | ) | |
13 |
|
13 | |||
14 | class SSHServerGetArgsTests(unittest.TestCase): |
|
14 | class SSHServerGetArgsTests(unittest.TestCase): | |
@@ -29,7 +29,7 b' class SSHServerGetArgsTests(unittest.Tes' | |||||
29 | def mockserver(inbytes): |
|
29 | def mockserver(inbytes): | |
30 | ui = mockui(inbytes) |
|
30 | ui = mockui(inbytes) | |
31 | repo = mockrepo(ui) |
|
31 | repo = mockrepo(ui) | |
32 |
return |
|
32 | return wireprotoserver.sshserver(ui, repo) | |
33 |
|
33 | |||
34 | class mockrepo(object): |
|
34 | class mockrepo(object): | |
35 | def __init__(self, ui): |
|
35 | def __init__(self, ui): |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now