Git Repos / blogofile_gitview / commit 1541b75
Commit: 1541b752e61cea1d961dfb07fb474c7c28365834
Parent: 6a3b6a967b7918157c6e0bdf73f8e130acc4f1d2
Author: Cameron Vanderzanden, 2021-07-31 09:27
Committer: Cameron Vanderzanden, 2021-07-31 09:27
Commit Message
Implement branches & tags, various other changes
Change List
? | File | Add | Del |
---|---|---|---|
M | _controllers/gitview.py | +96 | -22 |
A | _templates/gitview/git_branch_list.mako | +21 | |
M | _templates/gitview/git_commit.mako | +38 | -21 |
M | _templates/gitview/git_commit_list.mako | +2 | -3 |
M | _templates/gitview/git_file_list.mako | +3 | -4 |
M | _templates/gitview/git_header.mako | +3 | -1 |
M | _templates/gitview/git_repo.mako | +16 | |
A | _templates/gitview/git_tag_list.mako | +17 | |
M | css/style.css | +8 | -8 |
Diff _controllers/gitview.py
diff --git a/_controllers/gitview.py b/_controllers/gitview.py
index 842d31f..0a0b152 100644
--- a/_controllers/gitview.py
+++ b/_controllers/gitview.py
@@ -13,7 +13,7 @@ under the terms of the MIT License. Please see the file "LICENSE" in
the root dir of this repository for more information.
"""
-import datetime, os, shutil, stat, sys
+import datetime, os, re, shutil, stat, sys
try:
from urllib.parse import urlparse
except ImportError:
@@ -21,6 +21,7 @@ except ImportError:
try:
from pygit2 import Repository
from pygit2 import GIT_SORT_TOPOLOGICAL, GIT_SORT_REVERSE, GIT_SORT_NONE
+ from pygit2 import GIT_OBJ_COMMIT, GIT_OBJ_TAG
except ImportError:
print("gitview: pygit2 is required for this controller to work!")
sys.exit(1)
@@ -60,7 +61,7 @@ pygments_differ = pygments.formatters.HtmlFormatter(linenos=False,
cssclass="syntax_highlight", lineseparator="<br>", style="vim",
wrapcode=True)
-def human_readable_size(size, decimal_places=2):
+def human_readable_size(size, decimal_places=1):
# TODO: limit output to four characters
for unit in ['B', 'K', 'M', 'G', 'T', 'P']:
if size < 1024.0 or unit == 'P':
@@ -101,11 +102,13 @@ def write_log(repo, repoinfo):
parentids.append(str(parent.id))
diff = repo.diff(parent, commit)
# TODO diffstats are expensive?
- # dschanged += diff.stats.files_changed
- # dsinsert += diff.stats.insertions
- # dsdelete += diff.stats.deletions
+ dschanged += diff.stats.files_changed
+ dsinsert += diff.stats.insertions
+ dsdelete += diff.stats.deletions
for patch in diff:
pd = {
+ "add": patch.line_stats[1],
+ "del": patch.line_stats[2],
"newpath": util.html_escape(patch.delta.new_file.path),
"oldpath": util.html_escape(patch.delta.old_file.path),
"status": patch.delta.status_char()
@@ -130,9 +133,9 @@ def write_log(repo, repoinfo):
commit.committer.time),
"date": datetime.datetime.fromtimestamp(commit.commit_time),
"deltas": deltas,
- # "ds_changed": dschanged,
- # "ds_insert": dsinsert,
- # "ds_delete": dsdelete,
+ "ds_changed": dschanged,
+ "ds_insert": dsinsert,
+ "ds_delete": dsdelete,
"id": str(commit.id),
"msg": util.html_escape(commit.message.strip()),
"parentids": parentids,
@@ -155,7 +158,7 @@ def write_log(repo, repoinfo):
next_id = str(commit.id)
cl.append(ci)
# write the commit log list
- # NOTE: commented out in favor of git_repos.mako
+ # NOTE: commented out in favor of git_repo.mako
# tools.materialize_template('git_log.mako',
# util.path_join(config.path, repoinfo['name'], "log.html"),
# {"commits": cl, "repo": repoinfo })
@@ -235,14 +238,81 @@ def write_files(repo, repoinfo):
return fl
-def write_refs(repo, repoinfo):
- # TODO write refs (branches, tags)
- pass
+def get_branches(repo, repoinfo):
+ bl = []
+ for branch_s in repo.branches:
+ branch_b = repo.lookup_branch(branch_s)
+ last_commit = None
+ author = None
+ commitid = ""
+ summary = None
+ commit_link = False
+ for commit in repo.walk(branch_b.target):
+ author = util.html_escape(commit.author.name)
+ commitid = str(commit.id)
+ last_commit = datetime.datetime.fromtimestamp(commit.commit_time)
+ summary = util.html_escape(commit.message.split('\n')[0])
+ break
+ if os.path.exists(util.path_join(bf.writer.output_dir,
+ config.path, repoinfo['name'], str(commitid) + ".html")):
+ commit_link = True
+ b = {
+ "author": author,
+ "commit_link": commit_link,
+ "id": commitid,
+ "is_head": branch_b.is_head(),
+ "last_commit": last_commit,
+ "name": util.html_escape(branch_b.branch_name),
+ "summary": summary,
+ "target": branch_b.target
+ }
+ bl.append(b)
+ return bl
+
+
+def get_tags(repo, repoinfo):
+ tl = []
+ # https://www.pygit2.org/recipes/git-tag.html
+ # https://github.com/libgit2/pygit2/issues/856
+ regex = re.compile("^refs/tags/")
+ for ref in repo.references:
+ if not regex.match(ref): continue
+ tag = repo.revparse_single(ref)
+ author = None
+ commitid = ""
+ last_commit = None
+ summary = None
+ commit_link = False
+ if tag.type == GIT_OBJ_COMMIT:
+ author = util.html_escape(tag.author.name)
+ commitid = str(tag.id)
+ last_commit = datetime.datetime.fromtimestamp(tag.commit_time)
+ summary = util.html_escape(tag.message.split('\n')[0])
+ elif tag.type == GIT_OBJ_TAG:
+ target_commit = tag.get_object()
+ author = util.html_escape(tag.tagger.name)
+ commitid = str(target_commit.id)
+ last_commit = datetime.datetime.fromtimestamp(
+ target_commit.commit_time)
+ summary = util.html_escape(target_commit.message.split('\n')[0])
+ if os.path.exists(util.path_join(bf.writer.output_dir,
+ config.path, repoinfo['name'], str(commitid) + ".html")):
+ commit_link = True
+ t = {
+ "author": author,
+ "commit_link": commit_link,
+ "id": commitid,
+ "last_commit": last_commit,
+ "name": util.html_escape(ref[10:]),
+ "summary": summary
+ }
+ tl.append(t)
+ return tl
def run():
if not config.reporoot:
- print("gitview: repo root not found!")
+ print("gitview: repo root not configured!")
sys.exit(1)
for d in os.listdir(config.reporoot):
fullpath = util.path_join(config.reporoot, d)
@@ -257,8 +327,10 @@ def run():
rd_desc = ""
rd_owner = ""
rd_last_commit = None
- cl = []
- fl = []
+ commit_list = []
+ file_list = []
+ branch_list = []
+ tag_list = []
try:
with open(util.path_join(rd_path, "description"), "r") as f:
rd_desc = f.readline().strip()
@@ -289,12 +361,13 @@ def run():
}
ri.append(rd)
# 2. write log and commits; store the commit log dict list
- cl = write_log(r, rd)
- # 3. write refs
- rf = write_refs(r, rd)
+ commit_list = write_log(r, rd)
+ # 3. collect branches and tags
+ branch_list = get_branches(r, rd)
+ tag_list = get_tags(r, rd)
# 4. write the individual files in the tree
- fl = write_files(r, rd)
- # NOTE: commented out in favor of git_repos.mako
+ file_list = write_files(r, rd)
+ # NOTE: commented out in favor of git_repo.mako
#
# tools.materialize_template("git_files.mako",
# util.path_join(config.path, name, "files.html"),
@@ -302,8 +375,9 @@ def run():
# 5. write the repo index
tools.materialize_template("git_repo.mako",
util.path_join(config.path, rd['name'], "index.html"),
- {"commits": cl, "files": fl, "repo": rd})
- # NOTE: commented out in favor of git_repos.mako
+ {"commits": commit_list, "files": file_list,
+ "branches": branch_list, "tags": tag_list, "repo": rd})
+ # NOTE: commented out in favor of git_repo.mako above
#
# shutil.copyfile(
# util.path_join(bf.writer.output_dir,
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_branch_list.mako
diff --git a/_templates/gitview/git_branch_list.mako b/_templates/gitview/git_branch_list.mako
new file mode 100644
index 0000000..b0fbccc
--- /dev/null
+++ b/_templates/gitview/git_branch_list.mako
@@ -0,0 +1,21 @@
+<%page args="branches"/>\
+<section class="branches"><table><tr>
+<th class="branchname">Branch</th>
+<th class="branchlast">Last Commit</th>
+<th class="branchsummary">Commit Message</th>
+<th class="branchauth">Author</th></tr>
+% for b in branches:
+% if b['is_head']:
+<tr><td class="branchname"><strong>${b['name']}</strong></td>
+% else:
+<tr><td class="branchname">${b['name']}</td>
+% endif
+<td class="branchlast">${b['last_commit'].strftime("%Y-%m-%d")}</td>
+% if b['commit_link']:
+<td class="branchsummary"><a href="${b['id']}.html">${b['summary']}</a></td>
+% else:
+<td class="branchsummary">${b['summary']}</td>
+% endif
+<td class="branchauth">${b['author']}</td></tr>
+% endfor
+</table></section>\
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_commit.mako
diff --git a/_templates/gitview/git_commit.mako b/_templates/gitview/git_commit.mako
index 98f0408..2d88ecc 100644
--- a/_templates/gitview/git_commit.mako
+++ b/_templates/gitview/git_commit.mako
@@ -1,4 +1,7 @@
<%inherit file="site.mako" />\
+<%
+ repolink = bf.util.path_join(bf.config.gitview.path, repo['name'])
+%>\
<%def name="git_header(name, l, extra)">\
<%include file="git_header.mako" args="name=name, lastcommit=l, extra=extra" />\
</%def>\
@@ -8,11 +11,11 @@ ${self.git_header(repo['name'], repo['last_commit'],
<section class="commitinfo"><p>
Commit: <a href="${commitinfo['id']}.html">${commitinfo['id']}</a><br />
% for p in commitinfo['parentids']:
-% if prev_id and len(commitinfo['parentids']) == 1:
+% if prev_id and len(commitinfo['parentids']) == 1:
Parent: <a href="${p}.html">${p}</a><br />
-% else:
+% else:
Parent: ${p}<br />
-% endif
+% endif
% endfor
Author: ${commitinfo['author']} <${commitinfo['author_email']}>,
${commitinfo['author_time'].strftime("%Y-%m-%d %H:%M")}<br />
@@ -22,39 +25,53 @@ ${commitinfo['committer_time'].strftime("%Y-%m-%d %H:%M")}<br />
<h3>Commit Message</h3>
<pre>${commitinfo['msg']}</pre>
</section>
+% if len(commitinfo['deltas']) > 0 and len(commitinfo['patches']) > 0:
<h3>Change List & Diffs</h3>
<section class="changelist">
-% for i, delta in enumerate(commitinfo['deltas']):
-% if i == 0:
-<table>
-<tr><th class="cstatus">?</th><th class="filename">File</th></tr>
-% endif
+% for i, delta in enumerate(commitinfo['deltas']):
+% if i == 0:
+<table><tr>
+<th class="cstatus">?</th><th class="filename">File</th>
+<th class="cadd">Add</th><th class="cdel">Del</th></tr>
+% endif
<tr><td class="cstatus">${delta['status']}</td>
<td class="filename">
-<a href="${commitinfo['id']}.html#${i}">${delta['oldpath']}</a>
-</td></tr>
-% if i == (len(commitinfo['deltas']) - 1):
+<a href="${commitinfo['id']}.html#${i}">${delta['oldpath']}</a></td>
+% if delta['add']:
+<td class="cadd">${delta['add']}</td>
+% else:
+<td class="cadd"></td>
+% endif
+% if delta['del']:
+<td class="cdel">${delta['del']}</td>
+% else:
+<td class="cdel"></td>
+% endif
+</tr>
+% if i == (len(commitinfo['deltas']) - 1):
</table>
-% endif
-% endfor
+% endif
+% endfor
</section>
-% for i, patch in enumerate(commitinfo['patches']):
+% for i, patch in enumerate(commitinfo['patches']):
<h4 id="${i}">${commitinfo['deltas'][i]['oldpath']}</h4>
<section class="diff">
-${patch}
+${patch}\
</section>
-<p><a href="#top">Return to top of this page</a></p>
-% endfor
+<p><a href="#top">Return to top of this page</a> or
+<a href="/${repolink}">return to the overview of this repository</a></p>
+% endfor
+% endif
</article>
% if prev_id or next_id:
<hr class="bright" />
<nav><p class="clearfix">
-% if next_id:
+% if next_id:
<a href="${next_id}.html" title="Next Commit"><< Next Commit</a>
-% endif
-% if prev_id:
+% endif
+% if prev_id:
<a class="rg" href="${prev_id}.html" title="Previous Commit">
Previous Commit >></a>
-% endif
+% endif
</p></nav>\
% endif
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_commit_list.mako
diff --git a/_templates/gitview/git_commit_list.mako b/_templates/gitview/git_commit_list.mako
index 0fc64a2..64e15fb 100644
--- a/_templates/gitview/git_commit_list.mako
+++ b/_templates/gitview/git_commit_list.mako
@@ -1,9 +1,8 @@
<%page args="commits"/>\
-<section class="commits">
-<table><tr>
+<section class="commits"><table><tr>
<th class="commdate">Date</th>
<th class="commmesg">Commit Message</th>
-<th class="commauth">Author</th>
+<th class="commauth">Author</th></tr>
% for c in commits:
% if c == None:
<tr><td class="commdate"></td>
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_file_list.mako
diff --git a/_templates/gitview/git_file_list.mako b/_templates/gitview/git_file_list.mako
index f898c68..8c22a5c 100644
--- a/_templates/gitview/git_file_list.mako
+++ b/_templates/gitview/git_file_list.mako
@@ -8,8 +8,8 @@
return fnamet
else: return fullname
%>\
-<section class="files">
-<table><tr><th class="filemode">Mode</th>
+<section class="files"><table><tr>
+<th class="filemode">Mode</th>
<th class="filename">Name</th>
<th class="filesize">Size</th></tr>
% for f in files:
@@ -18,5 +18,4 @@
<a href="${objdir}/${f['sfname']}.html">${trunc_fname(f['fullname'])}</a></td>
<td class="filesize">${f['objsize']}</td></tr>
% endfor
-</table>
-</section>\
+</table></section>\
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_header.mako
diff --git a/_templates/gitview/git_header.mako b/_templates/gitview/git_header.mako
index 033c03d..da21f33 100644
--- a/_templates/gitview/git_header.mako
+++ b/_templates/gitview/git_header.mako
@@ -12,6 +12,8 @@
% endif
<p>Last commit to this repo was on ${lastcommit.strftime("%Y-%m-%d at %H:%M")}.
% if bf.template_context.template_name == "git_repo.mako":
-You can jump to the <a href="#files">file list</a> or the <a href="#commits">commit log</a>.
+You can jump to the <a href="#files">file list</a>, the
+<a href="#commits">commit log</a>, the <a href="#branchlist">branches</a>,
+or <a href="#taglist">tags</a>.
% endif
</p></header>\
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_repo.mako
diff --git a/_templates/gitview/git_repo.mako b/_templates/gitview/git_repo.mako
index 824565e..ae55a70 100644
--- a/_templates/gitview/git_repo.mako
+++ b/_templates/gitview/git_repo.mako
@@ -14,6 +14,12 @@
<%def name="commit_list(commits)">\
<%include file="git_commit_list.mako" args="commits=commits" />\
</%def>\
+<%def name="branch_list(branches)">\
+<%include file="git_branch_list.mako" args="branches=branches" />\
+</%def>\
+<%def name="tag_list(tags)">\
+<%include file="git_tag_list.mako" args="tags=tags" />\
+</%def>\
<article>
${self.git_header(repo['name'], repo['last_commit'], None)}
<p>${repo['desc']}</p>
@@ -29,4 +35,14 @@ ${self.file_list(files)}
${self.commit_list(commits)}
<p><a href="#top">Return to top of this page</a></p>
% endif
+% if len(branches) > 0:
+<h3 id="branchlist">Branches</h3>
+${self.branch_list(branches)}
+<p><a href="#top">Return to top of this page</a></p>
+% endif
+% if len(tags) > 0:
+<h3 id="taglist">Tags</h3>
+${self.tag_list(tags)}
+<p><a href="#top">Return to top of this page</a></p>
+% endif
</article>\
Return to the top of this page or return to the overview of this repo.
Diff _templates/gitview/git_tag_list.mako
diff --git a/_templates/gitview/git_tag_list.mako b/_templates/gitview/git_tag_list.mako
new file mode 100644
index 0000000..1dc5af2
--- /dev/null
+++ b/_templates/gitview/git_tag_list.mako
@@ -0,0 +1,17 @@
+<%page args="tags"/>\
+<section class="tags"><table><tr>
+<th class="tagname">Tag</th>
+<th class="taglast">Date</th>
+<th class="tagsummary">Commit Message</th>
+<th class="tagauth">Author</th></tr>
+% for tag in sorted(tags, key=lambda k: k['last_commit'], reverse=True):
+<tr><td class="tagname">${tag['name']}</td>
+<td class="taglast">${tag['last_commit'].strftime("%Y-%m-%d")}</td>
+% if tag['commit_link']:
+<td class="tagsummary"><a href="${tag['id']}.html">${tag['summary']}</a></td>
+% else:
+<td class="tagsummary">${tag['summary']}</td>
+% endif
+<td class="tagauth">${tag['author']}</td></tr>
+% endfor
+</table></section>\
Return to the top of this page or return to the overview of this repo.
Diff css/style.css
diff --git a/css/style.css b/css/style.css
index e78c791..87c6a67 100644
--- a/css/style.css
+++ b/css/style.css
@@ -6,12 +6,12 @@ span[id^='ln-']:before { color: #8c8c8c; text-align: right;
padding: 0 0.625em 0 0; width: 2.125em; display: inline-block; }
/* gitview commit list, diff list, and file list */
section.changelist, section.commits, section.diff, section.files,
-section.repolist { font-family: 'Inconsolata', monospace; font-size: 1em; }
-th.filemode, td.filemode , th.filesize, td.filesize, th.cstatus, td.cstatus,
-th.reponame, td.reponame, th.repoauth, td.repoauth, th.repodate, td.repodate,
-th.commdate, td.commdate, th.commauth, td.commauth {
- padding: 0 0.5em 0 0.5em; vertical-align: top; white-space: nowrap; }
-th.filename, td.filename, th.commmesg, td.commmesg, th.repodesc, td.repodesc {
- width: 100%; }
-th.commauth, td.commauth, th.filesize, td.filesize, th.repodate, td.repodate {
+section.repolist, section.branches, section.tags {
+ font-family: 'Inconsolata', monospace; font-size: 1em; }
+.filemode, .filesize, .cstatus, .cadd, .cdel, .reponame, .repoauth,
+.repodate, .commdate, .commauth, .tagname, .taglast, .tagauth, .branchname,
+.branchlast, .branchauth { padding: 0 0.5em 0 0.5em; vertical-align: top;
+ white-space: nowrap; }
+.filename, .commmesg, .repodesc, .tagsummary, .branchsummary { width: 100%; }
+.commauth, .filesize, .repodate, .tagauth, .branchauth, .cadd, .cdel {
text-align: right; }
Return to the top of this page or return to the overview of this repo.