Index

resty-gitweb / 72a1883

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
1713 Oct 2021 20:5472a1883Update S3 image source endpointsJosh Stockin122G

Blob @ resty-gitweb / pages / tree.lua

text/plain7385 bytesdownload raw
1-- resty-gitweb@pages/tree.lua
2-- Tree 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")
10
11local builder = require("utils/builder")
12local tabulate = require("utils/tabulate")
13local nav = require("utils/nav")
14
15local _M = function(repo, repo_dir, branch, path)
16
17 -- Pre checks
18 if path ~= "" then -- make sure path exists
19 local path_tree = git.list_tree(repo_dir, branch.name, string.sub(path, 1, path:len() - 1))
20 if #path_tree.dirs == 0 then -- no path found
21 error("tree "..path.." is nonexistent")
22 end
23 end
24
25 if branch.name == "" then
26 branch.name = branch.hash
27 end
28
29
30 local build = builder:new()
31
32 -- Breadcrumb navigation and repository description
33 local breadcrumb_nav = {
34 {string.format("/%s", repo.name), repo.name},
35 {string.format("/%s/tree/%s", repo.name, branch.name), branch.name},
36 }
37
38 -- Navigation links
39 local navlinks = {
40 {string.format("/%s/download", repo.name), "Download"},
41 {string.format("/%s/refs", repo.name), "Refs"},
42 {string.format("/%s/log/%s", repo.name, branch.name), "Commit Log"},
43 {string.format("/%s/tree/%s", repo.name, branch.name), "<b>Files</b>"}
44 }
45
46 for _, special in pairs(repo.specialfiles) do -- create nav items for special files
47 local split = string.split(special, " ")
48 table.insert(navlinks, {
49 string.format("/%s/blob/%s/%s", repo.name, branch.name, split[2]),
50 split[1]
51 })
52 end
53
54 build{
55 build.h2{nav(breadcrumb_nav, " / ")},
56 build.p{repo.description},
57 build.div{class="nav", nav(navlinks)}
58 }
59
60 -- Latest Commit table
61 build{
62 build.h3{"Latest Commit"}
63 }
64
65 local commit = git.log(repo_dir, branch.name, path ~= "" and path.."/" or "", 1, 0, true)[1]
66
67 local commits_table_data = {}
68 commits_table_data.class = "log"
69 commits_table_data.headers = {
70 {"count", [[<span class="q" title="Commit number/count">{#}</span>]]},
71 {"timestamp", "Time"},
72 {"shorthash", "Hash"},
73 {"subject", "Subject"},
74 {"author", "Author"},
75 {"changed_files", [[<span class="q" title="# of files changed">#</span>]]},
76 {"changed_plus", [[<span class="q" title="Insertions">(+)</span>]]},
77 {"changed_minus", [[<span class="q" title="Deletions">(-)</span>]]},
78 {"gpggood", [[<span class="q" title="GPG signature status
79
80G: Good (valid) signature
81B: Bad signature
82U: Good signature with unknown validity
83X: Good signature that has expired
84Y: Good signature made by an expired key
85R: Good signature made by a revoked key
86E: Signature can't be checked (e.g. missing key)
87N: No signature">GPG?</span>]]}
88 }
89 commits_table_data.rows = {}
90
91 table.insert(commits_table_data.rows, {
92 git.count(repo_dir, commit.hash),
93 utils.iso8601(commit.timestamp),
94 string.format([[<a href="/%s/commit/%s">%s</a>]], repo.name, commit.hash, commit.shorthash),
95 utils.html_sanitize(commit.subject),
96 string.format([[<a href="mailto:%s">%s</a>]], commit.email, utils.html_sanitize(commit.author)),
97 commit.diff.num,
98 commit.diff.plus,
99 commit.diff.minus,
100 commit.gpggood
101 })
102
103 build{tabulate(commits_table_data)}
104
105 -- Tree/files table
106 local title = build.h3{"Tree"}
107
108 if path ~= "" then -- build path with hyperlinks for section header
109 local split = string.split(path, "/")
110 table.remove(split, #split)
111 local base = "/"..repo.name.."/tree/"..branch.name
112 title{" @ ", build.a{href=base, repo.name}}
113 local b = ""
114 for _, part in pairs(split) do
115 b = b.."/"..part
116 title{" / ", build.a{href=base..b, part}}
117 end
118 end
119
120 build{title}
121
122 local files = git.list_tree(repo_dir, branch.name, path)
123
124 local files_table_data = {}
125 files_table_data.class = "files"
126 files_table_data.headers = {
127 {"object", "Object"},
128 {"subject", "Latest Commit Subject"},
129 {"timestamp", "Time"},
130 {"shorthash", "Hash"}}
131 files_table_data.rows = {}
132
133 local file_icon = [[<img style="width:1em;height:1em;vertical-align:middle;margin-right:0.5em;" alt="file" src="https://joshstock.in/static/svg/file.svg"/>]]
134 local folder_icon = [[<img style="width:1em;height:1em;vertical-align:middle;margin-right:0.5em;fill:#ffe9a2;" alt="folder" src="https://joshstock.in/static/svg/folder.svg"/>]]
135
136 -- .. directory
137 if path ~= "" then
138 local split = string.split(string.sub(path, 1, path:len() - 1), "/")
139 table.remove(split, #split)
140 if #split > 0 then -- deeper than 1 directory
141 table.insert(files_table_data.rows, {
142 string.format([[%s<a href="/%s/tree/%s/%s">..</a>]], folder_icon, repo.name, branch.name, table.concat(split, "/")),
143 "","",""
144 })
145 else -- only one directory deep
146 table.insert(files_table_data.rows, {
147 string.format([[%s<a href="/%s/tree/%s">..</a>]], folder_icon, repo.name, branch.name),
148 "","",""
149 })
150 end
151 end
152
153 -- Regular directories
154 for _, dir in pairs(files.dirs) do
155 local lastedit = git.log(repo_dir, branch.name.." -1", dir, 1, 0, false)[1]
156 local split = string.split(dir, "/")
157 local name = split[#split]
158 table.insert(files_table_data.rows, {
159 string.format([[%s<a href="/%s/tree/%s/%s">%s</a>]], folder_icon, repo.name, branch.name, dir, name),
160 utils.html_sanitize(lastedit.subject),
161 utils.iso8601(lastedit.timestamp),
162 string.format([[<a href="/%s/commit/%s">%s</a>]], repo.name, lastedit.hash, lastedit.shorthash)
163 })
164 end
165
166 -- Regular files
167 for _, file in pairs(files.files) do
168 local lastedit = git.log(repo_dir, branch.name.." -1", file, 1, 0, false)[1]
169 local split = string.split(file, "/")
170 local name = split[#split]
171 table.insert(files_table_data.rows, {
172 string.format([[%s<a href="/%s/blob/%s/%s">%s</a>]], file_icon, repo.name, branch.name, file, name),
173 utils.html_sanitize(lastedit.subject),
174 utils.iso8601(lastedit.timestamp),
175 string.format([[<a href="/%s/commit/%s">%s</a>]], repo.name, lastedit.hash, lastedit.shorthash)
176 })
177 end
178
179 build{tabulate(files_table_data)}
180
181 -- Look for and render README if it exists
182 for _, file in pairs(files.files) do
183 local split = string.split(file, "/")
184 local l = split[#split]:lower()
185 if l:match("^readme") then
186 build{build.h3{"README"}}
187 local repo = git.repo.open(repo_dir)
188 local text = git.read_blob(repo, branch.name, file)
189 git.repo.free(repo)
190 local s = l:len()
191 if string.sub(l, s-2, s) == ".md" then
192 build{build.div{class="markdown", utils.markdown(text)}}
193 else
194 build{build.pre{build.code{text}}}
195 end
196 break
197 end
198 end
199
200 return build
201end
202
203return _M
204