Lindenii Project Forge
Commit info | |
---|---|
ID | 7c008d4f16acaeb826f82d402772288f729e6e54 |
Author | Runxi Yu<me@runxiyu.org> |
Author date | Wed, 12 Feb 2025 20:47:33 +0800 |
Committer | Runxi Yu<me@runxiyu.org> |
Committer date | Wed, 12 Feb 2025 20:47:33 +0800 |
Actions | Get patch |
repo_index: Add clone instructions
package main import ( "net/http"
"net/url"
) func handle_repo_index(w http.ResponseWriter, r *http.Request, params map[string]string) { data := make(map[string]any) group_name, repo_name := params["group_name"], params["repo_name"] data["group_name"], data["repo_name"] = group_name, repo_name repo, err := open_git_repo(r.Context(), group_name, repo_name) if err != nil { _, _ = w.Write([]byte("Error opening repo: " + err.Error())) return } head, err := repo.Head() if err != nil { _, _ = w.Write([]byte("Error getting repo HEAD: " + err.Error())) return } data["ref"] = head.Name().Short() head_hash := head.Hash() recent_commits, err := get_recent_commits(repo, head_hash, 3) if err != nil { _, _ = w.Write([]byte("Error getting recent commits: " + err.Error())) return } data["commits"] = recent_commits commit_object, err := repo.CommitObject(head_hash) if err != nil { _, _ = w.Write([]byte("Error getting commit object: " + err.Error())) return } tree, err := commit_object.Tree() if err != nil { _, _ = w.Write([]byte("Error getting file tree: " + err.Error())) return } data["readme_filename"], data["readme"] = render_readme_at_tree(tree) data["files"] = build_display_git_tree(tree)
data["clone_url"] = "ssh://" + r.Host + "/" + url.PathEscape(params["group_name"]) + "/:/repos/" + url.PathEscape(params["repo_name"])
err = templates.ExecuteTemplate(w, "repo_index", data) if err != nil { _, _ = w.Write([]byte("Error rendering template: " + err.Error())) return } }
html { font-family: sans-serif; background-color: var(--background-color); color: var(--text-color); --background-color: hsl(0, 0%, 100%); --text-color: hsl(0, 0%, 0%); --link-color: hsl(320, 50%, 36%); --light-text-color: hsl(0, 0%, 45%); --darker-border-color: hsl(0, 0%, 72%); --lighter-border-color: hsl(0, 0%, 85%); --text-decoration-color: hsl(0, 0%, 72%); --darker-box-background-color: hsl(0, 0%, 92%); --lighter-box-background-color: hsl(0, 0%, 95%); } @media (prefers-color-scheme: dark) { html { --background-color: hsl(0, 0%, 0%); --text-color: hsl(0, 0%, 100%); --link-color: hsl(320, 50%, 76%); --light-text-color: hsl(0, 0%, 78%); --darker-border-color: hsl(0, 0%, 35%); --lighter-border-color: hsl(0, 0%, 25%); --text-decoration-color: hsl(0, 0%, 30%); --darker-box-background-color: hsl(0, 0%, 20%); --lighter-box-background-color: hsl(0, 0%, 15%); } } html, code, pre { font-size: 1rem; /* TODO: Not always correct */ } footer { margin-top: 1rem; margin-left: auto; margin-right: auto; display: block; padding: 0 5px; width: fit-content; text-align: center; color: var(--light-text-color); } footer a:link, footer a:visited { color: inherit; } .padding-wrapper { margin: 1rem auto; max-width: 60rem; padding: 0 5px; } a:link, a:visited { text-decoration-color: var(--text-decoration-color); color: var(--link-color); }
code:not(pre > code) {
#readme code:not(pre > code) {
background-color: var(--lighter-box-background-color); border-radius: 2px; padding: 2px; } table { border: var(--lighter-border-color) solid 1px; border-spacing: 0px; border-collapse: collapse; } table.wide { width: 100%; } td, th { padding: 3px 5px; border: var(--lighter-border-color) solid 1px; } th { background-color: var(--lighter-box-background-color); } th[scope=row] { text-align: left; } tr.title-row > th { background-color: var(--darker-box-background-color); } td > pre { margin: 0; } td#readme > *:last-child { margin-bottom: 0; } td#readme > *:first-child { margin-top: 0; } .commit-id { font-family: monospace; } .scroll { overflow-x: auto; } .toggle-table-off, .toggle-table-on { display: none; } .toggle-table-off + table > thead > tr > th, .toggle-table-on + table > thead > tr > th { padding: 0; } .toggle-table-off + table > thead > tr > th > label, .toggle-table-on + table > thead > tr > th > label { width: 100%; display: inline-block; padding: 3px 0; cursor: pointer; } .toggle-table-off:checked + table > tbody { display: none; } .toggle-table-on + table > tbody { display: none; } .toggle-table-on:checked + table > tbody { display: table-row-group; } .chunk-unchanged { color: grey; } .chunk-addition { color: green; } @media (prefers-color-scheme: dark) { .chunk-addition { color: lime; } } .chunk-deletion { color: red; } .chunk-unknown { color: yellow; } pre.chunk { margin-top: 0; margin-bottom: 0; } .toggle-on-wrapper { border: var(--lighter-border-color) solid 1px; } .toggle-on-toggle { display: none; } .toggle-on-header { cursor: pointer; display: block; width: 100%; background-color: var(--lighter-box-background-color); } .toggle-on-header > span { padding: 3px 5px; display: inline-block; } .toggle-on-content { display: none; } .toggle-on-toggle:checked + .toggle-on-header + .toggle-on-content { display: block; } .file-patch + .file-patch { margin-top: 0.5rem; } .file-content { padding: 3px 5px; } .file-header { font-family: monospace; }
{{- define "repo_index" -}} <!DOCTYPE html> <html lang="en"> <head> {{ template "head_common" . }} <title>{{ .group_name }}/repos/{{ .repo_name }} – Lindenii Forge</title> </head> <body class="repo-index"> <header> {{ template "repo_header" . }} </header>
<div class="padding-wrapper"> <table id="repo-info-table"> <thead> <tr class="title-row"> <th colspan="2">Repo Info</th> </tr> </thead> <tbody> <tr> <th scope="row">Clone</th> <td><code>git clone {{ .clone_url }}</code></td> </tr> </tbody> </table> </div>
<div class="padding-wrapper scroll"> <input id="toggle-table-recent-commits" type="checkbox" class="toggle-table-off" /> <table id="recent-commits" class="wide"> <thead> <tr class="title-row"> <th colspan="3"><label for="toggle-table-recent-commits">Recent Commits (<a href="log/{{ .ref }}/">see all</a>)</label></th> </tr> </thead> <tbody> {{- range .commits }} <tr> <td class="commit-title"><a href="commit/{{ .ID }}">{{ .Message | first_line }}</a></td> <td class="commit-author"> <a class="email-name" href="mailto:{{ .Author.Email }}">{{ .Author.Name }}</a> </td> <td class="commit-time"> {{ .Author.When.Format "2006-01-02 15:04:05 -0700" }} </td> </tr> {{- end }} </tbody> </table> </div> <div class="padding-wrapper scroll"> <input id="toggle-table-file-tree" type="checkbox" class="toggle-table-off" /> <table id="file-tree" class="wide"> <thead> <tr class="title-row"> <th colspan="3"><label for="toggle-table-file-tree">/ on {{ .ref }}</label></th> </tr> </thead> <tbody> {{- $ref := .ref }} {{- range .files }} <tr> <td class="file-mode">{{ .Mode }}</td> <td class="file-name"><a href="tree/{{ .Name }}">{{ .Name }}</a>{{ if not .Is_file }}/{{ end }}</td> <td class="file-size">{{ .Size }}</td> </tr> {{- end }} </tbody> </table> </div> <div class="padding-wrapper"> <div id="refs"> </div> </div> <div class="padding-wrapper"> {{ if .readme }} <input id="toggle-table-readme" type="checkbox" class="toggle-table-off" /> <table class="wide"> <thead> <tr class="title-row"> <th><label for="toggle-table-readme">{{ .readme_filename }}</label></th> </tr> </thead> <tbody> <tr> <td id="readme"> {{ .readme -}} </td> </tr> </tbody> </table> {{ end }} </div> <footer> {{ template "footer" . }} </footer> </body> </html> {{- end -}}