By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

 gitHTTP.py

View raw Download
text/x-script.python • 3.37 kiB
Python script, ASCII text executable
        
            
1
import uuid
2
3
from app import app, User, Repo, Commit, db, bcrypt
4
import os
5
import shutil
6
import config
7
import flask
8
import git
9
import subprocess
10
from flask_httpauth import HTTPBasicAuth
11
import zlib
12
import re
13
import datetime
14
15
auth = HTTPBasicAuth(realm=config.AUTH_REALM)
16
17
18
@auth.verify_password
19
def verifyPassword(username, password):
20
user = User.query.filter_by(username=username).first()
21
22
if user and bcrypt.check_password_hash(user.passwordHashed, password):
23
flask.g.user = username
24
return True
25
26
return False
27
28
29
def gitCommand(repo, data, *args):
30
if not os.path.isdir(repo):
31
raise FileNotFoundError("Repo not found")
32
env = os.environ.copy()
33
34
command = ["git", *args]
35
36
proc = subprocess.Popen(" ".join(command), cwd=repo, env=env, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
37
print(command)
38
39
if data:
40
proc.stdin.write(data)
41
42
out, err = proc.communicate()
43
return out
44
45
46
@app.route("/git/<username>/<repository>/git-upload-pack", methods=["POST"])
47
@auth.login_required
48
def gitUploadPack(username, repository):
49
serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git")
50
text = gitCommand(serverRepoLocation, flask.request.data, "upload-pack", "--stateless-rpc", ".")
51
52
return flask.Response(text, content_type="application/x-git-upload-pack-result")
53
54
55
@app.route("/git/<username>/<repository>/git-receive-pack", methods=["POST"])
56
@auth.login_required
57
def gitReceivePack(username, repository):
58
serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git")
59
text = gitCommand(serverRepoLocation, flask.request.data, "receive-pack", "--stateless-rpc", ".")
60
61
sha = flask.request.data.split(b" ", 2)[1].decode()
62
info = gitCommand(serverRepoLocation, None, "show", "-s", "--format='%H%n%at%n%cn <%ce>%n%B'").decode()
63
64
if re.match("[0-9a-fA-F]", info[:40]):
65
print(info.split("\n", 4))
66
sha, time, identity, *body = info.split("\n", 4)
67
body = "\n".join("body")
68
login = flask.g.user
69
70
user = User.query.filter_by(username=login).first()
71
repo = Repo.query.filter_by(route=f"/{username}/{repository}").first()
72
commit = Commit(sha, user, repo, time, body, identity)
73
74
db.session.add(commit)
75
db.session.commit()
76
77
return flask.Response(text, content_type="application/x-git-receive-pack-result")
78
79
80
@app.route("/git/<username>/<repository>/info/refs", methods=["GET"])
81
@auth.login_required
82
def gitInfoRefs(username, repository):
83
serverRepoLocation = os.path.join(config.REPOS_PATH, username, repository, ".git")
84
service = flask.request.args.get("service")
85
86
if service.startswith("git"):
87
service = service[4:]
88
89
print(service)
90
91
serviceLine = f"# service=git-{service}\n"
92
serviceLine = (f"{len(serviceLine) + 4:04x}" + serviceLine).encode()
93
94
if service == "upload-pack":
95
text = serviceLine + b"0000" + gitCommand(serverRepoLocation, None, "upload-pack", "--stateless-rpc", "--advertise-refs", "--http-backend-info-refs", ".")
96
elif service == "receive-pack":
97
text = serviceLine + b"0000" + gitCommand(serverRepoLocation, None, "receive-pack", "--http-backend-info-refs", ".")
98
else:
99
flask.abort(403)
100
101
response = flask.Response(text, content_type=f"application/x-git-{service}-advertisement")
102
response.headers["Cache-Control"] = "no-cache"
103
104
return response
105
106