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