package handlers
import (
"fmt"
"html/template"
"net/http"
"path/filepath"
"strings"
"time"
"olexsmir.xyz/mugit/internal/config"
"olexsmir.xyz/mugit/internal/humanize"
"olexsmir.xyz/mugit/web"
)
type handlers struct {
c *config.Config
t *template.Template
}
func InitRoutes(cfg *config.Config) *http.ServeMux {
tmpls := template.Must(template.New("").
Funcs(templateFuncs).
ParseFS(web.TemplatesFS, "*"))
h := handlers{cfg, tmpls}
mux := http.NewServeMux()
mux.HandleFunc("GET /", h.index)
mux.HandleFunc("GET /static/{file}", h.serveStatic)
mux.HandleFunc("GET /{name}", h.multiplex)
mux.HandleFunc("POST /{name}", h.multiplex)
mux.HandleFunc("GET /{name}/{rest...}", h.multiplex)
mux.HandleFunc("POST /{name}/{rest...}", h.multiplex)
mux.HandleFunc("GET /{name}/tree/{ref}/{rest...}", h.repoTree)
mux.HandleFunc("GET /{name}/blob/{ref}/{rest...}", h.fileContents)
mux.HandleFunc("GET /{name}/log/{ref}", h.log)
mux.HandleFunc("GET /{name}/commit/{ref}", h.commit)
mux.HandleFunc("GET /{name}/refs/{$}", h.refs)
return mux
}
// multiplex, check if the request smells like gitprotocol-http(5), if so, it
// passes it to git smart http, otherwise renders templates
func (h *handlers) multiplex(w http.ResponseWriter, r *http.Request) {
if r.URL.RawQuery == "service=git-receive-pack" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("http pushing isn't supported"))
return
}
path := r.PathValue("rest")
if path == "info/refs" && r.Method == "GET" && r.URL.RawQuery == "service=git-upload-pack" {
h.infoRefs(w, r)
} else if path == "git-upload-pack" && r.Method == "POST" {
h.uploadPack(w, r)
} else if r.Method == "GET" {
h.repoIndex(w, r)
}
}
func (h *handlers) serveStatic(w http.ResponseWriter, r *http.Request) {
f := filepath.Clean(r.PathValue("file"))
// TODO: check if files exists
http.ServeFileFS(w, r, web.StaticFS, f)
}
var templateFuncs = template.FuncMap{
"commitSummary": func(v any) string {
s := fmt.Sprint(v)
if i := strings.IndexByte(s, '\n'); i >= 0 {
s = strings.TrimSuffix(s[:i], "\r")
return s + "..."
}
return strings.TrimSuffix(s, "\r")
},
"humanTime": func(t time.Time) string {
return humanize.Time(t)
},
}