all repos — legit @ 60298a69538ccdda417613a09e5acbd917bfc53a

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
177	d.showFile(contents, data, w)
178	return
179}
180
181func (d *deps) Log(w http.ResponseWriter, r *http.Request) {
182	name := flow.Param(r.Context(), "name")
183	ref := flow.Param(r.Context(), "ref")
184
185	path := filepath.Join(d.c.Repo.ScanPath, name)
186	gr, err := git.Open(path, ref)
187	if err != nil {
188		d.Write404(w)
189		return
190	}
191
192	commits, err := gr.Commits()
193	if err != nil {
194		d.Write500(w)
195		log.Println(err)
196		return
197	}
198
199	tpath := filepath.Join(d.c.Dirs.Templates, "*")
200	t := template.Must(template.ParseGlob(tpath))
201
202	data := make(map[string]interface{})
203	data["commits"] = commits
204	data["meta"] = d.c.Meta
205	data["name"] = name
206	data["ref"] = ref
207	data["desc"] = getDescription(path)
208
209	if err := t.ExecuteTemplate(w, "log", data); err != nil {
210		log.Println(err)
211		return
212	}
213}
214
215func (d *deps) Diff(w http.ResponseWriter, r *http.Request) {
216	name := flow.Param(r.Context(), "name")
217	ref := flow.Param(r.Context(), "ref")
218
219	path := filepath.Join(d.c.Repo.ScanPath, name)
220	gr, err := git.Open(path, ref)
221	if err != nil {
222		d.Write404(w)
223		return
224	}
225
226	diff, err := gr.Diff()
227	if err != nil {
228		d.Write500(w)
229		log.Println(err)
230		return
231	}
232
233	tpath := filepath.Join(d.c.Dirs.Templates, "*")
234	t := template.Must(template.ParseGlob(tpath))
235
236	data := make(map[string]interface{})
237
238	data["commit"] = diff.Commit
239	data["stat"] = diff.Stat
240	data["diff"] = diff.Diff
241	data["meta"] = d.c.Meta
242	data["name"] = name
243	data["ref"] = ref
244	data["desc"] = getDescription(path)
245
246	if err := t.ExecuteTemplate(w, "commit", data); err != nil {
247		log.Println(err)
248		return
249	}
250}
251
252func (d *deps) Refs(w http.ResponseWriter, r *http.Request) {
253	name := flow.Param(r.Context(), "name")
254
255	path := filepath.Join(d.c.Repo.ScanPath, name)
256	gr, err := git.Open(path, "")
257	if err != nil {
258		d.Write404(w)
259		return
260	}
261
262	tags, err := gr.Tags()
263	if err != nil {
264		// Non-fatal, we *should* have at least one branch to show.
265		log.Println(err)
266	}
267
268	branches, err := gr.Branches()
269	if err != nil {
270		log.Println(err)
271		d.Write500(w)
272		return
273	}
274
275	tpath := filepath.Join(d.c.Dirs.Templates, "*")
276	t := template.Must(template.ParseGlob(tpath))
277
278	data := make(map[string]interface{})
279
280	data["meta"] = d.c.Meta
281	data["name"] = name
282	data["branches"] = branches
283	data["tags"] = tags
284	data["desc"] = getDescription(path)
285
286	if err := t.ExecuteTemplate(w, "refs", data); err != nil {
287		log.Println(err)
288		return
289	}
290}
291
292func (d *deps) ServeStatic(w http.ResponseWriter, r *http.Request) {
293	f := flow.Param(r.Context(), "file")
294	f = filepath.Clean(filepath.Join(d.c.Dirs.Static, f))
295
296	http.ServeFile(w, r, f)
297}
298
299func getDescription(path string) (desc string) {
300	db, err := os.ReadFile(filepath.Join(path, "description"))
301	if err == nil {
302		desc = string(db)
303	} else {
304		desc = ""
305	}
306	return
307}