routes/routes.go (view raw)
1package routes
2
3import (
4 "html/template"
5 "log"
6 "net/http"
7 "os"
8 "path/filepath"
9
10 "github.com/alexedwards/flow"
11 "github.com/dustin/go-humanize"
12 "icyphox.sh/legit/config"
13 "icyphox.sh/legit/git"
14)
15
16type deps struct {
17 c *config.Config
18}
19
20func (d *deps) Index(w http.ResponseWriter, r *http.Request) {
21 dirs, err := os.ReadDir(d.c.Repo.ScanPath)
22 if err != nil {
23 d.Write500(w)
24 log.Printf("reading scan path: %s", err)
25 return
26 }
27
28 type info struct{ Name, Desc, Idle string }
29
30 infos := []info{}
31
32 for _, dir := range dirs {
33 path := filepath.Join(d.c.Repo.ScanPath, dir.Name())
34 gr, err := git.Open(path, "")
35 if err != nil {
36 d.Write500(w)
37 log.Printf("opening dir %s: %s", path, err)
38 return
39 }
40
41 c, err := gr.LastCommit()
42 if err != nil {
43 d.Write500(w)
44 log.Println(err)
45 return
46 }
47
48 var desc string
49 db, err := os.ReadFile(filepath.Join(path, "description"))
50 if err == nil {
51 desc = string(db)
52 } else {
53 desc = ""
54 }
55
56 infos = append(infos, info{
57 Name: dir.Name(),
58 Desc: desc,
59 Idle: humanize.Time(c.Author.When),
60 })
61 }
62
63 tpath := filepath.Join(d.c.Dirs.Templates, "*")
64 t := template.Must(template.ParseGlob(tpath))
65
66 data := make(map[string]interface{})
67 data["meta"] = d.c.Meta
68 data["info"] = infos
69
70 if err := t.ExecuteTemplate(w, "index", data); err != nil {
71 log.Println(err)
72 return
73 }
74}
75
76func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) {
77 name := flow.Param(r.Context(), "name")
78 name = filepath.Clean(name)
79 path := filepath.Join(d.c.Repo.ScanPath, name)
80 gr, err := git.Open(path, "")
81 if err != nil {
82 d.Write404(w)
83 return
84 }
85
86 files, err := gr.FileTree("")
87 if err != nil {
88 d.Write500(w)
89 log.Println(err)
90 return
91 }
92
93 var readmeContent string
94 for _, readme := range d.c.Repo.Readme {
95 readmeContent, _ = gr.FileContent(readme)
96 if readmeContent != "" {
97 break
98 }
99 }
100
101 if readmeContent == "" {
102 log.Printf("no readme found for %s", name)
103 }
104
105 mainBranch, err := gr.FindMainBranch(d.c.Repo.MainBranch)
106 if err != nil {
107 d.Write500(w)
108 log.Println(err)
109 return
110 }
111
112 data := make(map[string]any)
113 data["name"] = name
114 data["ref"] = mainBranch
115 data["readme"] = readmeContent
116
117 d.listFiles(files, data, w)
118 return
119}
120
121func (d *deps) RepoTree(w http.ResponseWriter, r *http.Request) {
122 name := flow.Param(r.Context(), "name")
123 treePath := flow.Param(r.Context(), "...")
124 ref := flow.Param(r.Context(), "ref")
125
126 name = filepath.Clean(name)
127 path := filepath.Join(d.c.Repo.ScanPath, name)
128 gr, err := git.Open(path, ref)
129 if err != nil {
130 d.Write404(w)
131 return
132 }
133
134 files, err := gr.FileTree(treePath)
135 if err != nil {
136 d.Write500(w)
137 log.Println(err)
138 return
139 }
140
141 data := make(map[string]any)
142 data["name"] = name
143 data["ref"] = ref
144 data["parent"] = treePath
145
146 d.listFiles(files, data, w)
147 return
148}
149
150func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) {
151 name := flow.Param(r.Context(), "name")
152 treePath := flow.Param(r.Context(), "...")
153 ref := flow.Param(r.Context(), "ref")
154
155 name = filepath.Clean(name)
156 path := filepath.Join(d.c.Repo.ScanPath, name)
157 gr, err := git.Open(path, ref)
158 if err != nil {
159 d.Write404(w)
160 return
161 }
162
163 contents, err := gr.FileContent(treePath)
164 data := make(map[string]any)
165 data["name"] = name
166 data["ref"] = ref
167
168 d.showFile(contents, data, w)
169 return
170}
171
172func (d *deps) Log(w http.ResponseWriter, r *http.Request) {
173 name := flow.Param(r.Context(), "name")
174 ref := flow.Param(r.Context(), "ref")
175
176 path := filepath.Join(d.c.Repo.ScanPath, name)
177 gr, err := git.Open(path, ref)
178 if err != nil {
179 d.Write404(w)
180 return
181 }
182
183 commits, err := gr.Commits()
184 if err != nil {
185 d.Write500(w)
186 log.Println(err)
187 return
188 }
189
190 tpath := filepath.Join(d.c.Dirs.Templates, "*")
191 t := template.Must(template.ParseGlob(tpath))
192
193 data := make(map[string]interface{})
194 data["commits"] = commits
195 data["meta"] = d.c.Meta
196 data["name"] = name
197 data["ref"] = ref
198
199 if err := t.ExecuteTemplate(w, "log", data); err != nil {
200 log.Println(err)
201 return
202 }
203}
204
205func (d *deps) Diff(w http.ResponseWriter, r *http.Request) {
206 name := flow.Param(r.Context(), "name")
207 ref := flow.Param(r.Context(), "ref")
208
209 path := filepath.Join(d.c.Repo.ScanPath, name)
210 gr, err := git.Open(path, ref)
211 if err != nil {
212 d.Write404(w)
213 return
214 }
215
216 diff, err := gr.Diff()
217 if err != nil {
218 d.Write500(w)
219 log.Println(err)
220 return
221 }
222
223 tpath := filepath.Join(d.c.Dirs.Templates, "*")
224 t := template.Must(template.ParseGlob(tpath))
225
226 data := make(map[string]interface{})
227
228 data["commit"] = diff.Commit
229 data["stat"] = diff.Stat
230 data["diff"] = diff.Diff
231 data["meta"] = d.c.Meta
232 data["name"] = name
233 data["ref"] = ref
234
235 if err := t.ExecuteTemplate(w, "commit", data); err != nil {
236 log.Println(err)
237 return
238 }
239}
240
241func (d *deps) Refs(w http.ResponseWriter, r *http.Request) {
242 name := flow.Param(r.Context(), "name")
243
244 path := filepath.Join(d.c.Repo.ScanPath, name)
245 gr, err := git.Open(path, "")
246 if err != nil {
247 d.Write404(w)
248 return
249 }
250
251 tags, err := gr.Tags()
252 if err != nil {
253 // Non-fatal, we *should* have at least one branch to show.
254 log.Println(err)
255 }
256
257 branches, err := gr.Branches()
258 if err != nil {
259 log.Println(err)
260 d.Write500(w)
261 return
262 }
263
264 tpath := filepath.Join(d.c.Dirs.Templates, "*")
265 t := template.Must(template.ParseGlob(tpath))
266
267 data := make(map[string]interface{})
268
269 data["meta"] = d.c.Meta
270 data["name"] = name
271 data["branches"] = branches
272 data["tags"] = tags
273
274 if err := t.ExecuteTemplate(w, "refs", data); err != nil {
275 log.Println(err)
276 return
277 }
278}
279
280func (d *deps) ServeStatic(w http.ResponseWriter, r *http.Request) {
281 f := flow.Param(r.Context(), "file")
282 f = filepath.Clean(filepath.Join(d.c.Dirs.Static, f))
283
284 http.ServeFile(w, r, f)
285}