From 00c7ddced5cd820c54420ad785eed21918bf7eba Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 21 Sep 2018 11:23:22 -0400 Subject: [PATCH] Make repo summary page real --- gitsrht/app.py | 3 ++ gitsrht/blueprints/repo.py | 56 +++++++++++++++++++++++++++++++--- gitsrht/git.py | 34 +++++++++++++++++++++ gitsrht/redis.py | 3 ++ gitsrht/templates/summary.html | 48 ++++++++++++----------------- 5 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 gitsrht/git.py create mode 100644 gitsrht/redis.py diff --git a/gitsrht/app.py b/gitsrht/app.py index d85997d..a0704cb 100644 --- a/gitsrht/app.py +++ b/gitsrht/app.py @@ -10,6 +10,7 @@ from gitsrht.types import User db.init() import gitsrht.oauth +from gitsrht.git import commit_time, trim_commit class GitApp(SrhtFlask): def __init__(self): @@ -39,6 +40,8 @@ class GitApp(SrhtFlask): if notice: del session["notice"] return { + "trim_commit": trim_commit, + "commit_time": commit_time, "notice": notice } diff --git a/gitsrht/blueprints/repo.py b/gitsrht/blueprints/repo.py index a9c6833..a015fa9 100644 --- a/gitsrht/blueprints/repo.py +++ b/gitsrht/blueprints/repo.py @@ -1,17 +1,65 @@ +import pygit2 +from jinja2 import Markup from flask import Blueprint, render_template, abort from flask_login import current_user from gitsrht.access import get_repo, has_access, UserAccess +from gitsrht.redis import redis +from gitsrht.git import CachedRepository, commit_time from gitsrht.types import User, Repository +from srht.config import cfg +from srht.markdown import markdown +from datetime import datetime, timedelta repo = Blueprint('repo', __name__) -# TODO: !! SECURITY !! +def get_readme(repo, tip): + if not tip or not "README.md" in tip.tree: + return None + readme = tip.tree["README.md"] + if readme.type != "blob": + return None + html = redis.get(readme.id.hex) + if html: + return Markup(html.decode()) + try: + md = repo.get(readme.id).data.decode() + except: + pass + html = markdown(md, ["h1", "h2", "h3", "h4", "h5"]) + redis.setex(readme.id.hex, html, timedelta(days=30)) + return Markup(html) @repo.route("//") def summary(owner, repo): owner, repo = get_repo(owner, repo) if not has_access(repo, UserAccess.read): abort(401) - with open("/home/sircmpwn/sources/wlroots/README.md") as f: - rm = f.read() - return render_template("summary.html", owner=owner, repo=repo, rm=rm) + git_repo = CachedRepository(repo.path) + master = git_repo.branches.get("master") + if not master: + master = list(git_repo.branches.local)[0] + master = git_repo.branches.get(master) + # TODO: Test on empty repos + tip = git_repo.get(master.target) + commits = list() + for commit in git_repo.walk(tip.id, pygit2.GIT_SORT_TIME): + commits.append(commit) + if len(commits) >= 3: + break + readme = get_readme(git_repo, tip) + base = (cfg("git.sr.ht", "origin") + .replace("http://", "") + .replace("https://", "")) + clone_urls = [ + url.format(base, owner.canonical_name, repo.name) + for url in ["https://{}/{}/{}", "git@{}:{}/{}"] + ] + tags = [(ref, git_repo.get(git_repo.references[ref].target)) + for ref in git_repo.listall_references() + if ref.startswith("refs/tags/")] + tags = sorted(tags, key=lambda c: commit_time(c[1]), reverse=True) + latest_tag = tags[0] if len(tags) else None + default_branch = master + return render_template("summary.html", owner=owner, repo=repo, + readme=readme, commits=commits, clone_urls=clone_urls, + latest_tag=latest_tag, default_branch=master) diff --git a/gitsrht/git.py b/gitsrht/git.py new file mode 100644 index 0000000..16d7974 --- /dev/null +++ b/gitsrht/git.py @@ -0,0 +1,34 @@ +from datetime import datetime, timedelta, timezone +from pygit2 import Repository, Tag +from functools import lru_cache + +def trim_commit(msg): + if "\n" not in msg: + return msg + return msg[:msg.index("\n")] + +def commit_time(commit): + author = commit.author if hasattr(commit, 'author') else commit.tagger + # Time handling in python is so dumb + tzinfo = timezone(timedelta(minutes=author.offset)) + tzaware = datetime.fromtimestamp(float(author.time), tzinfo) + diff = datetime.now(timezone.utc) - tzaware + return datetime.utcnow() - diff + +@lru_cache(maxsize=256) +def CachedRepository(path): + return _CachedRepository(path) + +@lru_cache(maxsize=1024) +def _get_ref(repo, ref): + return repo._get(ref) + +class _CachedRepository(Repository): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def get(self, ref): + return _get_ref(self, ref) + + def _get(self, ref): + return super().get(ref) diff --git a/gitsrht/redis.py b/gitsrht/redis.py new file mode 100644 index 0000000..c64d07c --- /dev/null +++ b/gitsrht/redis.py @@ -0,0 +1,3 @@ +from redis import Redis + +redis = Redis() diff --git a/gitsrht/templates/summary.html b/gitsrht/templates/summary.html index 247b15f..30b095f 100644 --- a/gitsrht/templates/summary.html +++ b/gitsrht/templates/summary.html @@ -4,67 +4,57 @@
+ {% for c in commits %}
- emersion - <contact@emersion.fr> - committed - ac28d701c - 14 hours ago + {{c.id.hex[:8]}} — + {{c.author.name}} + + {{ commit_time(c) | date }} +
buffer: disconnect clients that commit an unknown buffer type
-
-
-
- emersion - <contact@emersion.fr> - committed - ac28d701c - 14 hours ago -
-
-
-
- emersion - <contact@emersion.fr> - committed - ac28d701c - 14 hours ago -
+ >{{ trim_commit(c.message) }}
+ {% endfor %}

refs

-
master
+ {% if default_branch %} +
{{default_branch.name[len("refs/heads/"):]}}
log {{icon("caret-right")}} browse {{icon("caret-right")}}
-
v1.0
+ {% endif %} + {% if latest_tag %} +
{{ latest_tag[0][len("refs/tags/"):] }}
log {{icon("caret-right")}} .tar.gz {{icon("caret-right")}}
+ {% endif %}

clone

read-only
-
https://git.sr.ht/~sircmpwn/wlroots
+
{{clone_urls[0]}}
read/write
-
git@git.sr.ht/~sircmpwn/wlroots
+
{{clone_urls[1]}}
+ {% if readme %}
- {{ rm | extended_md }} + {{ readme }}
+ {% endif %} {% endblock %} -- 2.38.4