107 lines
2.2 KiB
Go
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
|
|
}
|