summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-09-22 13:15:41 -0400
committerDrew DeVault <sir@cmpwn.com>2018-09-22 13:15:41 -0400
commit8616f09c97b99c81ca4142869721aab86fc00063 (patch)
tree799645b78e8460c5c8fa1893381d7366d51ab3a9
parentcfff448c92ae5dd1af3bd86e8aa15188ad2978c3 (diff)
Add blob view
-rw-r--r--gitsrht/blueprints/repo.py34
-rw-r--r--gitsrht/git.py9
-rw-r--r--gitsrht/templates/blob.html39
-rw-r--r--scss/main.scss43
4 files changed, 118 insertions, 7 deletions
diff --git a/gitsrht/blueprints/repo.py b/gitsrht/blueprints/repo.py
index b0f90cd..d4e4f94 100644
--- a/gitsrht/blueprints/repo.py
+++ b/gitsrht/blueprints/repo.py
@@ -1,4 +1,6 @@
import pygit2
+import pygments
+from datetime import datetime, timedelta
from jinja2 import Markup
from flask import Blueprint, render_template, abort
from flask_login import current_user
@@ -6,9 +8,11 @@ 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 pygments import highlight
+from pygments.lexers import guess_lexer_for_filename, TextLexer
+from pygments.formatters import HtmlFormatter
from srht.config import cfg
from srht.markdown import markdown
-from datetime import datetime, timedelta
repo = Blueprint('repo', __name__)
@@ -30,6 +34,21 @@ def get_readme(repo, tip):
redis.setex(key, html, timedelta(days=30))
return Markup(html)
+def _highlight_file(name, data, blob_id):
+ key = f"git.sr.ht:git:highlight:{blob_id}"
+ html = redis.get(key)
+ if html:
+ return Markup(html.decode())
+ try:
+ lexer = guess_lexer_for_filename(name, data)
+ except pygments.util.ClassNotFound:
+ lexer = TextLexer()
+ formatter = HtmlFormatter()
+ style = formatter.get_style_defs('.highlight')
+ html = f"<style>{style}</style>" + highlight(data, lexer, formatter)
+ redis.setex(key, html, timedelta(days=30))
+ return Markup(html)
+
@repo.route("/<owner>/<repo>")
def summary(owner, repo):
owner, repo = get_repo(owner, repo)
@@ -82,6 +101,7 @@ def tree(owner, repo, branch, path):
branch = git_repo.branches.get(branch)
if not branch:
abort(404)
+ branch_name = branch.name[len("refs/heads/"):]
commit = git_repo.get(branch.target)
tree = commit.tree
@@ -93,13 +113,19 @@ def tree(owner, repo, branch, path):
abort(404)
entry = tree[part]
if entry.type == "blob":
- return "TODO: render blobs"
+ tree = annotate_tree(git_repo, tree, commit)
+ commit = next(e.commit for e in tree if e.name == entry.name)
+ blob = git_repo.get(entry.id)
+ data = blob.data.decode()
+ return render_template("blob.html", view="tree",
+ owner=owner, repo=repo, branch=branch, path=path,
+ branch_name=branch_name, entry=entry, blob=blob, data=data,
+ commit=commit, highlight_file=_highlight_file)
tree = git_repo.get(entry.id)
tree = annotate_tree(git_repo, tree, commit)
tree = sorted(tree, key=lambda e: e.name)
return render_template("tree.html", view="tree",
- owner=owner, repo=repo, branch=branch,
- branch_name=branch.name[len("refs/heads/"):],
+ owner=owner, repo=repo, branch=branch, branch_name=branch_name,
commit=commit, tree=tree, path=path)
diff --git a/gitsrht/git.py b/gitsrht/git.py
index 40ae3b3..b254360 100644
--- a/gitsrht/git.py
+++ b/gitsrht/git.py
@@ -95,9 +95,12 @@ def annotate_tree(repo, tree, commit):
key = f"git.sr.ht:git:tree:{tree.id.hex}"
cache = redis.get(key)
if cache:
- cache = json.loads(cache.decode())
- return [AnnotatedTreeEntry.deserialize(
- e, repo).fetch_blob() for e in cache.values()]
+ try:
+ cache = json.loads(cache.decode())
+ return [AnnotatedTreeEntry.deserialize(
+ e, repo).fetch_blob() for e in cache.values()]
+ except:
+ redis.delete(key)
tree = { entry.id.hex: AnnotatedTreeEntry(
repo, entry) for entry in tree }
diff --git a/gitsrht/templates/blob.html b/gitsrht/templates/blob.html
new file mode 100644
index 0000000..00d0f90
--- /dev/null
+++ b/gitsrht/templates/blob.html
@@ -0,0 +1,39 @@
+{% extends "repo.html" %}
+{% block content %}
+<div class="header-extension">
+ <div class="container-fluid">
+ <span style="padding-left: 1rem">
+ {% if path != [''] %}
+ <a href="{{url_for("repo.tree",
+ owner=repo.owner.canonical_name, repo=repo.name, branch=branch_name)}}"
+ >{{repo.name}}</a>{% endif %}/{% for part in path%}{%
+ if loop.last %}{{part}}{% else %}<a
+ href="{{url_for("repo.tree", owner=repo.owner.canonical_name,
+ repo=repo.name, branch=branch_name,
+ path=path_join(*path[:loop.index]))}}"
+ >{{part}}</a>/{%
+ endif %}{% endfor %}
+ </span>
+ <div class="pull-right">
+ <a href="#">{{commit.id.hex[:8]}}</a> &mdash;
+ <a href="#">{{commit.author.name}}</a>:
+ {{trim_commit(commit.message)}}
+ <span class="text-muted">
+ {{ commit_time(commit) | date }}
+ </span>
+ </div>
+ </div>
+</div>
+<div class="container-fluid">
+ <div class="row" style="margin-bottom: 1rem">
+ <div class="col-md-12 code-view">
+ <pre class="ruler"><span>{% for i in range(80) %} {% endfor %}</span></pre>
+ <pre class="lines">{% for line in data.split("\n") %}<a
+ href="#L{{loop.index}}"
+ id="L{{loop.index}}"
+ >{{loop.index}}</a>{% if not loop.last %}
+{% endif %}{% endfor %}</pre>
+ {{ highlight_file(entry.name, data, blob.id.hex) }}
+ </div>
+</div>
+{% endblock %}
diff --git a/scss/main.scss b/scss/main.scss
index 9b44c8e..abd3a8d 100644
--- a/scss/main.scss
+++ b/scss/main.scss
@@ -61,3 +61,46 @@
}
}
}
+
+.code-view {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ grid-template-rows: auto;
+
+ .lines {
+ grid-column-start: 1;
+ grid-row-start: 1;
+ border-right: 1px solid #444;
+ }
+
+ .highlight {
+ grid-column-start: 2;
+ grid-row-start: 1;
+ padding-left: 1rem;
+ background: transparent;
+ overflow-x: hidden;
+
+ pre {
+ background: transparent;
+ }
+ }
+
+ .ruler {
+ background: transparent;
+ grid-column-start: 2;
+ grid-row-start: 1;
+ display: block;
+ padding-left: calc(1rem + 4px);
+ height: 100%;
+
+ pre {
+ background: transparent;
+ }
+
+ & > span {
+ height: 100%;
+ display: inline-block;
+ border-right: 1px solid $gray-200;
+ }
+ }
+}