Index

resty-gitweb / 1f62b32

A git web interface for Lua/OpenResty (you're on it right now!)

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
415 Dec 2020 20:211f62b32Expand tabs to spaces in blob renderingJosh Stockin121G

Blob @ resty-gitweb / pages / blob.lua

text/plain4928 bytesdownload raw
1-- resty-gitweb@pages/blob.lua
2-- File blob page builder
3
4-- Copyright (c) 2020 Joshua 'joshuas3' Stockin
5-- <https://git.joshstock.in/resty-gitweb>
6-- This software is licensed under the MIT License.
7
8local utils = require("utils/utils")
9local git = require("git/git_commands")
10
11local builder = require("utils/builder")
12local tabulate = require("utils/tabulate")
13local nav = require("utils/nav")
14
15local _M = function(repo, repo_dir, branch, file_path)
16
17 -- Pre checks
18 if file_path ~= "" then -- make sure path exists
19 local path_tree = git.list_tree(repo_dir, branch.name, file_path)
20 if #path_tree.files == 0 then -- no path found
21 return nil
22 end
23 else
24 return nil
25 end
26
27 local build = builder:new()
28
29 -- Breadcrumb navigation and repository description
30 local breadcrumb_nav = {
31 {string.format("/%s", repo.name), repo.name},
32 {string.format("/%s/tree/%s", repo.name, branch.name), branch.name},
33 }
34 build:add("<h2>"..nav(breadcrumb_nav, " / ").."</h2>")
35 build:add("<p>"..repo.description.."</p>")
36
37 -- Navigation links
38 local navlinks = {
39 {string.format("/%s/download", repo.name), "Download"},
40 {string.format("/%s/refs", repo.name), "Refs"},
41 {string.format("/%s/log/%s", repo.name, branch.name), "Commit Log"},
42 {string.format("/%s/tree/%s", repo.name, branch.name), "<b>Files</b>"}
43 }
44
45 for _, special in pairs(repo.specialfiles) do -- create nav items for special files
46 local split = string.split(special, " ")
47 table.insert(navlinks, {
48 string.format("/%s/blob/%s/%s", repo.name, branch.name, split[2]),
49 split[1]
50 })
51 end
52
53 build:add([[<div class="nav">]])
54 build:add(nav(navlinks))
55 build:add("</div>")
56
57 -- Latest Commit table
58 build:add("<h3>Latest Commit</h3>")
59
60 local commit = git.log(repo_dir, branch.name, file_path, 1, 0, true)[1]
61
62 local commits_table_data = {}
63 commits_table_data.class = "log"
64 commits_table_data.headers = {
65 {"count", [[<span class="q" title="Commit number/count">{#}</span>]]},
66 {"timestamp", "Time"},
67 {"shorthash", "Hash"},
68 {"subject", "Subject"},
69 {"author", "Author"},
70 {"changed_files", [[<span class="q" title="# of files changed">#</span>]]},
71 {"changed_plus", [[<span class="q" title="Insertions">(+)</span>]]},
72 {"changed_minus", [[<span class="q" title="Deletions">(-)</span>]]},
73 {"gpggood", [[<span class="q" title="GPG signature status
74
75G: Good (valid) signature
76B: Bad signature
77U: Good signature with unknown validity
78X: Good signature that has expired
79Y: Good signature made by an expired key
80R: Good signature made by a revoked key
81E: Signature can't be checked (e.g. missing key)
82N: No signature">GPG?</span>]]}
83 }
84 commits_table_data.rows = {}
85
86 table.insert(commits_table_data.rows, {
87 git.count(repo_dir, commit.hash),
88 utils.iso8601(commit.timestamp),
89 string.format([[<a href="/%s/commit/%s">%s</a>]], repo.name, commit.hash, commit.shorthash),
90 utils.html_sanitize(commit.subject),
91 string.format([[<a href="mailto:%s">%s</a>]], commit.email, utils.html_sanitize(commit.author)),
92 commit.diff.num,
93 commit.diff.plus,
94 commit.diff.minus,
95 commit.gpggood
96 })
97
98 build:add(tabulate(commits_table_data))
99
100 -- Tree breadcrumb
101 build:add("<h3>Blob @ ")
102
103 local treelinks = {
104 {string.format("/%s/tree/%s", repo.name, branch.name), repo.name}
105 }
106
107 local base_path = treelinks[1][1] -- /repo/tree/branch
108
109 local path_string = ""
110 local path_split = string.split(file_path, "/")
111 local file_name = path_split[#path_split]
112 table.remove(path_split, #path_split)
113
114 for _, part in pairs(path_split) do
115 path_string = path_string.."/"..part
116 table.insert(treelinks, {base_path..path_string, part})
117 end
118 path_string = path_string.."/"..file_name
119 table.insert(treelinks, {
120 string.format("/%s/blob/%s"..path_string, repo.name, branch.name), file_name
121 })
122
123 build:add(nav(treelinks, " / "))
124 build:add("</h3>")
125
126 -- File
127 build:add([[<div class="blob">]])
128
129 local content = git.show_file(repo_dir, branch.name, file_path)
130
131 local text_table = {}
132 text_table.class = "blob-lines"
133 text_table.headers = {}
134 text_table.rows = {}
135 for i, line in pairs(string.split(utils.highlight(content, file_name), "\n")) do
136 if line ~= "" then
137 local ftab = line:gsub("\t", " ")
138 table.insert(text_table.rows, {i, ftab})
139 else
140 table.insert(text_table.rows, {i, "\n"}) -- preserve newlines for copying/pasting
141 end
142 end
143
144 build:add(tabulate(text_table))
145
146 build:add("</div>")
147
148 return build
149end
150
151return _M
152