1 | -- resty-gitweb@pages/log.lua |
2 | -- Log 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 |
|
8 | local utils = require("utils/utils") |
9 | local git = require("git/git") |
10 |
|
11 | local builder = require("utils/builder") |
12 | local tabulate = require("utils/tabulate") |
13 | local nav = require("utils/nav") |
14 |
|
15 | local _M = function(repo, repo_dir, branch, n, skip) |
16 | n = tonumber(n or 20) |
17 | skip = tonumber(skip or 0) |
18 |
|
19 | local build = builder:new() |
20 |
|
21 | -- Breadcrumb navigation and repository description |
22 | local breadcrumb_nav = { |
23 | {string.format("/%s", repo.name), repo.name}, |
24 | {string.format("/%s/tree/%s", repo.name, branch.name), branch.name}, |
25 | {string.format("/%s/log/%s", repo.name, branch.name), "log"} |
26 | } |
27 | build:add("<h2>"..nav(breadcrumb_nav, " / ").."</h2>") |
28 | build:add("<p>"..repo.description.."</p>") |
29 |
|
30 | -- Navigation links |
31 | local navlinks = { |
32 | {string.format("/%s/download", repo.name), "Download"}, |
33 | {string.format("/%s/refs", repo.name), "Refs"}, |
34 | {string.format("/%s/log/%s", repo.name, branch.name), "<b>Commit Log</b>"}, |
35 | {string.format("/%s/tree/%s", repo.name, branch.name), "Files"} |
36 | } |
37 |
|
38 | for _, special in pairs(repo.specialfiles) do -- create nav items for special files |
39 | local split = string.split(special, " ") |
40 | table.insert(navlinks, { |
41 | string.format("/%s/blob/%s/%s", repo.name, branch.name, split[2]), |
42 | split[1] |
43 | }) |
44 | end |
45 |
|
46 | build:add([[<div class="nav">]]) |
47 | build:add(nav(navlinks)) |
48 | build:add("</div>") |
49 |
|
50 | -- Commits table |
51 | build:add("<h3>Commits</h3>") |
52 |
|
53 | local commits_head = git.log(repo_dir, branch.name, path, n, skip, true) |
54 |
|
55 | local this_page = string.format("/%s/log/%s", repo.name, branch.name) |
56 |
|
57 | -- Build controls |
58 | local controls = [[<div class="controls">]] |
59 | local prev = false |
60 | if skip ~= 0 then -- previous page? |
61 | local params = "" |
62 | if skip - n > 0 then |
63 | params = params.."?skip="..tostring(tonumber(skip) - tonumber(n)) |
64 | end |
65 | if n ~= 20 then |
66 | if params ~= "" then |
67 | params = params.."&" |
68 | else |
69 | params = params.."?" |
70 | end |
71 | params = params.."n="..tostring(n) |
72 | end |
73 | controls = controls..[[<span><a href="]]..this_page..params..[["><< Previous Page</a></span>]] |
74 | prev = true |
75 | end |
76 | if git.count(repo_dir, commits_head[#commits_head].hash) ~= 1 then -- check if last commit in this list is actually the last |
77 | -- it's not the last, create a "next page" button |
78 | local params = "" |
79 | params = params.."?skip="..tostring(skip+n) |
80 | if n ~= 20 then |
81 | params = params.."&n="..tostring(n) |
82 | end |
83 | if prev then |
84 | controls = controls..[[<span style="margin:0 5px">|</span>]] |
85 | end |
86 | controls = controls..[[<span><a href="]]..this_page..params..[[">Next Page >></a></span>]] |
87 | end |
88 | controls = controls..[[<span float="right"> |
89 | <form class="control-form" method="GET" style="display:inline;margin:0;float:right"> |
90 | <input type="hidden" name="skip" value="]]..tostring(skip)..[["> |
91 | <label for="n">Results</label> |
92 | <select id="n" name="n" onchange="if (this.value != 0){this.form.submit();}"> |
93 | <option disabled selected value style="display:none">]]..tostring(n)..[[</option> |
94 | <option>10</option> |
95 | <option>20</option> |
96 | <option>50</option> |
97 | <option>100</option> |
98 | </select> |
99 | </form> |
100 | </span>]] |
101 | controls = controls.."</div>" |
102 |
|
103 | build:add(controls) |
104 |
|
105 | -- Build commit table |
106 | local commits_table_data = {} |
107 | commits_table_data.class = "log" |
108 | commits_table_data.headers = { |
109 | {"count", [[<span class="q" title="Commit number/count">{#}</span>]]}, |
110 | {"timestamp", "Time"}, |
111 | {"shorthash", "Hash"}, |
112 | {"subject", "Subject"}, |
113 | {"author", "Author"}, |
114 | {"changed_files", [[<span class="q" title="# of files changed">#</span>]]}, |
115 | {"changed_plus", [[<span class="q" title="Insertions">(+)</span>]]}, |
116 | {"changed_minus", [[<span class="q" title="Deletions">(-)</span>]]}, |
117 | {"gpggood", [[<span class="q" title="GPG signature status |
118 | |
119 | G: Good (valid) signature |
120 | B: Bad signature |
121 | U: Good signature with unknown validity |
122 | X: Good signature that has expired |
123 | Y: Good signature made by an expired key |
124 | R: Good signature made by a revoked key |
125 | E: Signature can't be checked (e.g. missing key) |
126 | N: No signature">GPG?</span>]]} |
127 | } |
128 | commits_table_data.rows = {} |
129 |
|
130 | for i, commit in pairs(commits_head) do |
131 | table.insert(commits_table_data.rows, { |
132 | git.count(repo_dir, commit.hash), |
133 | utils.iso8601(commit.timestamp), |
134 | string.format([[<a href="/%s/commit/%s">%s</a>]], repo.name, commit.hash, commit.shorthash), |
135 | utils.html_sanitize(commit.subject), |
136 | string.format([[<a href="mailto:%s">%s</a>]], commit.email, utils.html_sanitize(commit.author)), |
137 | commit.diff.num, |
138 | commit.diff.plus, |
139 | commit.diff.minus, |
140 | commit.gpggood |
141 | }) |
142 | end |
143 |
|
144 | -- Add |
145 | build:add(tabulate(commits_table_data)) |
146 | build:add(controls) |
147 |
|
148 | return build |
149 | end |
150 |
|
151 | return _M |
152 |
|