PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/mercurial/hgweb/protocol.py

https://bitbucket.org/mirror/mercurial/
Python | 98 lines | 89 code | 3 blank | 6 comment | 0 complexity | 314ae98a048ed3475e93ff7caad68042 MD5 | raw file
Possible License(s): GPL-2.0
  1. #
  2. # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
  3. # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
  4. #
  5. # This software may be used and distributed according to the terms of the
  6. # GNU General Public License version 2 or any later version.
  7. import cgi, cStringIO, zlib, urllib
  8. from mercurial import util, wireproto
  9. from common import HTTP_OK
  10. HGTYPE = 'application/mercurial-0.1'
  11. HGERRTYPE = 'application/hg-error'
  12. class webproto(wireproto.abstractserverproto):
  13. def __init__(self, req, ui):
  14. self.req = req
  15. self.response = ''
  16. self.ui = ui
  17. def getargs(self, args):
  18. knownargs = self._args()
  19. data = {}
  20. keys = args.split()
  21. for k in keys:
  22. if k == '*':
  23. star = {}
  24. for key in knownargs.keys():
  25. if key != 'cmd' and key not in keys:
  26. star[key] = knownargs[key][0]
  27. data['*'] = star
  28. else:
  29. data[k] = knownargs[k][0]
  30. return [data[k] for k in keys]
  31. def _args(self):
  32. args = self.req.form.copy()
  33. chunks = []
  34. i = 1
  35. while True:
  36. h = self.req.env.get('HTTP_X_HGARG_' + str(i))
  37. if h is None:
  38. break
  39. chunks += [h]
  40. i += 1
  41. args.update(cgi.parse_qs(''.join(chunks), keep_blank_values=True))
  42. return args
  43. def getfile(self, fp):
  44. length = int(self.req.env['CONTENT_LENGTH'])
  45. for s in util.filechunkiter(self.req, limit=length):
  46. fp.write(s)
  47. def redirect(self):
  48. self.oldio = self.ui.fout, self.ui.ferr
  49. self.ui.ferr = self.ui.fout = cStringIO.StringIO()
  50. def restore(self):
  51. val = self.ui.fout.getvalue()
  52. self.ui.ferr, self.ui.fout = self.oldio
  53. return val
  54. def groupchunks(self, cg):
  55. z = zlib.compressobj()
  56. while True:
  57. chunk = cg.read(4096)
  58. if not chunk:
  59. break
  60. yield z.compress(chunk)
  61. yield z.flush()
  62. def _client(self):
  63. return 'remote:%s:%s:%s' % (
  64. self.req.env.get('wsgi.url_scheme') or 'http',
  65. urllib.quote(self.req.env.get('REMOTE_HOST', '')),
  66. urllib.quote(self.req.env.get('REMOTE_USER', '')))
  67. def iscmd(cmd):
  68. return cmd in wireproto.commands
  69. def call(repo, req, cmd):
  70. p = webproto(req, repo.ui)
  71. rsp = wireproto.dispatch(repo, p, cmd)
  72. if isinstance(rsp, str):
  73. req.respond(HTTP_OK, HGTYPE, body=rsp)
  74. return []
  75. elif isinstance(rsp, wireproto.streamres):
  76. req.respond(HTTP_OK, HGTYPE)
  77. return rsp.gen
  78. elif isinstance(rsp, wireproto.pushres):
  79. val = p.restore()
  80. rsp = '%d\n%s' % (rsp.res, val)
  81. req.respond(HTTP_OK, HGTYPE, body=rsp)
  82. return []
  83. elif isinstance(rsp, wireproto.pusherr):
  84. # drain the incoming bundle
  85. req.drain()
  86. p.restore()
  87. rsp = '0\n%s\n' % rsp.res
  88. req.respond(HTTP_OK, HGTYPE, body=rsp)
  89. return []
  90. elif isinstance(rsp, wireproto.ooberror):
  91. rsp = rsp.message
  92. req.respond(HTTP_OK, HGERRTYPE, body=rsp)
  93. return []