all repos — legit @ subdir

web frontend for git

routes/routes.go (view raw)

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