summaryrefslogtreecommitdiffstats
path: root/gitsrht/blueprints/repo.py
blob: e9e56514e1237d6d706166a73fd0607af4626252 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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, annotate_tree
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__)

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
    key = f"git.sr.ht:git:markdown:{readme.id.hex}"
    html = redis.get(key)
    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(key, html, timedelta(days=30))
    return Markup(html)

@repo.route("/<owner>/<repo>")
def summary(owner, repo):
    owner, repo = get_repo(owner, repo)
    if not repo:
        abort(404)
    if not has_access(repo, UserAccess.read):
        abort(401)
    git_repo = CachedRepository(repo.path)
    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@{}:{}/{}"]
    ]
    if git_repo.is_empty:
        return render_template("empty-repo.html", owner=owner, repo=repo,
                clone_urls=clone_urls)
    default_branch = git_repo.default_branch()
    tip = git_repo.get(default_branch.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)
    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
    return render_template("summary.html", view="summary",
            owner=owner, repo=repo, readme=readme, commits=commits,
            clone_urls=clone_urls, latest_tag=latest_tag,
            default_branch=default_branch)

@repo.route("/<owner>/<repo>/tree", defaults={"branch": None, "path": ""})
@repo.route("/<owner>/<repo>/tree/<branch>", defaults={"path": ""})
@repo.route("/<owner>/<repo>/tree/<branch>/<path>")
def tree(owner, repo, branch, path):
    owner, repo = get_repo(owner, repo)
    if not repo:
        abort(404)
    if not has_access(repo, UserAccess.read):
        abort(401)
    git_repo = CachedRepository(repo.path)
    if branch is None:
        branch = git_repo.default_branch()
    else:
        branch = git_repo.branches.get(branch)
    if not branch:
        abort(404)
    commit = git_repo.get(branch.target)

    tree = annotate_tree(git_repo, commit)
    tree = sorted(tree, key=lambda e: e.name)
    # TODO: follow path
    return render_template("tree.html", view="tree",
            owner=owner, repo=repo, commit=commit, tree=tree, path=path)