all repos — legit @ 60e1092dbcfacb28b30d052b0f73d2249cd63a9d

web frontend for git, written in go

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}