gitHTTP.py
Python script, ASCII text executable
1import uuid 2 3from app import app, User, Repo, db, bcrypt 4import os 5import shutil 6import config 7import flask 8import git 9import subprocess 10from flask_httpauth import HTTPBasicAuth 11import zlib 12 13auth = HTTPBasicAuth(realm=config.AUTH_REALM) 14 15 16@auth.verify_password 17def verifyPassword(username, password): 18user = User.query.filter_by(username=username).first() 19 20if user and bcrypt.check_password_hash(user.passwordHashed, password): 21flask.g.user = username 22return True 23 24return False 25 26 27def gitCommand(repo, data, *args): 28if not os.path.isdir(repo): 29raise FileNotFoundError("Repo not found") 30env = os.environ.copy() 31 32command = ["git", *args] 33print("RUNNING GIT COMMAND") 34print(" ".join(command)) 35proc = subprocess.Popen(" ".join(command), cwd=repo, env=env, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 36print(command) 37 38if data: 39proc.stdin.write(data) 40 41out, err = proc.communicate() 42return out 43 44 45@app.route("/git/<username>/<repository>/git-upload-pack", methods=["POST"]) 46@auth.login_required 47def gitUploadPack(username, repository): 48serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git") 49text = gitCommand(serverRepoLocation, flask.request.data, "upload-pack", "--stateless-rpc", ".") 50 51return flask.Response(text, content_type="application/x-git-upload-pack-result") 52 53 54@app.route("/git/<username>/<repository>/git-receive-pack", methods=["POST"]) 55@auth.login_required 56def gitReceivePack(username, repository): 57serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git") 58text = gitCommand(serverRepoLocation, flask.request.data, "receive-pack", "--stateless-rpc", ".") 59 60return flask.Response(text, content_type="application/x-git-receive-pack-result") 61 62 63@app.route("/git/<username>/<repository>/info/refs", methods=["GET"]) 64@auth.login_required 65def gitInfoRefs(username, repository): 66serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git") 67service = flask.request.args.get("service") 68 69if service.startswith("git"): 70service = service[4:] 71 72print(service) 73 74serviceLine = f"# service=git-{service}\n" 75serviceLine = (f"{len(serviceLine) + 4:04x}" + serviceLine).encode() 76 77if service == "upload-pack": 78text = serviceLine + b"0000" + gitCommand(serverRepoLocation, None, "upload-pack", "--stateless-rpc", "--advertise-refs", "--http-backend-info-refs", ".") 79elif service == "receive-pack": 80text = serviceLine + b"0000" + gitCommand(serverRepoLocation, None, "receive-pack", "--http-backend-info-refs", ".") 81 82response = flask.Response(text, content_type=f"application/x-git-{service}-advertisement") 83response.headers["Cache-Control"] = "no-cache" 84 85return response 86 87