This commit is contained in:
Barrett Ruth 2025-05-14 11:42:58 -04:00
parent 48d05fa727
commit 281ec556ff
3 changed files with 53 additions and 64 deletions

109
app.py
View file

@ -1,15 +1,16 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import subprocess
import json
from dataclasses import dataclass from dataclasses import dataclass
from flask import Flask, render_template, request, jsonify, send_from_directory
app = Flask(__name__, static_folder=None) # Disable default static folder from flask import Flask, jsonify, render_template, send_from_directory
GIT_REPO_PATH = "/home/frozenpipe/dev" # Default path for git repositories app = Flask(__name__, static_folder=None)
GIT_REPO_PATH = "/home/frozenpipe/dev"
EXPORT_MARKER = "readme.md" EXPORT_MARKER = "readme.md"
@dataclass @dataclass
class Repository: class Repository:
name: str name: str
@ -17,85 +18,79 @@ class Repository:
path: str path: str
exported: bool exported: bool
def get_repositories(): def get_repositories():
"""
Scan the git repository directory and return a list of Repository objects
"""
repositories = [] repositories = []
# Make sure the git repository path exists
if not os.path.exists(GIT_REPO_PATH): if not os.path.exists(GIT_REPO_PATH):
return repositories return repositories
# List all subdirectories that are git repositories (have a .git dir or are bare repos)
for item in os.listdir(GIT_REPO_PATH): for item in os.listdir(GIT_REPO_PATH):
repo_path = os.path.join(GIT_REPO_PATH, item) repo_path = os.path.join(GIT_REPO_PATH, item)
# Skip if not a directory
if not os.path.isdir(repo_path): if not os.path.isdir(repo_path):
continue continue
# Check if it's a git repository (either has a .git directory or is a bare repo with HEAD file) if not (
if not (os.path.exists(os.path.join(repo_path, ".git")) or os.path.exists(os.path.join(repo_path, ".git"))
os.path.exists(os.path.join(repo_path, "HEAD"))): or os.path.exists(os.path.join(repo_path, "HEAD"))
):
continue continue
# Check if the git-daemon-export-ok file exists
exported = os.path.exists(os.path.join(repo_path, EXPORT_MARKER)) exported = os.path.exists(os.path.join(repo_path, EXPORT_MARKER))
# Try to get the repository description from the description file only description = "No description available"
description = ""
description_file = os.path.join(repo_path, "description") description_file = os.path.join(repo_path, "description")
if os.path.exists(description_file): if os.path.exists(description_file):
try: try:
with open(description_file, 'r') as f: with open(description_file, "r") as f:
description = f.read().strip() description = f.read().strip()
# Skip default description if (
if description == "Unnamed repository; edit this file 'description' to name the repository.": description
== "Unnamed repository; edit this file 'description' to name the repository."
):
description = "No description available" description = "No description available"
except: except _ as _:
description = "No description available" pass
else: repositories.append(
description = "No description available" Repository(
name=item, description=description, path=repo_path, exported=exported
repositories.append(Repository( )
name=item, )
description=description,
path=repo_path,
exported=exported
))
# Sort repositories by name
repositories.sort(key=lambda repo: repo.name.lower()) repositories.sort(key=lambda repo: repo.name.lower())
return repositories return repositories
@app.route('/')
@app.route("/")
def index(): def index():
repositories = [repo for repo in get_repositories() if repo.exported] repositories = [repo for repo in get_repositories() if repo.exported]
return render_template('index.html', repositories=repositories) return render_template("index.html", repositories=repositories)
@app.route('/styles/<path:filename>')
@app.route("/styles/<path:filename>")
def serve_styles(filename): def serve_styles(filename):
return send_from_directory('styles', filename) return send_from_directory("styles", filename)
@app.route('/scripts/<path:filename>')
@app.route("/scripts/<path:filename>")
def serve_scripts(filename): def serve_scripts(filename):
return send_from_directory('scripts', filename) return send_from_directory("scripts", filename)
@app.route('/api/repo/<int:repo_id>')
@app.route("/api/repo/<int:repo_id>")
def get_repo(repo_id): def get_repo(repo_id):
repositories = [repo for repo in get_repositories() if repo.exported] repositories = [repo for repo in get_repositories() if repo.exported]
if repo_id < 0 or repo_id >= len(repositories): if repo_id < 0 or repo_id >= len(repositories):
return jsonify({"error": "Repository not found"}), 404 return jsonify({"error": "Repository not found"}), 404
repo = repositories[repo_id]
return jsonify({
"name": repo.name,
"description": repo.description,
"path": repo.path
})
if __name__ == '__main__': repo = repositories[repo_id]
app.run(host='0.0.0.0', port=8000, debug=True) return jsonify(
{"name": repo.name, "description": repo.description, "path": repo.path}
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=True)

View file

@ -5,7 +5,7 @@ After=network.target
[Service] [Service]
User=apache User=apache
WorkingDirectory=/srv/git/git-server-ui WorkingDirectory=/srv/git/git-server-ui
ExecStart=/root/.local/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 wsgi:app ExecStart=/root/.local/bin/gunicorn --workers 3 --bind 0.0.0.0:8000 --chdir /srv/git wsgi:app
Restart=on-failure Restart=on-failure
[Install] [Install]

View file

@ -1,6 +0,0 @@
def main():
print("Hello from git-server-ui!")
if __name__ == "__main__":
main()