You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.7 KiB

5 years ago
5 years ago
5 years ago
  1. # -*- coding: utf-8 -*-
  2. import subprocess, os, io
  3. from odoo import http
  4. from odoo.tools import config
  5. import werkzeug
  6. from ..http_chunked_fix import http_input_stream
  7. class Main(http.Controller):
  8. def authorize(self, request):
  9. auth = request.httprequest.authorization
  10. if auth:
  11. request.session.authenticate(request.session.db, auth.username, auth.password)
  12. @http.route(
  13. [
  14. '/git/<repo>',
  15. '/git/<repo>/<path:path>',
  16. ],
  17. auth='public',
  18. csrf=False
  19. )
  20. def git(self, request, repo, **kw):
  21. self.authorize(request)
  22. if not request.env.uid or request.env.user.login == 'public':
  23. return werkzeug.Response(
  24. headers=[('WWW-Authenticate', 'Basic')],
  25. status=401
  26. )
  27. try:
  28. repository = request.env['galicea_git.repository'].search(
  29. [('system_name', '=', repo)]
  30. )
  31. except AccessError:
  32. return werkzeug.Response(
  33. status=403
  34. )
  35. if not repository.exists():
  36. return werkzeug.Response(
  37. status=404
  38. )
  39. http_environment = request.httprequest.environ
  40. git_env = {
  41. 'REQUEST_METHOD': http_environment['REQUEST_METHOD'],
  42. 'QUERY_STRING': http_environment['QUERY_STRING'],
  43. 'CONTENT_TYPE': request.httprequest.headers.get('Content-Type'),
  44. 'REMOTE_ADDR': http_environment['REMOTE_ADDR'],
  45. 'GIT_PROJECT_ROOT': os.path.join(config['data_dir'], 'git'),
  46. 'GIT_HTTP_EXPORT_ALL': '1',
  47. 'PATH_INFO': http_environment['PATH_INFO'][4:],
  48. 'REMOTE_USER': request.env.user.login
  49. }
  50. command_env = os.environ.copy()
  51. for var in git_env:
  52. command_env[var] = git_env[var]
  53. git = subprocess.Popen(
  54. ['/usr/lib/git-core/git-http-backend'],
  55. stdin=subprocess.PIPE,
  56. stdout=subprocess.PIPE,
  57. stderr=subprocess.PIPE,
  58. env=command_env,
  59. shell=True
  60. )
  61. stdout, stderr = git.communicate(http_input_stream(request).read())
  62. headers_str, body = stdout.split(b"\r\n\r\n", 2)
  63. http_status_code = 200
  64. headers = []
  65. for header in headers_str.split(b"\r\n"):
  66. name, value = header.split(b': ', 2)
  67. if name == 'Status':
  68. http_code = int(value.split(b' ')[0])
  69. else:
  70. headers.append((name.decode('ascii'), value.decode('ascii')))
  71. return werkzeug.Response(
  72. body,
  73. status = http_status_code,
  74. headers = headers
  75. )