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

 gitme.py

View raw Download
text/x-script.python • 7.84 kiB
Python script, ASCII text executable
        
            
1
import os
2
import flask
3
import git
4
import mimetypes
5
import magic
6
from markupsafe import escape
7
8
import config
9
10
app = flask.Flask(__name__)
11
import gitHTTP
12
13
mime = magic.Magic(mime=True)
14
15
16
def humanSize(value, decimals=2, scale=1024, units=("B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB")):
17
for unit in units:
18
if value < scale:
19
break
20
value /= scale
21
if int(value) == value:
22
# do not return decimals, if the value is already round
23
return int(value), unit
24
return round(value * 10**decimals) / 10**decimals, unit
25
26
27
def guessMIME(path):
28
if os.path.isdir(path):
29
mimetype = "inode/directory"
30
elif mime.from_file(path):
31
mimetype = mime.from_file(path)
32
else:
33
mimetype = "application/octet-stream"
34
return mimetype
35
36
37
def convertToHTML(path):
38
with open(path, "r") as f:
39
contents = f.read()
40
return contents
41
42
43
@app.route("/")
44
def main():
45
return flask.render_template("home.html", title="gitme")
46
47
48
@app.route("/accounts/", methods=["GET", "POST"])
49
def login():
50
return flask.render_template("login.html", title="gitme")
51
52
53
@app.route("/<username>/")
54
def userProfile(username):
55
return flask.render_template("teapot.html"), 418
56
57
58
@app.route("/<username>/<repository>/")
59
def repositoryIndex(username, repository):
60
return flask.redirect("./tree", code=302)
61
62
63
@app.route("/<username>/<repository>/raw/<branch>/<path:subpath>")
64
def repositoryRaw(username, repository, branch, subpath):
65
serverRepoLocation = os.path.join(config.REPOS_PATH, os.path.join(username, repository))
66
67
app.logger.info(f"Loading {serverRepoLocation}")
68
69
if not os.path.exists(serverRepoLocation):
70
app.logger.error(f"Cannot load {serverRepoLocation}")
71
return flask.render_template("not-found.html"), 404
72
73
repo = git.Repo(serverRepoLocation)
74
try:
75
repo.git.checkout(branch)
76
except git.exc.GitCommandError:
77
return flask.render_template("not-found.html"), 404
78
79
return flask.send_from_directory(config.REPOS_PATH, os.path.join(username, repository, subpath))
80
81
82
@app.route("/<username>/<repository>/tree/", defaults={"branch": None, "subpath": ""})
83
@app.route("/<username>/<repository>/tree/<branch>/", defaults={"subpath": ""})
84
@app.route("/<username>/<repository>/tree/<branch>/<path:subpath>")
85
def repositoryTree(username, repository, branch, subpath):
86
serverRepoLocation = os.path.join(config.REPOS_PATH, os.path.join(username, repository))
87
88
app.logger.info(f"Loading {serverRepoLocation}")
89
90
if not os.path.exists(serverRepoLocation):
91
app.logger.error(f"Cannot load {serverRepoLocation}")
92
return flask.render_template("not-found.html"), 404
93
94
repo = git.Repo(serverRepoLocation)
95
if not branch:
96
branch = repo.heads[0].name
97
return flask.redirect(f"./{branch}", code=302)
98
try:
99
repo.git.checkout(branch)
100
except git.exc.GitCommandError:
101
return flask.render_template("not-found.html"), 404
102
103
branches = repo.heads
104
if os.path.isdir(os.path.join(serverRepoLocation, subpath)):
105
files = []
106
blobs = []
107
108
for entry in os.listdir(os.path.join(serverRepoLocation, subpath)):
109
if not os.path.basename(entry) == ".git":
110
files.append(os.path.join(subpath, entry))
111
112
infos = []
113
114
for file in files:
115
path = os.path.join(serverRepoLocation, file)
116
mimetype = guessMIME(path)
117
118
info = {
119
"name": os.path.basename(file),
120
"serverPath": path,
121
"relativePath": file,
122
"link": os.path.join(f"/{username}/{repository}/tree/{branch}/", file),
123
"size": humanSize(os.path.getsize(path)),
124
"mimetype": f"{mimetype}{f' ({mimetypes.guess_type(path)[1]})' if mimetypes.guess_type(path)[1] else ''}",
125
}
126
127
specialIcon = config.matchIcon(os.path.basename(file))
128
if specialIcon:
129
info["icon"] = specialIcon
130
elif os.path.isdir(path):
131
info["icon"] = config.folderIcon
132
elif mimetypes.guess_type(path)[0] in config.fileIcons:
133
info["icon"] = config.fileIcons[mimetypes.guess_type(path)[0]]
134
else:
135
info["icon"] = config.unknownIcon
136
137
if os.path.isdir(path):
138
infos.insert(0, info)
139
else:
140
infos.append(info)
141
142
return flask.render_template(
143
"repo-tree.html",
144
username=username,
145
repository=repository,
146
files=infos,
147
subpath=os.path.join("/", subpath),
148
branches=branches,
149
current=branch
150
)
151
else:
152
path = os.path.join(serverRepoLocation, subpath)
153
154
if not os.path.exists(path):
155
return flask.render_template("not-found.html"), 404
156
157
mimetype = guessMIME(path)
158
mode = mimetype.split("/", 1)[0]
159
size = humanSize(os.path.getsize(path))
160
161
specialIcon = config.matchIcon(os.path.basename(path))
162
if specialIcon:
163
icon = specialIcon
164
elif os.path.isdir(path):
165
icon = config.folderIcon
166
elif mimetypes.guess_type(path)[0] in config.fileIcons:
167
icon = config.fileIcons[mimetypes.guess_type(path)[0]]
168
else:
169
icon = config.unknownIcon
170
171
contents = None
172
if mode == "text":
173
contents = convertToHTML(path)
174
175
return flask.render_template(
176
"repo-file.html",
177
username=username,
178
repository=repository,
179
file=os.path.join(f"/{username}/{repository}/raw/{branch}/", subpath),
180
branches=branches,
181
current=branch,
182
mode=mode,
183
mimetype=mimetype,
184
size=size,
185
icon=icon,
186
subpath=os.path.join("/", subpath),
187
basename=os.path.basename(path),
188
contents=contents
189
)
190
191
192
@app.route("/<username>/<repository>/forum/")
193
def repositoryForum(username, repository):
194
return flask.render_template("repo-forum.html", username=username, repository=repository)
195
196
197
@app.route("/<username>/<repository>/docs/")
198
def repositoryDocs(username, repository):
199
return flask.render_template("repo-docs.html", username=username, repository=repository)
200
201
202
@app.route("/<username>/<repository>/releases/")
203
def repositoryReleases(username, repository):
204
return flask.render_template("repo-releases.html", username=username, repository=repository)
205
206
207
@app.route("/<username>/<repository>/branches/")
208
def repositoryBranches(username, repository):
209
return flask.render_template("repo-branches.html", username=username, repository=repository)
210
211
212
@app.route("/<username>/<repository>/people/")
213
def repositoryPeople(username, repository):
214
return flask.render_template("repo-people.html", username=username, repository=repository)
215
216
217
@app.route("/<username>/<repository>/activity/")
218
def repositoryActivity(username, repository):
219
return flask.render_template("repo-activity.html", username=username, repository=repository)
220
221
222
@app.route("/<username>/<repository>/ci/")
223
def repositoryCI(username, repository):
224
return flask.render_template("repo-ci.html", username=username, repository=repository)
225
226
227
@app.route("/<username>/<repository>/settings/")
228
def repositorySettings(username, repository):
229
flask.abort(401)
230
return flask.render_template("repo-settings.html", username=username, repository=repository)
231
232
233
@app.errorhandler(404)
234
def e404(error):
235
return flask.render_template("not-found.html"), 404
236
237
238
@app.errorhandler(401)
239
def e401(error):
240
return flask.render_template("unauthorised.html"), 401
241
242
243
@app.errorhandler(403)
244
def e403(error):
245
return flask.render_template("forbidden.html"), 403
246
247
248
@app.errorhandler(418)
249
def e418(error):
250
return flask.render_template("teapot.html"), 418
251
252