1 | local utils = require("utils") |
2 | local git = require("git_commands") |
3 |
|
4 | ngx.say([[<style> |
5 | *{ |
6 | box-sizing:border-box; |
7 | } |
8 | body{ |
9 | font-family:sans-serif; |
10 | } |
11 | .container>h3{ |
12 | margin-bottom:4px; |
13 | } |
14 | td,th{ |
15 | padding:2px 5px; |
16 | border:1px solid #858585; |
17 | text-align:left; |
18 | vertical-align:top; |
19 | } |
20 | th{ |
21 | border:1px solid #000; |
22 | } |
23 | table{ |
24 | width:100%; |
25 | border-collapse:collapse; |
26 | overflow:auto; |
27 | font-family:monospace; |
28 | font-size:14px; |
29 | } |
30 | table.log td:not(:nth-child(3)){ |
31 | max-width:1%; |
32 | white-space:nowrap; |
33 | } |
34 | table.tree td:not(:nth-child(2)){ |
35 | max-width:1%; |
36 | white-space:nowrap; |
37 | } |
38 | .q{ |
39 | text-decoration:underline; |
40 | text-decoration-style:dotted; |
41 | } |
42 | .q:hover{ |
43 | cursor:help; |
44 | } |
45 | tr:hover,th{ /*darker color for table head, hovered-over rows*/ |
46 | background-color:#dedede; |
47 | } |
48 | .container{ |
49 | max-width: 1000px; |
50 | margin:20px auto; |
51 | } |
52 | .readme{ |
53 | width:100%; |
54 | padding:20px 50px; |
55 | border:1px solid #858585; |
56 | border-top:none; |
57 | border-radius:0 0 6px 6px; |
58 | } |
59 | img{ |
60 | max-width:100%; |
61 | } |
62 | pre{ |
63 | background-color:#eee; |
64 | padding:15px; |
65 | overflow-x:auto; |
66 | } |
67 | :not(pre)>code{ |
68 | background-color:#eee; |
69 | padding:2px; |
70 | } |
71 | .gpggood { |
72 | font-weight: bold; |
73 | color: slategray; |
74 | } |
75 | .gpggood-G { |
76 | color: green; |
77 | } |
78 | .gpggood-N { |
79 | color: red; |
80 | } |
81 | .gpggood-E { |
82 | color: goldenrod |
83 | } |
84 | td>svg { |
85 | width:1em; |
86 | height:1em; |
87 | vertical-align:middle; |
88 | } |
89 | </style>]]) |
90 | ngx.say("<body>") |
91 |
|
92 | local print_table |
93 | print_table = function(t, l) |
94 | l = l or 0 |
95 | local n = 0 |
96 | for i,v in pairs(t) do n = n + 1 break end |
97 | if n > 0 then |
98 | ngx.print("{\n") |
99 | for i,v in pairs(t) do |
100 | for i=0,l do ngx.print(" ") end |
101 | ngx.print("<span style='color:red'>",i,"</span>: ") |
102 | if type(v) ~= "table" then |
103 | if type(v) == "string" then |
104 | ngx.print("\"") |
105 | local s = v:gsub("&", "&"):gsub("<","<"):gsub(">",">") |
106 | ngx.print(s) |
107 | ngx.print("\"") |
108 | else |
109 | ngx.print(v) |
110 | end |
111 | else |
112 | print_table(v,l+1) |
113 | end |
114 | ngx.print("\n") |
115 | end |
116 | for i=0,l-1 do ngx.print(" ") end |
117 | ngx.print("}") |
118 | else |
119 | ngx.print("{}") |
120 | end |
121 | end |
122 |
|
123 | local name = "ncurses-minesweeper" |
124 | --local name = "lognestmonster" |
125 | --local name = "auto-plow" |
126 | --local name = "joshstock.in" |
127 |
|
128 | local repo = "/home/josh/repos/"..name |
129 |
|
130 | local headname = git.get_head(repo) |
131 |
|
132 | ngx.say("<div class=\"container\"><h2>"..name.." / "..headname.name.."</h2>") |
133 | ngx.say("<p>< DESCRIPTION GOES HERE ></p>") |
134 | ngx.print("<p>") |
135 | ngx.print("<a href=\"#\">Refs</a> | ") |
136 | ngx.print("<a href=\"#\">Commit Log</a> | ") |
137 | ngx.print("<a href=\"#\">Files</a> | ") |
138 | ngx.print("<a href=\"#\">README</a> | ") |
139 | ngx.print("<a href=\"#\">LICENSE</a>") |
140 | ngx.print("</p></div>") |
141 |
|
142 | local commits_head = git.log(repo, "@", "", 1, 0, true) |
143 | ngx.say("<div class=\"container\"><h3>Latest Commit</h3><table class=\"log\">") |
144 | ngx.print("<tr>") |
145 | ngx.print("<th>Time</th>") |
146 | ngx.print("<th>Hash</th>") |
147 | ngx.print("<th>Subject</th>") |
148 | ngx.print("<th>Author</th>") |
149 | ngx.print("<th>Email</th>") |
150 | ngx.print("<th><span class=\"q\" title=\"# of files changed\">#</span></th>") |
151 | ngx.print("<th><span class=\"q\" title=\"Insertions\">(+)</span></th>") |
152 | ngx.print("<th><span class=\"q\" title=\"Deletions\">(-)</span></th>") |
153 | ngx.print([[<th><span class="q" title="GPG signature status |
154 | * |
155 | G: Good (valid) signature |
156 | B: Bad signature |
157 | U: Good signature with unknown validity |
158 | X: Good signature that has expired |
159 | Y: Good signature made by an expired key |
160 | R: Good signature made by a revoked key |
161 | E: Signature can't be checked (e.g. missing key) |
162 | N: No signature">GPG?</span></th>]]) |
163 | ngx.print("</tr>") |
164 | for i,commit in pairs(commits_head) do |
165 | ngx.print("<tr class=\"commit\">") |
166 | ngx.print("<td class=\"timestamp\">",utils.iso8601(commit.timestamp),"</td>") |
167 | ngx.print("<td class=\"hash\"><a class=\"hash\" href=\"/"..name.."/commit/",commit.hash,"\">",commit.shorthash,"</a></td>") |
168 | ngx.print("<td class=\"subject\">",commit.subject,"</td>") |
169 | ngx.print("<td class=\"author\">",commit.author,"</td>") |
170 | ngx.print("<td class=\"email\"><a class=\"email\" href=\"mailto:",commit.email,"\">",commit.email,"</a></td>") |
171 | ngx.print("<td class=\"changed\">",commit.diff.num,"</td>") |
172 | ngx.print("<td class=\"plus\"",commit.diff.plus>commit.diff.minus and " style=\"color:green;font-weight:bold\"" or "",">",commit.diff.plus~=0 and commit.diff.plus or "","</td>") |
173 | ngx.print("<td class=\"minus\"",commit.diff.minus>commit.diff.plus and " style=\"color:red;font-weight:bold\"" or "",">",commit.diff.minus~=0 and commit.diff.minus or "","</td>") |
174 | ngx.print("<td class=\"gpggood gpggood-",commit.gpggood ~= "" and commit.gpggood or "NONE","\">",commit.gpggood,"</td>") |
175 | ngx.say("</tr>") |
176 | end |
177 | ngx.say("</table>") |
178 | ngx.say("</div>") |
179 |
|
180 | ngx.say("<div class=\"container\"><h3>Files</h3><table class=\"tree\">") |
181 | ngx.print("<tr>") |
182 | ngx.print("<th>Object</th><th>Latest Commit Subject</th><th>Time</th><th>Hash</th>") |
183 | ngx.say("</tr>") |
184 | local files = git.list_tree(repo, "@", "") |
185 |
|
186 | local iconfolder = [[<svg viewBox="0 0 24 24" width="12" height="15" stroke="currentColor" stroke-width="2" fill="#FFE9A2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>]] |
187 | local iconfile = [[<svg viewBox="0 0 24 24" width="12" height="15" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>]] |
188 |
|
189 | for i,v in pairs(files.dirs) do |
190 | ngx.print("<tr>") |
191 | ngx.print("<td>",iconfolder," <a href=\"/",name,"/master/tree/",v,"\">",v,"</a></td>") |
192 | local lastedit = git.log(repo, "@ -1", v, 1, 0, false)[1] |
193 | ngx.print("<td>",lastedit.subject,"</td>") |
194 | ngx.print("<td class=\"timestamp\">",utils.iso8601(lastedit.timestamp),"</td>") |
195 | ngx.print("<td class=\"hash\"><a href=\"",lastedit.hash,"\">",lastedit.shorthash,"</a></td>") |
196 | ngx.say("</tr>") |
197 | end |
198 | for i,v in pairs(files.files) do |
199 | ngx.print("<tr>") |
200 | ngx.print("<td>",iconfile," <a href=\"/",name,"/master/blob/",v,"\">",v,"</a></td>") |
201 | local lastedit = git.log(repo, "@ -1", v, 1, 0, false)[1] |
202 | ngx.print("<td>",lastedit.subject,"</td>") |
203 | ngx.print("<td class=\"timestamp\">",utils.iso8601(lastedit.timestamp),"</td>") |
204 | ngx.print("<td class=\"hash\"><a href=\"/",name,"/commit/",lastedit.hash,"\">",lastedit.shorthash,"</a></td>") |
205 | ngx.say("</tr>") |
206 | end |
207 | ngx.say("</table></div>") |
208 |
|
209 | ngx.say("<div class=\"container\"><h3 style=\"margin:0;padding:10px;background-color:#dedede;border-radius:6px 6px 0 0;border:1px solid #000\">README</h3><div class=\"readme\">") |
210 | local README = git.show_file(repo, "@", "README.md") |
211 | ngx.say(utils.markdown(README)) |
212 | ngx.say("</div></div>") |
213 |
|
214 | ngx.say("</body>") |
215 |
|
216 | ngx.exit(ngx.HTTP_OK) |
217 |
|