mirror of https://git.sr.ht/~sircmpwn/git.sr.ht
Add debug server support for http cloning
This commit is contained in:
parent
f06d92f9cb
commit
2761ac5688
97
run.py
97
run.py
|
@ -1,4 +1,97 @@
|
|||
import logging
|
||||
import os.path
|
||||
import re
|
||||
import subprocess
|
||||
from srht.config import cfg
|
||||
from werkzeug.exceptions import BadRequest
|
||||
from werkzeug.wrappers import Request, Response
|
||||
from werkzeug.wsgi import wrap_file
|
||||
|
||||
def configure_git_arguments(parser):
|
||||
parser.add_argument('--http-serve', action='store_true',
|
||||
help="Also serve the Git repositories for HTTP cloning.")
|
||||
|
||||
def configure_git_app(app, args):
|
||||
if not args.http_serve:
|
||||
return
|
||||
|
||||
gitreposdir = cfg('git.sr.ht', 'repos')
|
||||
print("Serving git repos from {}".format(gitreposdir))
|
||||
app.wsgi_app = HttpGitRepos(app.wsgi_app, gitreposdir)
|
||||
|
||||
re_git1 = re.compile(
|
||||
r"^.*/objects/([0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+.(pack|idx)).*$")
|
||||
re_git2 = re.compile(
|
||||
r"^.*/(HEAD|info/refs|objects/info/.*|git-(upload|receive)-pack).*$")
|
||||
|
||||
logger = logging.getLogger('werkzeug')
|
||||
|
||||
class HttpGitRepos:
|
||||
def __init__(self, app, reposdir, ssl=None):
|
||||
self._app = app
|
||||
self._reposdir = reposdir
|
||||
self._ssl = None
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
request = Request(environ)
|
||||
|
||||
if re_git1.search(request.path):
|
||||
path = os.path.join(self._reposdir, request.path.lstrip('/'))
|
||||
if os.path.exists(path):
|
||||
f = wrap_file(environ, open(path))
|
||||
return Response(f, direct_passthrough=True)
|
||||
|
||||
if re_git2.search(request.path):
|
||||
subenv = environ.copy()
|
||||
for k in list(subenv.keys()):
|
||||
if (k.startswith('wsgi') or k.startswith('werkzeug') or
|
||||
type(subenv[k]) is not str):
|
||||
del subenv[k]
|
||||
|
||||
subenv['GIT_PROJECT_ROOT'] = self._reposdir
|
||||
subenv['GIT_HTTP_EXPORT_ALL'] = "1"
|
||||
p = subprocess.Popen(['git', 'http-backend'],
|
||||
cwd=self._reposdir, env=subenv, stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
try:
|
||||
stdin = request.data
|
||||
stdout, stderr = p.communicate(input=stdin, timeout=30)
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.warning("Git HTTP backend timed out:")
|
||||
logger.warning(stderr.decode())
|
||||
return BadRequest()(environ, start_response)
|
||||
|
||||
sep = stdout.find(b'\r\n\r\n')
|
||||
headers = []
|
||||
body_start = 0
|
||||
if sep > 0:
|
||||
body_start = sep + 4
|
||||
raw_headers = stdout[:sep].decode()
|
||||
for i, line in enumerate(raw_headers.split('\r\n')):
|
||||
sepidx = line.find(':')
|
||||
if sepidx > 0:
|
||||
headers.append((line[:sepidx], line[sepidx+1:].lstrip()))
|
||||
else:
|
||||
logger.warning("Skipping malformed header: %s" % line)
|
||||
|
||||
if stderr:
|
||||
logger.warning("Errors while serving Git repo:")
|
||||
logger.warning(stderr.decode())
|
||||
body = stdout[body_start:]
|
||||
r = Response(body, headers=headers)
|
||||
return r(environ, start_response)
|
||||
|
||||
return self._app(environ, start_response)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from srht.debug import run_service
|
||||
from srht.debug import configure_static_folder, configure_static_serving
|
||||
from srht.debug import configure_static_arguments, build_parser, run_app
|
||||
from gitsrht.app import app
|
||||
run_service(app)
|
||||
configure_static_folder(app)
|
||||
parser = build_parser(app)
|
||||
configure_static_arguments(parser)
|
||||
configure_git_arguments(parser)
|
||||
args = parser.parse_args()
|
||||
configure_static_serving(app, args)
|
||||
configure_git_app(app, args)
|
||||
run_app(app)
|
||||
|
|
Loading…
Reference in New Issue