all repos — legit @ 7fe98772b079cca83b854e8f8a6be5dc55c10483

web frontend for git

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		desc := getDescription(path)
 49
 50		infos = append(infos, info{
 51			Name: dir.Name(),
 52			Desc: desc,
 53			Idle: humanize.Time(c.Author.When),
 54		})
 55	}
 56
 57	tpath := filepath.Join(d.c.Dirs.Templates, "*")
 58	t := template.Must(template.ParseGlob(tpath))
 59
 60	data := make(map[string]interface{})
 61	data["meta"] = d.c.Meta
 62	data["info"] = infos
 63
 64	if err := t.ExecuteTemplate(w, "index", data); err != nil {
 65		log.Println(err)
 66		return
 67	}
 68}
 69
 70func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) {
 71	name := flow.Param(r.Context(), "name")
 72	name = filepath.Clean(name)
 73	path := filepath.Join(d.c.Repo.ScanPath, name)
 74	gr, err := git.Open(path, "")
 75	if err != nil {
 76		d.Write404(w)
 77		return
 78	}
 79
 80	commits, err := gr.Commits()
 81	if err != nil {
 82		d.Write500(w)
 83		log.Println(err)
 84		return
 85	}
 86
 87	var readmeContent string
 88	for _, readme := range d.c.Repo.Readme {
 89		readmeContent, _ = gr.FileContent(readme)
 90		if readmeContent != "" {
 91			break
 92		}
 93	}
 94
 95	if readmeContent == "" {
 96		log.Printf("no readme found for %s", name)
 97	}
 98
 99	mainBranch, err := gr.FindMainBranch(d.c.Repo.MainBranch)
100	if err != nil {
101		d.Write500(w)
102		log.Println(err)
103		return
104	}
105
106	tpath := filepath.Join(d.c.Dirs.Templates, "*")
107	t := template.Must(template.ParseGlob(tpath))
108
109	if len(commits) >= 3 {
110		commits = commits[:3]
111	}
112
113	data := make(map[string]any)
114	data["name"] = name
115	data["ref"] = mainBranch
116	data["readme"] = readmeContent
117	data["commits"] = commits
118	data["desc"] = getDescription(path)
119
120	if err := t.ExecuteTemplate(w, "repo", data); err != nil {
121		log.Println(err)
122		return
123	}
124
125	return
126}
127
128func (d *deps) RepoTree(w http.ResponseWriter, r *http.Request) {
129	name := flow.Param(r.Context(), "name")
130	treePath := flow.Param(r.Context(), "...")
131	ref := flow.Param(r.Context(), "ref")
132
133	name = filepath.Clean(name)
134	path := filepath.Join(d.c.Repo.ScanPath, name)
135	gr, err := git.Open(path, ref)
136	if err != nil {
137		d.Write404(w)
138		return
139	}
140
141	files, err := gr.FileTree(treePath)
142	if err != nil {
143		d.Write500(w)
144		log.Println(err)
145		return
146	}
147
148	data := make(map[string]any)
149	data["name"] = name
150	data["ref"] = ref
151	data["parent"] = treePath
152	data["desc"] = getDescription(path)
153
154	d.listFiles(files, data, w)
155	return
156}
157
158func (d *deps) FileContent(w http.ResponseWriter, r *http.Request) {
159	name := flow.Param(r.Context(), "name")
160	treePath := flow.Param(r.Context(), "...")
161	ref := flow.Param(r.Context(), "ref")
162
163	name = filepath.Clean(name)
164	path := filepath.Join(d.c.Repo.ScanPath, name)
165	gr, err := git.Open(path, ref)
166	if err != nil {
167		d.Write404(w)
168		return
169	}
170
171	contents, err := gr.FileContent(treePath)
172	data := make(map[string]any)
173	data["name"] = name
174	data["ref"] = ref
175	data["desc"] = getDescription(path)
176	data["path"] = treePath
177
178	d.showFile(contents, data, w)
179	return
180}
181
182func (d *deps) Log(w http.ResponseWriter, r *http.Request) {
183	name := flow.Param(r.Context(), "name")
184	ref := flow.Param(r.Context(), "ref")
185
186	path := filepath.Join(d.c.Repo.ScanPath, name)
187	gr, err := git.Open(path, ref)
188	if err != nil {
189		d.Write404(w)
190		return
191	}
192
193	commits, err := gr.Commits()
194	if err != nil {
195		d.Write500(w)
196		log.Println(err)
197		return
198	}
199
200	tpath := filepath.Join(d.c.Dirs.Templates, "*")
201	t := template.Must(template.ParseGlob(tpath))
202
203	data := make(map[string]interface{})
204	data["commits"] = commits
205	data["meta"] = d.c.Meta
206	data["name"] = name
207	data["ref"] = ref
208	data["desc"] = getDescription(path)
209
210	if err := t.ExecuteTemplate(w, "log", data); err != nil {
211		log.Println(err)
212		return
213	}
214}
215
216func (d *deps) Diff(w http.ResponseWriter, r *http.Request) {
217	name := flow.Param(r.Context(), "name")
218	ref := flow.Param(r.Context(), "ref")
219
220	path := filepath.Join(d.c.Repo.ScanPath, name)
221	gr, err := git.Open(path, ref)
222	if err != nil {
223		d.Write404(w)
224		return
225	}
226
227	diff, err := gr.Diff()
228	if err != nil {
229		d.Write500(w)
230		log.Println(err)
231		return
232	}
233
234	tpath := filepath.Join(d.c.Dirs.Templates, "*")
235	t := template.Must(template.ParseGlob(tpath))
236
237	data := make(map[string]interface{})
238
239	data["commit"] = diff.Commit
240	data["stat"] = diff.Stat
241	data["diff"] = diff.Diff
242	data["meta"] = d.c.Meta
243	data["name"] = name
244	data["ref"] = ref
245	data["desc"] = getDescription(path)
246
247	if err := t.ExecuteTemplate(w, "commit", data); err != nil {
248		log.Println(err)
249		return
250	}
251}
252
253func (d *deps) Refs(w http.ResponseWriter, r *http.Request) {
254	name := flow.Param(r.Context(), "name")
255
256	path := filepath.Join(d.c.Repo.ScanPath, name)
257	gr, err := git.Open(path, "")
258	if err != nil {
259		d.Write404(w)
260		return
261	}
262
263	tags, err := gr.Tags()
264	if err != nil {
265		// Non-fatal, we *should* have at least one branch to show.
266		log.Println(err)
267	}
268
269	branches, err := gr.Branches()
270	if err != nil {
271		log.Println(err)
272		d.Write500(w)
273		return
274	}
275
276	tpath := filepath.Join(d.c.Dirs.Templates, "*")
277	t := template.Must(template.ParseGlob(tpath))
278
279	data := make(map[string]interface{})
280
281	data["meta"] = d.c.Meta
282	data["name"] = name
283	data["branches"] = branches
284	data["tags"] = tags
285	data["desc"] = getDescription(path)
286
287	if err := t.ExecuteTemplate(w, "refs", data); err != nil {
288		log.Println(err)
289		return
290	}
291}
292
293func (d *deps) ServeStatic(w http.ResponseWriter, r *http.Request) {
294	f := flow.Param(r.Context(), "file")
295	f = filepath.Clean(filepath.Join(d.c.Dirs.Static, f))
296
297	http.ServeFile(w, r, f)
298}
299
300func getDescription(path string) (desc string) {
301	db, err := os.ReadFile(filepath.Join(path, "description"))
302	if err == nil {
303		desc = string(db)
304	} else {
305		desc = ""
306	}
307	return
308}