Index

resty-gitweb / 7890389

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
315 Dec 2020 18:527890389Update copyright noticesJosh Stockin142G

Blob @ resty-gitweb / app.lua

text/plain5854 bytesdownload raw
1-- resty-gitweb@app.lua
2-- Entry point for git HTTP site implementation
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")
10local parse_uri = require("utils/parse_uri")
11
12local parsed_uri = parse_uri()
13local content
14
15if parsed_uri.repo == nil then
16 content = require("pages/index")(yaml_config)
17else -- repo found
18 local repo
19 for _,r in pairs(yaml_config) do
20 if parsed_uri.repo == r.name then
21 repo = r
22 break
23 end
24 end
25 if repo then
26 local repo_dir = repo.location.dev
27 local view = parsed_uri.parts[2] or "tree"
28 local branch
29
30 if pcall(function() -- if branch is real
31 branch = git.get_head(repo_dir, parsed_uri.parts[3]) -- if parts[3] is nil, defaults to "HEAD"
32 end) then
33 local res, status = pcall(function() -- effectively catch any errors, 404 if any
34 if view == "tree" then -- directory display (with automatic README rendering)
35 local path = parsed_uri.parts
36 table.remove(path, 3) -- branch
37 table.remove(path, 2) -- "tree"
38 table.remove(path, 1) -- repo
39 if #path > 0 then
40 path = table.concat(path, "/").."/"
41 else
42 path = ""
43 end
44
45 content = require("pages/tree")(repo, repo_dir, branch, path)
46 elseif view == "blob" then
47 local path = parsed_uri.parts
48 table.remove(path, 3) -- branch
49 table.remove(path, 2) -- "tree"
50 table.remove(path, 1) -- repo
51 if #path > 0 then
52 path = table.concat(path, "/")
53 else
54 path = ""
55 end
56
57 content = require("pages/blob")(repo, repo_dir, branch, path)
58 elseif view == "raw" then
59 -- /repo/raw/branch/[FILE PATH]
60 elseif view == "log" then
61 content = require("pages/log")(repo, repo_dir, branch, ngx.var.arg_n, ngx.var.arg_skip)
62 elseif view == "refs" then
63 content = require("pages/refs")(repo, repo_dir, branch)
64 elseif view == "download" then
65 content = require("pages/download")(repo, repo_dir, branch)
66 elseif view == "commit" then
67 -- /repo/commit/[COMMIT HASH]
68 end
69 end) -- pcall
70
71 if res ~= true then
72 ngx.say(res)
73 ngx.say(status)
74 ngx.exit(ngx.HTTP_NOT_FOUND)
75 return
76 end
77 end
78 end
79end
80
81if content ~= nil then -- TODO: HTML templates from files, static serving
82 ngx.header.content_type = "text/html"
83ngx.say([[<style>
84@import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,400i,700,700i&display=swap');
85*{
86box-sizing:border-box;
87}
88body{
89font-family:'Fira Sans', sans-serif;
90padding-bottom:200px;
91line-height:1.4;
92max-width:1000px;
93margin:20px auto;
94}
95body>h2{
96 margin-top:5px;
97 margin-bottom:0;
98}
99h3{
100margin-bottom:4px;
101}
102td,th{
103padding:2px 5px;
104border:1px solid #858585;
105text-align:left;
106vertical-align:top;
107}
108th{
109border:1px solid #000;
110}
111table.files,table.log,table.blob-lines{
112 width:100%;
113 max-width:100%;
114}
115table{
116 border-collapse:collapse;
117 overflow:auto;
118 font-family: monospace;
119 font-size:14px;
120}
121table.files td:first-child{
122 padding-right:calc(5px + 1em);
123}
124table.files td:not(:nth-child(2)), table.log td:not(:nth-child(4)){
125 width:1%;
126 white-space:nowrap;
127}
128span.q{
129text-decoration:underline;
130text-decoration-style:dotted;
131}
132.q:hover{
133cursor:help;
134}
135th, tr:hover{ /*darker color for table head, hovered-over rows*/
136 background-color:#dedede;
137}
138div.markdown{
139width:100%;
140padding:20px 50px;
141border:1px solid #858585;
142border-radius:6px;
143}
144img{
145max-width:100%;
146}
147pre{
148background-color:#eee;
149padding:15px;
150overflow-x:auto;
151border-radius:8px;
152}
153:not(pre)>code{
154background-color:#eee;
155padding:2.5px;
156border-radius:4px;
157}
158
159div.blob {
160 border:1px solid #858585;
161 overflow-x: auto;
162}
163table.blob-lines{
164 font-size:1em;
165 max-width:100%;
166 line-height:1;
167}
168table.blob-lines tr:hover {
169 background-color: inherit;
170}
171table.blob-lines td{
172 border:none;
173 padding:1px 5px;
174}
175table.blob-lines td:first-child{
176 text-align: right;
177 padding-left:20px;
178 cursor: pointer;
179 user-select: none;
180 color:#858585;
181 max-width:1%;
182 white-space:nowrap;
183}
184table.blob-lines td:first-child:hover{
185 color: #454545;
186}
187table.blob-lines td:nth-child(2){
188 width:100%;
189 white-space:pre;
190}
191
192a{
193text-decoration:none;
194color: #0077aa;
195}
196a:hover{
197 text-decoration:underline;
198}
199.home-banner h1 {
200 margin-top:40px;
201 margin-bottom:0;
202}
203.home-banner p {
204 margin-top:8px;
205 margin-bottom:30px;
206}
207.repo-section .name {
208 margin-bottom:0;
209}
210.repo-section h3 {
211 margin-top:10px;
212}
213.repo-section .description {
214 margin-top:8px;
215}
216.repo-section .nav {
217 margin-top:10px;
218}
219hr {
220 margin: 20px 0;
221}
222</style>]])
223
224 if parsed_uri.repo then
225 local arrow_left_circle = [[<img style="width:1.2em;height:1.2em;vertical-align:middle;margin-right:0.2em" src="https://joshuas3.s3.amazonaws.com/svg/arrow-left.svg"/>]]
226 ngx.say("<a style=\"margin-left:-1.35em\" href=\"/\">"..arrow_left_circle.."<span style=\"vertical-align:middle\">Index</span></a>")
227 end
228 ngx.say(content:build())
229 ngx.exit(ngx.HTTP_OK)
230 return
231else
232 ngx.exit(ngx.HTTP_NOT_FOUND) -- default behavior
233 return
234end
235