Show More
@@ -53,12 +53,12 b' from . import (' | |||
|
53 | 53 | rewriteutil, |
|
54 | 54 | scmutil, |
|
55 | 55 | server, |
|
56 | sshserver, | |
|
57 | 56 | streamclone, |
|
58 | 57 | tags as tagsmod, |
|
59 | 58 | templatekw, |
|
60 | 59 | ui as uimod, |
|
61 | 60 | util, |
|
61 | wireprotoserver, | |
|
62 | 62 | ) |
|
63 | 63 | |
|
64 | 64 | release = lockmod.release |
@@ -4756,7 +4756,7 b' def serve(ui, repo, **opts):' | |||
|
4756 | 4756 | if repo is None: |
|
4757 | 4757 | raise error.RepoError(_("there is no Mercurial repository here" |
|
4758 | 4758 | " (.hg not found)")) |
|
4759 |
s = |
|
|
4759 | s = wireprotoserver.sshserver(ui, repo) | |
|
4760 | 4760 | s.serve_forever() |
|
4761 | 4761 | |
|
4762 | 4762 | service = server.createservice(ui, repo, opts) |
@@ -8,9 +8,13 b' from __future__ import absolute_import' | |||
|
8 | 8 | |
|
9 | 9 | import cgi |
|
10 | 10 | import struct |
|
11 | import sys | |
|
11 | 12 | |
|
13 | from .i18n import _ | |
|
12 | 14 | from . import ( |
|
15 | encoding, | |
|
13 | 16 | error, |
|
17 | hook, | |
|
14 | 18 | pycompat, |
|
15 | 19 | util, |
|
16 | 20 | wireproto, |
@@ -197,3 +201,114 b' def callhttp(repo, req, cmd):' | |||
|
197 | 201 | req.respond(HTTP_OK, HGERRTYPE, body=rsp) |
|
198 | 202 | return [] |
|
199 | 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 | 6 | import silenttestrunner |
|
7 | 7 | |
|
8 | 8 | from mercurial import ( |
|
9 | sshserver, | |
|
10 | 9 | util, |
|
11 | 10 | wireproto, |
|
11 | wireprotoserver, | |
|
12 | 12 | ) |
|
13 | 13 | |
|
14 | 14 | class SSHServerGetArgsTests(unittest.TestCase): |
@@ -29,7 +29,7 b' class SSHServerGetArgsTests(unittest.Tes' | |||
|
29 | 29 | def mockserver(inbytes): |
|
30 | 30 | ui = mockui(inbytes) |
|
31 | 31 | repo = mockrepo(ui) |
|
32 |
return |
|
|
32 | return wireprotoserver.sshserver(ui, repo) | |
|
33 | 33 | |
|
34 | 34 | class mockrepo(object): |
|
35 | 35 | def __init__(self, ui): |
|
1 | NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now