web frontend for git (tangled's grandpa)
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

routes: index view

+86 -11
+1 -1
config.yaml
··· 1 1 git: 2 - scanPath: /home/icy/code/tmp 2 + scanPath: /home/icy/code/tmp/testrepos 3 3 readme: 4 4 - readme 5 5 - README
+8
git/git.go
··· 52 52 return commits, nil 53 53 } 54 54 55 + func (g *GitRepo) LastCommit() (*object.Commit, error) { 56 + c, err := g.r.CommitObject(g.h) 57 + if err != nil { 58 + return nil, fmt.Errorf("last commit: %w", err) 59 + } 60 + return c, nil 61 + } 62 + 55 63 func (g *GitRepo) FileContent(path string) (string, error) { 56 64 c, err := g.r.CommitObject(g.h) 57 65 if err != nil {
+44 -8
routes/routes.go
··· 4 4 "html/template" 5 5 "log" 6 6 "net/http" 7 + "os" 7 8 "path/filepath" 9 + "time" 8 10 9 11 "github.com/alexedwards/flow" 10 12 "icyphox.sh/legit/config" ··· 16 18 } 17 19 18 20 func (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 + } 19 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 + } 20 59 } 21 60 22 61 func (d *deps) RepoIndex(w http.ResponseWriter, r *http.Request) { 23 62 name := flow.Param(r.Context(), "name") 24 63 name = filepath.Clean(name) 25 - // TODO: remove .git 26 - path := filepath.Join(d.c.Git.ScanPath, name+".git") 64 + path := filepath.Join(d.c.Git.ScanPath, name) 27 65 gr, err := git.Open(path, "") 28 66 if err != nil { 29 67 d.Write404(w) ··· 65 103 ref := flow.Param(r.Context(), "ref") 66 104 67 105 name = filepath.Clean(name) 68 - // TODO: remove .git 69 - path := filepath.Join(d.c.Git.ScanPath, name+".git") 106 + path := filepath.Join(d.c.Git.ScanPath, name) 70 107 gr, err := git.Open(path, ref) 71 108 if err != nil { 72 109 d.Write404(w) ··· 95 132 ref := flow.Param(r.Context(), "ref") 96 133 97 134 name = filepath.Clean(name) 98 - // TODO: remove .git 99 - path := filepath.Join(d.c.Git.ScanPath, name+".git") 135 + path := filepath.Join(d.c.Git.ScanPath, name) 100 136 gr, err := git.Open(path, ref) 101 137 if err != nil { 102 138 d.Write404(w) ··· 116 152 name := flow.Param(r.Context(), "name") 117 153 ref := flow.Param(r.Context(), "ref") 118 154 119 - path := filepath.Join(d.c.Git.ScanPath, name+".git") 155 + path := filepath.Join(d.c.Git.ScanPath, name) 120 156 gr, err := git.Open(path, ref) 121 157 if err != nil { 122 158 d.Write404(w) ··· 149 185 name := flow.Param(r.Context(), "name") 150 186 ref := flow.Param(r.Context(), "ref") 151 187 152 - path := filepath.Join(d.c.Git.ScanPath, name+".git") 188 + path := filepath.Join(d.c.Git.ScanPath, name) 153 189 gr, err := git.Open(path, ref) 154 190 if err != nil { 155 191 d.Write404(w)
+1 -1
templates/500.html
··· 1 1 {{ define "500" }} 2 2 <html> 3 3 <title>500</title> 4 - {{ template "header" . }} 4 + {{ template "head" . }} 5 5 <body> 6 6 500 &mdash; something broke! 7 7 </body>
+27
templates/index.html
··· 1 + {{ define "index" }} 2 + <html> 3 + {{ template "head" . }} 4 + 5 + <header> 6 + <h1>{{ .meta.Title }}</h1> 7 + <h2>{{ .meta.Description }}</h2> 8 + </header> 9 + <body> 10 + {{ template "nav" . }} 11 + <main> 12 + <table> 13 + <tr> 14 + <td>repository</td> 15 + <td>last active</td> 16 + </tr> 17 + {{ range $repo, $lc := .info }} 18 + <tr> 19 + <td><a href="/{{ $repo }}">{{ $repo }}</a></td> 20 + <td>{{ $lc }}</td> 21 + </tr> 22 + {{ end }} 23 + </table> 24 + </main> 25 + </body> 26 + </html> 27 + {{ end }}
+4
templates/nav.html
··· 2 2 <nav> 3 3 <ul> 4 4 <li><a href="/">all repos</a> 5 + {{ if .name }} 5 6 <li><a href="/{{ .name }}">{{ .name }}</a> 7 + {{ end }} 8 + {{ if .ref }} 6 9 <li><a href="/{{ .name }}/tree/{{ .ref }}/">tree</a> 7 10 <li><a href="/{{ .name }}/log/{{ .ref }}">log</a> 11 + {{ end }} 8 12 </ul> 9 13 </nav> 10 14 {{ end }}
+1 -1
templates/repo.html
··· 37 37 {{ if $parent }} 38 38 <a href="/{{ $repo }}/tree/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}/</a> 39 39 {{ else }} 40 - <a href="{{ $repo }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a> 40 + <a href="/{{ $repo }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a> 41 41 {{ end }} 42 42 </td> 43 43 </tr>