Files

107 lines
2.2 KiB
Go

package daemon
import (
"embed"
"html/template"
"log"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"simplegit/state"
)
type indexHandler struct {
store *state.LocalState
reporoot string
sshAddr string
}
type repoClone struct {
Name string
HTTPURL string
SSHURL string
}
//go:embed index.html
var indexFS embed.FS
var indexTmpl = template.Must(template.ParseFS(indexFS, "index.html"))
func (h *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
paths, err := h.listPublicRepos()
if err != nil {
log.Printf("index: list public repos: %v", err)
}
hasSSH := h.sshAddr != ""
scheme := "http"
if r.TLS != nil {
scheme = "https"
}
if p := r.Header.Get("X-Forwarded-Proto"); p != "" {
scheme = p
}
httpBase := scheme + "://" + r.Host
repos := make([]repoClone, 0, len(paths))
for _, p := range paths {
rc := repoClone{Name: p, HTTPURL: httpBase + "/" + p}
if hasSSH {
rc.SSHURL = "ssh://git@" + h.sshAddr + "/" + p
}
repos = append(repos, rc)
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
_ = indexTmpl.Execute(w, struct {
Repos []repoClone
SSH bool
}{Repos: repos, SSH: hasSSH})
}
func (h *indexHandler) listPublicRepos() ([]string, error) {
if eng := h.store.Engine(); eng != nil {
var repos []struct {
state.Repo `xorm:"extends"`
NSName string `xorm:"ns_name"`
}
if err := eng.Table("repo").Select("repo.*, namespace.name AS ns_name").
Join("INNER", "namespace", "namespace.id = repo.namespace_id").Find(&repos); err != nil {
return nil, err
}
out := make([]string, 0, len(repos))
for _, r := range repos {
if r.IsPrivate {
continue
}
out = append(out, r.NSName+"/"+r.Name+".git")
}
sort.Strings(out)
return out, nil
}
return h.scanDiskRepos()
}
func (h *indexHandler) scanDiskRepos() ([]string, error) {
var out []string
err := filepath.WalkDir(h.reporoot, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() || !strings.HasSuffix(d.Name(), ".git") {
return nil
}
rel, err := filepath.Rel(h.reporoot, path)
if err != nil {
return err
}
out = append(out, filepath.ToSlash(rel))
return filepath.SkipDir
})
sort.Strings(out)
return out, err
}