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