10 files changed,
271 insertions(+),
224 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-02-20 21:24:04 +0200
Authored at:
2026-02-20 21:21:37 +0200
Change ID:
quxxpnkrkpsusuonusotlxrzormroouv
Parent:
8fee104
jump to
M
internal/handlers/repo.go
··· 23 23 "olexsmir.xyz/mugit/internal/mdx" 24 24 ) 25 25 26 +type Meta struct { 27 + Title string 28 + Description string 29 + Host string 30 + IsEmpty bool 31 + GoMod bool 32 + SSHEnabled bool 33 +} 34 + 35 +type RepoBase struct { 36 + Ref string 37 + Desc string 38 +} 39 + 40 +type PageData[T any] struct { 41 + Meta Meta 42 + RepoName string // empty for non-repo pages, needed for _head.html to compile 43 + P T 44 +} 45 + 26 46 func (h *handlers) indexHandler(w http.ResponseWriter, r *http.Request) { 27 47 repos, err := h.listPublicRepos() 28 48 if err != nil { 29 49 h.write500(w, err) 30 50 return 31 51 } 52 + h.templ(w, "index", h.pageData(nil, repos)) 53 +} 32 54 33 - data := make(map[string]any) 34 - data["meta"] = h.c.Meta 35 - data["repos"] = repos 36 - data["servername"] = h.c.Meta.Host 37 - h.templ(w, "index", data) 55 +type RepoIndex struct { 56 + Desc string 57 + IsEmpty bool 58 + Readme template.HTML 59 + Ref string 60 + Commits []*git.Commit 61 + IsMirror bool 62 + MirrorURL string 63 + MirrorLastSync time.Time 38 64 } 39 65 40 66 func (h *handlers) repoIndex(w http.ResponseWriter, r *http.Request) { ··· 50 76 return 51 77 } 52 78 53 - data := make(map[string]any) 54 - data["name"] = repo.Name() 55 - data["desc"] = desc 56 - data["servername"] = h.c.Meta.Host 57 - data["meta"] = h.c.Meta 58 - 59 - if repo.IsEmpty() { 60 - data["empty"] = true 61 - h.templ(w, "repo_index", data) 79 + p := RepoIndex{Desc: desc, IsEmpty: repo.IsEmpty()} 80 + if p.IsEmpty { 81 + h.templ(w, "repo_index", h.pageData(repo, p)) 62 82 return 63 83 } 64 84 65 - masterBranch, err := repo.FindMasterBranch(h.c.Repo.Masters) 85 + p.Ref, err = repo.FindMasterBranch(h.c.Repo.Masters) 66 86 if err != nil { 67 87 h.write500(w, err) 68 88 return 69 89 } 70 90 71 - readme, err := h.renderReadme(repo) 91 + p.Readme, err = h.renderReadme(repo) 72 92 if err != nil { 73 93 h.write500(w, err) 74 94 return 75 95 } 76 96 77 - commits, err := repo.Commits() 97 + p.Commits, err = repo.Commits() 78 98 if err != nil { 79 99 h.write500(w, err) 80 100 return 81 101 } 82 102 83 - if len(commits) >= 4 { 84 - commits = commits[:3] 103 + if len(p.Commits) >= 3 { 104 + p.Commits = p.Commits[:3] 85 105 } 86 106 87 - data["ref"] = masterBranch 88 - data["readme"] = readme 89 - data["commits"] = commits 90 - data["gomod"] = repo.IsGoMod() 107 + if isMirror, err := repo.IsMirror(); isMirror && err == nil { 108 + p.IsMirror = true 109 + p.MirrorURL, _ = repo.RemoteURL() 110 + p.MirrorLastSync, _ = repo.LastSync() 111 + } 91 112 92 - if isMirror, err := repo.IsMirror(); err == nil && isMirror { 93 - lastSync, _ := repo.LastSync() 94 - remoteURL, _ := repo.RemoteURL() 95 - data["mirrorinfo"] = map[string]any{ 96 - "isMirror": true, 97 - "url": remoteURL, 98 - "lastSync": lastSync, 99 - } 100 - } 113 + h.templ(w, "repo_index", h.pageData(repo, p)) 114 +} 101 115 102 - h.templ(w, "repo_index", data) 116 +type RepoTree struct { 117 + Desc string 118 + Ref string 119 + Tree []git.NiceTree 120 + ParentPath string 121 + DotDot string 122 + Readme template.HTML 103 123 } 104 124 105 125 func (h *handlers) repoTreeHandler(w http.ResponseWriter, r *http.Request) { ··· 119 139 return 120 140 } 121 141 122 - files, err := repo.FileTree(treePath) 142 + tree, err := repo.FileTree(treePath) 123 143 if err != nil { 124 144 h.write500(w, err) 125 145 return 126 146 } 127 147 128 - data := make(map[string]any) 129 - data["name"] = name 130 - data["ref"] = ref 131 - data["parent"] = treePath 132 - data["dotdot"] = filepath.Dir(treePath) 133 - data["desc"] = desc 134 - data["meta"] = h.c.Meta 135 - data["files"] = files 148 + h.templ(w, "repo_tree", h.pageData(repo, RepoTree{ 149 + Desc: desc, 150 + Ref: ref, 151 + Tree: tree, 152 + ParentPath: treePath, 153 + DotDot: filepath.Dir(treePath), 154 + // TODO: return the readme 155 + Readme: "", 156 + })) 157 +} 136 158 137 - h.templ(w, "repo_tree", data) 159 +type RepoFile struct { 160 + Ref string 161 + Desc string 162 + LineCount []int 163 + Path string 164 + IsImage bool 165 + IsBinary bool 166 + Content string 167 + Mime string 168 + Size int64 138 169 } 139 170 140 171 func (h *handlers) fileContentsHandler(w http.ResponseWriter, r *http.Request) { ··· 150 181 repo, err := h.openPublicRepo(name, ref) 151 182 if err != nil { 152 183 h.write404(w, err) 153 - return 154 - } 155 - 156 - desc, err := repo.Description() 157 - if err != nil { 158 - h.write500(w, err) 159 184 return 160 185 } 161 186 ··· 176 201 return 177 202 } 178 203 179 - if fc.IsImage() || fc.IsBinary { 180 - data := make(map[string]any) 181 - data["name"] = name 182 - data["ref"] = ref 183 - data["desc"] = desc 184 - data["path"] = treePath 185 - data["is_image"] = fc.IsImage() 186 - data["is_binary"] = fc.IsBinary 187 - data["mime_type"] = fc.Mime 188 - data["size"] = fc.Size 189 - data["meta"] = h.c.Meta 190 - h.templ(w, "repo_file", data) 191 - return 204 + p := RepoFile{ 205 + Ref: ref, 206 + Path: treePath, 207 + IsImage: fc.IsImage(), 208 + IsBinary: fc.IsBinary, 209 + Mime: fc.Mime, 210 + Size: fc.Size, 192 211 } 193 212 194 - data := make(map[string]any) 195 - data["name"] = name 196 - data["ref"] = ref 197 - data["desc"] = desc 198 - data["path"] = treePath 199 - 200 - contentStr := fc.String() 201 - lc, err := countLines(strings.NewReader(contentStr)) 213 + p.Desc, err = repo.Description() 202 214 if err != nil { 203 - slog.Error("failed to count line numbers", "err", err) 215 + h.write500(w, err) 216 + return 204 217 } 205 218 206 - lines := make([]int, lc) 207 - if lc > 0 { 219 + if !fc.IsImage() && !fc.IsBinary { 220 + contentStr := fc.String() 221 + lc, err := countLines(strings.NewReader(contentStr)) 222 + if err != nil { 223 + slog.Error("failed to count line numbers", "err", err) 224 + } 225 + lines := make([]int, lc) 208 226 for i := range lines { 209 227 lines[i] = i + 1 210 228 } 229 + p.Content = contentStr 230 + p.LineCount = lines 211 231 } 212 232 213 - data["linecount"] = lines 214 - data["content"] = contentStr 215 - data["meta"] = h.c.Meta 233 + h.templ(w, "repo_file", h.pageData(repo, p)) 234 +} 216 235 217 - h.templ(w, "repo_file", data) 236 +type RepoLog struct { 237 + Desc string 238 + Commits []*git.Commit 239 + Ref string 218 240 } 219 241 220 242 func (h *handlers) logHandler(w http.ResponseWriter, r *http.Request) { ··· 239 261 return 240 262 } 241 263 242 - data := make(map[string]any) 243 - data["name"] = name 244 - data["ref"] = ref 245 - data["desc"] = desc 246 - data["meta"] = h.c.Meta 247 - data["log"] = true 248 - data["commits"] = commits 249 - h.templ(w, "repo_log", data) 264 + h.templ(w, "repo_log", h.pageData(repo, RepoLog{ 265 + Desc: desc, 266 + Commits: commits, 267 + Ref: ref, 268 + })) 269 +} 270 + 271 +type RepoCommit struct { 272 + Diff *git.NiceDiff 273 + Ref string 274 + Desc string 250 275 } 251 276 252 277 func (h *handlers) commitHandler(w http.ResponseWriter, r *http.Request) { ··· 270 295 return 271 296 } 272 297 273 - data := make(map[string]any) 274 - data["diff"] = diff.Diff 275 - data["commit"] = diff.Commit 276 - data["parents"] = diff.Parents 277 - data["stat"] = diff.Stat 278 - data["name"] = name 279 - data["ref"] = ref 280 - data["desc"] = desc 281 - h.templ(w, "repo_commit", data) 298 + h.templ(w, "repo_commit", h.pageData(repo, RepoCommit{ 299 + Desc: desc, 300 + Ref: ref, 301 + Diff: diff, 302 + })) 303 +} 304 + 305 +type RepoRefs struct { 306 + Desc string 307 + Ref string 308 + Branches []*git.Branch 309 + Tags []*git.TagReference 282 310 } 283 311 284 312 func (h *handlers) refsHandler(w http.ResponseWriter, r *http.Request) { ··· 294 322 return 295 323 } 296 324 297 - masterBranch, err := repo.FindMasterBranch(h.c.Repo.Masters) 325 + master, err := repo.FindMasterBranch(h.c.Repo.Masters) 298 326 if err != nil { 299 327 h.write500(w, err) 300 328 return ··· 306 334 return 307 335 } 308 336 309 - tags, err := repo.Tags() 310 - if err != nil { 311 - // repo should have at least one branch, tags are *optional* 312 - slog.Error("couldn't fetch repo tags", "err", err) 313 - } 337 + // repo should have at least one branch, tags are *optional* 338 + tags, _ := repo.Tags() 314 339 315 - data := make(map[string]any) 316 - data["meta"] = h.c.Meta 317 - data["name"] = repo.Name() 318 - data["desc"] = desc 319 - data["ref"] = masterBranch 320 - data["branches"] = branches 321 - data["tags"] = tags 322 - h.templ(w, "repo_refs", data) 340 + h.templ(w, "repo_refs", h.pageData(repo, RepoRefs{ 341 + Desc: desc, 342 + Ref: master, 343 + Tags: tags, 344 + Branches: branches, 345 + })) 323 346 } 324 347 325 348 func countLines(r io.Reader) (int, error) { ··· 452 475 h.readmeCache.Set(name, readmeContents) 453 476 return readmeContents, nil 454 477 } 478 + 479 +func (h handlers) pageData(repo *git.Repo, p any) PageData[any] { 480 + var name string 481 + var gomod, empty bool 482 + if repo != nil { 483 + gomod = repo.IsGoMod() 484 + empty = repo.IsEmpty() 485 + name = repo.Name() 486 + } 487 + 488 + return PageData[any]{ 489 + P: p, 490 + RepoName: name, 491 + Meta: Meta{ 492 + Title: h.c.Meta.Title, 493 + Description: h.c.Meta.Description, 494 + Host: h.c.Meta.Host, 495 + GoMod: gomod, 496 + SSHEnabled: h.c.SSH.Enable, 497 + IsEmpty: empty, 498 + }, 499 + } 500 +}
M
web/templates/_head.html
··· 3 3 <meta name="viewport" content="width=device-width, initial-scale=1"> 4 4 <link rel="stylesheet" href="/static/style.css" type="text/css"> 5 5 <link rel="icon" href="/static/favicon.svg"> 6 - {{ if and .servername .gomod }} 7 - <meta name="go-import" content="{{ .servername}}/{{ .name }} git https://{{ .servername }}/{{ .name }}"> 8 - {{ end }} 9 - {{ if and .servername .name }} 10 - <link rel="alternate" type="application/rss" href="https://{{ .servername }}/{{ .name }}/feed"> 6 + 7 + {{ if .Meta.GoMod }} 8 + <meta name="go-import" content="{{.Meta.Host}}/{{.RepoName}} git https://{{.Meta.Host}}/{{.RepoName}}"> 11 9 {{ end }} 12 - {{ if .servername }} 13 - <link rel="alternate" type="application/rss" href="https://{{ .servername }}/index.xml"> 10 + 11 + <link ref="alternate" type="application/rss" href="https://{{.Meta.Host}}/index.xml"> 12 + {{ if .RepoName }} 13 + <link ref="alternate" type="application/rss" href="https://{{.Meta.Host}}/{{.RepoName}}/feed"> 14 14 {{ end }} 15 15 {{ end }}
M
web/templates/_repo_header.html
··· 4 4 <a href="/">all repos</a> 5 5 </div> 6 6 <h1 class="repo-name"> 7 - {{ .name }} 8 - {{- if .ref }} 9 - <span class="ref">@ {{ .ref }}</span> 7 + {{ .RepoName }} 8 + {{- if .P.Ref }} 9 + <span class="ref">@ {{ .P.Ref }}</span> 10 10 {{- end }} 11 11 </h1> 12 - {{- if .desc }} 13 - <div class="desc muted">{{ .desc }}</div> 12 + {{- if .P.Desc }} 13 + <div class="desc muted">{{ .P.Desc }}</div> 14 14 {{- end }} 15 15 16 - {{- if not .empty }} 16 + {{- if not .Meta.IsEmpty }} 17 17 <nav class="repo-nav"> 18 18 <ul> 19 - <li><a href="/{{ .name }}">summary</a></li> 20 - <li><a href="/{{ .name }}/refs">refs</a></li> 21 - <li><a href="/{{ .name }}/tree/{{ .ref }}/">tree</a></li> 22 - <li><a href="/{{ .name }}/log/{{ .ref }}">log</a></li> 19 + <li><a href="/{{ .RepoName }}">summary</a></li> 20 + <li><a href="/{{ .RepoName }}/refs">refs</a></li> 21 + <li><a href="/{{ .RepoName }}/tree/{{ .P.Ref }}/">tree</a></li> 22 + <li><a href="/{{ .RepoName }}/log/{{ .P.Ref }}">log</a></li> 23 23 </ul> 24 24 </nav> 25 25 {{- end }}
M
web/templates/index.html
··· 3 3 <html> 4 4 <head> 5 5 {{ template "head" . }} 6 - <title>{{ .meta.Title }}</title> 6 + <title>{{ .Meta.Title }}</title> 7 7 </head> 8 8 <body> 9 9 <header> 10 - <h1>{{ .meta.Title }}</h1> 11 - {{ if .meta.Description }}<h2>{{ .meta.Description }}</h2>{{ end }} 10 + <h1>{{ .Meta.Title }}</h1> 11 + {{ if .Meta.Description }}<h2>{{ .Meta.Description }}</h2>{{ end }} 12 12 </header> 13 13 <main> 14 14 <table class="table index"> ··· 20 20 </tr> 21 21 </thead> 22 22 <tbody> 23 - {{- range .repos }} 23 + {{- range .P }} 24 24 <tr> 25 25 <td class="nowrap"><a href="/{{ .Name }}">{{ .Name }}</a></td> 26 26 <td class="fill">
M
web/templates/repo_commit.html
··· 1 1 {{ define "repo_commit" }} 2 +{{ $commit := .P.Diff.Commit }} 3 +{{ $diff := .P.Diff.Diff }} 4 +{{ $stat := .P.Diff.Stat }} 5 +{{ $parents := .P.Diff.Parents }} 2 6 <html> 3 7 <head> 4 8 {{ template "head" . }} 5 - <title>{{ .name }}: {{ .commit.HashShort }}</title> 9 + <title>{{ .RepoName }}: {{ $commit.HashShort }}</title> 6 10 </head> 7 11 <body> 8 12 {{ template "repo_header" . }} 9 13 <main> 10 14 <section class="commit"> 11 15 <div class="commit-refs"> 12 - {{ .stat.FilesChanged }} files changed, 13 - {{ .stat.Insertions }} insertions(+), 14 - {{ .stat.Deletions }} deletions(-) 16 + {{ $stat.FilesChanged }} files changed, 17 + {{ $stat.Insertions }} insertions(+), 18 + {{ $stat.Deletions }} deletions(-) 15 19 </div> 16 20 17 21 <div class="box"> 18 22 <pre class="commit-message"> 19 - {{- if .commit.Message }}{{- .commit.Message -}} 23 + {{- if $commit.Message }}{{- $commit.Message -}} 20 24 {{- else -}}<span class="muted">Empty message</span>{{- end -}} 21 25 </pre> 22 26 <div> 23 27 <strong>Author:</strong> 24 - {{ .commit.AuthorName }} 25 - <a href="mailto:{{ .AuthorEmail }}" class="commit-email">{{ .commit.AuthorEmail }}</a> 28 + {{ $commit.AuthorName }} 29 + <a href="mailto:{{ $commit.AuthorEmail }}" class="commit-email">{{ $commit.AuthorEmail }}</a> 26 30 </div> 27 31 <div> 28 32 <strong>Committed at:</strong> 29 - {{ .commit.Committed }} 33 + {{ $commit.Committed }} 30 34 </div> 31 - {{ if .commit.ChangeID -}} 35 + {{ if $commit.ChangeID -}} 32 36 <div> 33 37 <strong>Change ID:</strong> 34 - {{ .commit.ChangeID }} 38 + {{ $commit.ChangeID }} 35 39 </div> 36 40 {{- end }} 37 41 <div> 38 42 <strong>Parent:</strong> 39 - {{ range $i, $p := .parents -}} 43 + {{ range $i, $p := $parents -}} 40 44 {{ if $i }}, {{ end -}} 41 - <a class="link" href="/{{ $.name }}/commit/{{ $p }}">{{ $p }}</a> 45 + <a class="link" href="/{{$.RepoName}}/commit/{{ $p }}">{{ $p }}</a> 42 46 {{- end }} 43 47 </div> 44 48 </div> 45 49 46 - {{ if gt (len .diff) 1 -}} 50 + {{ if gt (len $diff) 1 -}} 47 51 <div class="jump"> 48 52 <strong>jump to</strong> 49 53 <table class="table jump-table"> 50 54 <tbody> 51 - {{ range .diff }} 55 + {{ range $diff }} 52 56 {{ $path := .Name.New }} 53 57 {{ if not $path }}{{ $path = .Name.Old }}{{ end }} 54 58 <tr> ··· 70 74 {{ end }} 71 75 </section> 72 76 <section> 73 - {{ $repo := .name }} 74 - {{ $this := .commit.Hash }} 75 - {{ $parent := index .parents 0 }} 76 - {{ range .diff }} 77 + {{ $this := $commit.Hash }} 78 + {{ $parent := index $parents 0 }} 79 + {{ range $diff }} 77 80 {{ $path := .Name.New }} 78 81 {{ if not $path }}{{ $path = .Name.Old }}{{ end }} 79 82 <div id="{{ $path }}"> ··· 88 91 <span class="diff-type diff-mod">M</span> 89 92 {{ end }} 90 93 {{ if .Name.Old }} 91 - <a href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}">{{ .Name.Old }}</a> 94 + <a href="/{{$.RepoName}}/blob/{{ $parent }}/{{ .Name.Old }}">{{ .Name.Old }}</a> 92 95 {{ if .Name.New }} 93 96 → 94 - <a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 97 + <a href="/{{$.RepoName}}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 95 98 {{ end }} 96 99 {{ else }} 97 - <a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 100 + <a href="/{{$.RepoName}}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a> 98 101 {{- end -}} 99 102 {{ if .IsBinary }} 100 103 <p>Not showing binary file.</p>
M
web/templates/repo_file.html
··· 2 2 <html> 3 3 <head> 4 4 {{ template "head" . }} 5 - <title>{{ .name }}: {{ .path }} ({{ .ref }})</title> 5 + <title>{{ .RepoName }}: {{ .P.Path }} ({{ .P.Ref }})</title> 6 6 </head> 7 7 <body> 8 8 {{ template "repo_header" . }} 9 9 <main> 10 - <p>{{ .path }} (<a class="muted" href="?raw=true">view raw</a>)</p> 10 + <p>{{ .P.Path }} (<a class="muted" href="?raw=true">view raw</a>)</p> 11 11 <div class="file-wrapper"> 12 - {{ if .is_image }} 12 + {{ if .P.IsImage }} 13 13 <div class="image-viewer"> 14 - <p>{{.mime_type}} • {{.size}} bytes</p> 15 - <img src="?raw=true" alt="{{- .path -}}"> 14 + <p>{{ .P.Mime }} • {{ .P.Size }} bytes</p> 15 + <img src="?raw=true" alt="{{- .P.Path -}}"> 16 16 </div> 17 - {{ else if .is_binary }} 17 + {{ else if .P.IsBinary }} 18 18 <div class="binary-viewer"> 19 - <p>Binary file ({{.mime_type}})</p> 20 - <p>Size: {{.size}} bytes</p> 19 + <p>Binary file ({{ .P.Mime }})</p> 20 + <p>Size: {{ .P.Size }} bytes</p> 21 21 <a class="link" href="?raw=true" download>[ Download ]</a> 22 22 </div> 23 23 {{ else }} 24 24 <table> 25 - <tbody><tr> 26 - <td class="line-numbers"> 27 - <pre>{{- range .linecount }} 25 + <tbody> 26 + <tr> 27 + <td class="line-numbers"> 28 +<pre>{{- range .P.LineCount }} 28 29 <a id="L{{ . }}" href="#L{{ . }}">{{ . }}</a> 29 30 {{- end -}}</pre> 30 - </td> 31 - <td class="file-content"> 32 - <pre>{{- .content -}}</pre> 33 - </td> 34 - </tbody></tr> 31 + </td> 32 + <td class="file-content"> 33 + <pre>{{- .P.Content -}}</pre> 34 + </td> 35 + </tr> 36 + </tbody> 35 37 </table> 36 38 {{ end }} 37 39 </div>
M
web/templates/repo_index.html
··· 3 3 <html> 4 4 <head> 5 5 {{ template "head" . }} 6 - <title>{{ .name }} — {{ .meta.Title }}</title> 6 + <title>{{ .RepoName}} — {{ .Meta.Title }}</title> 7 7 </head> 8 8 <body> 9 9 {{ template "repo_header" . }} 10 10 <main> 11 - {{ $repo := .name }} 12 - {{ if .empty }} 11 + {{ if .P.IsEmpty }} 13 12 <h3>Repository is empty</h3> 14 13 {{ else }} 15 14 <section class="repo-index"> 16 15 <div class="repo-index-main"> 17 - {{ range .commits }} 16 + {{ $repo := .RepoName }} 17 + {{ range .P.Commits }} 18 18 <div class="box"> 19 19 <div> 20 20 <a href="/{{ $repo }}/commit/{{ .Hash }}" class="commit-hash link">{{ .HashShort }}</a> ··· 34 34 35 35 <div class="repo-index-side"> 36 36 <h2>Clone urls</h2> 37 - <pre>{{- /* */ -}} 38 -https://{{ .servername }}/{{ .name }} 39 -git@{{ .servername }}:{{ .name }} 40 -{{- /* */ -}}</pre> 41 - 42 - {{- if .mirrorinfo.isMirror }} 37 + <pre>https://{{.Meta.Host}}/{{.RepoName}}</pre> 38 + {{ if .Meta.SSHEnabled }}<pre>git@{{.Meta.Host}}:{{.RepoName}}</pre>{{end}} 39 + {{- if .P.IsMirror -}} 43 40 <br> 44 - <h2>Mirror Status</h3> 45 - <p> 46 - Last updated {{ humanizeTime .mirrorinfo.lastSync }} from: 47 - <a href="{{ .mirrorinfo.url }}" target="_blank">{{ .mirrorinfo.url }}</a> 48 - </p> 49 - {{- end }} 41 + <h2>Mirror status</h2> 42 + <p> 43 + Last updated {{ humanizeTime .P.MirrorLastSync }} from: 44 + <a href="{{.P.MirrorURL}}" target="_blank">{{.P.MirrorURL}}</a> 45 + </p> 46 + {{- end}} 50 47 </div> 51 48 </section> 52 49 {{ end }} 53 50 54 - {{- if .readme }} 55 - <article class="readme"> 56 - {{- .readme -}} 57 - </article> 51 + {{- if .P.Readme }} 52 + <article class="readme">{{- .P.Readme -}}</article> 58 53 {{- end -}} 59 54 </main> 60 55 </body>
M
web/templates/repo_log.html
··· 1 1 {{ define "repo_log" }} 2 +{{ $repo := .RepoName }} 2 3 <html> 3 4 <head> 4 5 {{ template "head" . }} 5 - <title>{{ .name }}: log</title> 6 + <title>{{ $repo }}: log</title> 6 7 </head> 7 8 <body> 8 9 {{ template "repo_header" . }} 9 10 <main> 10 - {{ $repo := .name }} 11 11 <table class="table log"> 12 12 <thead> 13 13 <tr class="nohover"> ··· 18 18 </tr> 19 19 </thead> 20 20 <tbody> 21 - {{ range .commits }} 21 + {{ range .P.Commits }} 22 22 <tr> 23 23 <td class="fill"> 24 24 <a href="/{{ $repo }}/commit/{{ .Hash }}"> 25 25 {{- if .Message }}{{- commitSummary .Message -}} 26 26 {{- else -}}<span class="muted">Empty message</span>{{- end -}} 27 - </a> 27 + </a> 28 28 </td> 29 29 <td class="author nowrap"> 30 30 <span class="author-short">
M
web/templates/repo_refs.html
··· 1 1 {{ define "repo_refs" }} 2 +{{ $repo := .RepoName }} 2 3 <html> 3 4 <head> 4 5 {{ template "head" . }} 5 - <title>{{ .name }}: refs</title> 6 + <title>{{ $repo }}: refs</title> 6 7 </head> 7 8 <body> 8 9 {{ template "repo_header" . }} 9 10 <main> 10 - {{ $name := .name }} 11 11 <h3>branches</h3> 12 12 <div class="refs"> 13 - {{ range .branches }} 13 + {{ range .P.Branches }} 14 14 <div> 15 - <strong>{{ .Name }}</strong> 16 - <a class="link" href="/{{ $name }}/tree/{{ .Name }}/">browse</a> 17 - <a class="link" href="/{{ $name }}/log/{{ .Name }}">log</a> 18 - <a class="link" href="/{{ $name }}/archive/{{ .Name }}">tar.gz</a> 15 + <strong>{{ .Name }}</strong> 16 + <a class="link" href="/{{ $repo }}/tree/{{ .Name }}/">browse</a> 17 + <a class="link" href="/{{ $repo }}/log/{{ .Name }}">log</a> 18 + <a class="link" href="/{{ $repo }}/archive/{{ .Name }}">tar.gz</a> 19 19 </div> 20 - {{ end }} 20 + {{ end }} 21 21 </div> 22 - {{ if .tags }} 22 + {{ if .P.Tags }} 23 23 <h3>tags</h3> 24 24 <div class="refs"> 25 - {{ range .tags }} 26 - <div> 27 - <strong>{{ .Name }}</strong> 28 - <a class="link" href="/{{ $name }}/tree/{{ .Name }}/">browse</a> 29 - <a class="link" href="/{{ $name }}/log/{{ .Name }}">log</a> 30 - <a class="link" href="/{{ $name }}/archive/{{ .Name }}">tar.gz</a> 31 - {{ if .Message }} 32 - <pre>{{ .Message }}</pre> 33 - </div> 34 - {{ end }} 35 - {{ end }} 25 + {{ range .P.Tags }} 26 + <div> 27 + <strong>{{ .Name }}</strong> 28 + <a class="link" href="/{{ $repo }}/tree/{{ .Name }}/">browse</a> 29 + <a class="link" href="/{{ $repo }}/log/{{ .Name }}">log</a> 30 + <a class="link" href="/{{ $repo }}/archive/{{ .Name }}">tar.gz</a> 31 + {{ if .Message }} 32 + <details> 33 + <summary>message</summary> 34 + <pre>{{ .Message }}</pre> 35 + </details> 36 + {{ end }} 37 + </div> 38 + {{ end }} 36 39 </div> 37 40 {{ end }} 38 41 </main>
M
web/templates/repo_tree.html
··· 1 1 {{ define "repo_tree" }} 2 +{{ $name := .RepoName }} 3 +{{ $ref := .P.Ref }} 2 4 <html> 3 5 <head> 4 6 {{ template "head" . }} 5 - <title>{{ .name }}: tree ({{ .ref }})</title> 7 + <title>{{ $name }}: tree ({{ $ref }})</title> 6 8 </head> 7 9 <body> 8 10 {{ template "repo_header" . }} 9 11 <main> 10 - {{ $repo := .name }} 11 - {{ $ref := .ref }} 12 - {{ $parent := .parent }} 12 + {{ $parent := .P.ParentPath }} 13 13 14 14 <table class="table tree"> 15 15 <thead> ··· 24 24 <tr> 25 25 <td class="mode nowrap"></td> 26 26 <td class="size nowrap"></td> 27 - <td class="fill"><a href="/{{ $repo }}/tree/{{ $ref }}/{{ .dotdot }}">..</a></td> 27 + <td class="fill"><a href="/{{ $name }}/tree/{{ $ref }}/{{ .P.DotDot }}">..</a></td> 28 28 </tr> 29 29 {{ end }} 30 30 31 - {{ range .files }} 31 + {{ range .P.Tree }} 32 32 {{ if not .IsFile }} 33 33 <tr> 34 34 <td class="mode nowrap">{{ .Mode }}</td> 35 35 <td class="size nowrap">{{ .Size }}</td> 36 36 <td class="fill"> 37 37 {{ if $parent }} 38 - <a href="/{{ $repo }}/tree/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}/</a> 38 + <a href="/{{ $name}}/tree/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}/</a> 39 39 {{ else }} 40 - <a href="/{{ $repo }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a> 40 + <a href="/{{ $name }}/tree/{{ $ref }}/{{ .Name }}">{{ .Name }}/</a> 41 41 {{ end }} 42 42 </td> 43 43 </tr> 44 44 {{ end }} 45 45 {{ end }} 46 46 47 - {{ range .files }} 47 + {{ range .P.Tree }} 48 48 {{ if .IsFile }} 49 49 <tr> 50 50 <td class="mode nowrap">{{ .Mode }}</td> 51 51 <td class="size nowrap">{{ .Size }}</td> 52 52 <td class="fill"> 53 53 {{ if $parent }} 54 - <a href="/{{ $repo }}/blob/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}</a> 54 + <a href="/{{ $name }}/blob/{{ $ref }}/{{ $parent }}/{{ .Name }}">{{ .Name }}</a> 55 55 {{ else }} 56 - <a href="/{{ $repo }}/blob/{{ $ref }}/{{ .Name }}">{{ .Name }}</a> 56 + <a href="/{{ $name }}/blob/{{ $ref }}/{{ .Name }}">{{ .Name }}</a> 57 57 {{ end }} 58 58 </td> 59 59 </tr> ··· 63 63 </table> 64 64 65 65 <article> 66 - <pre> 67 - {{- if .readme }}{{ .readme }}{{- end -}} 68 - </pre> 66 + <pre>{{- if .P.Readme }}{{ .P.Readme }}{{- end -}}</pre> 69 67 </article> 70 68 </main> 71 69 </body>