use gitweb/gitolite directory layout (including subdirs)
1 file changed, 77 insertions(+), 22 deletions(-)
changed files
M routes/handler.go → routes/handler.go
@@ -3,14 +3,26 @@ import ( "log" "net/http" + "os" + "path" + "slices" + "strings" + + "github.com/dimfeld/httptreemux/v5" "go.alanpearce.eu/elgit/config" ) // Checks for gitprotocol-http(5) specific smells; if found, passes // the request on to the git http service, else render the web frontend. -func (d *deps) Multiplex(w http.ResponseWriter, r *http.Request) { - path := r.PathValue("rest") +func (d *deps) Multiplex(w http.ResponseWriter, r *http.Request, params map[string]string) { + rest := params["rest"] + switch params["name"] { + case "info", "git-upload-pack": + rest = path.Join(params["name"], params["rest"]) + params["name"] = params["category"] + params["category"] = "" + } if r.URL.RawQuery == "service=git-receive-pack" { w.WriteHeader(http.StatusBadRequest)@@ -25,33 +37,76 @@ return } - if path == "info/refs" && + if rest == "info/refs" && r.URL.RawQuery == "service=git-upload-pack" && r.Method == "GET" { - d.InfoRefs(w, r) - } else if path == "git-upload-pack" && r.Method == "POST" { - d.UploadPack(w, r) + d.InfoRefs(w, r, params) + } else if rest == "git-upload-pack" && r.Method == "POST" { + d.UploadPack(w, r, params) } else if r.Method == "GET" { - d.RepoIndex(w, r) + d.RepoIndex(w, r, params) } } -func Handlers(c *config.Config) *http.ServeMux { - mux := http.NewServeMux() - d := deps{c} +func Handlers(c *config.Config) *httptreemux.TreeMux { + mux := httptreemux.New() + + projects, err := ReadProjectsList(c) + if err != nil { + log.Fatal(err) + } + + d := deps{ + c, + projects, + } + + categories := []string{} + for _, project := range projects { + if cat, _, found := strings.Cut(project, string(os.PathSeparator)); found { + categories = append(categories, cat) + } + } + categories = slices.Compact(categories) + + mux.NotFoundHandler = func(w http.ResponseWriter, r *http.Request) { + d.Write404(w) + } + + mux.RedirectTrailingSlash = false + + mux.GET("/", d.Index) + mux.GET("/static/:file", d.ServeStatic) + + mux.GET("/:name/tree/:ref/*rest", d.RepoTree) + mux.GET("/:name/blob/:ref/*rest", d.FileContent) + mux.GET("/:name/tree/:ref/", d.RepoTree) + mux.GET("/:name/blob/:ref/", d.FileContent) + mux.GET("/:name/log/:ref", d.Log) + mux.GET("/:name/archive/:file", d.Archive) + mux.GET("/:name/commit/:ref", d.Diff) + mux.GET("/:name/refs/", d.Refs) + mux.GET("/:name", d.Multiplex) + mux.POST("/:name", d.Multiplex) + mux.GET("/:name/", d.Multiplex) + mux.POST("/:name/", d.Multiplex) + mux.GET("/:name/*rest", d.Multiplex) + mux.POST("/:name/*rest", d.Multiplex) - mux.HandleFunc("GET /", d.Index) - mux.HandleFunc("GET /static/{file}", d.ServeStatic) - mux.HandleFunc("GET /{name}", d.Multiplex) - mux.HandleFunc("POST /{name}", d.Multiplex) - mux.HandleFunc("GET /{name}/tree/{ref}/{rest...}", d.RepoTree) - mux.HandleFunc("GET /{name}/blob/{ref}/{rest...}", d.FileContent) - mux.HandleFunc("GET /{name}/log/{ref}", d.Log) - mux.HandleFunc("GET /{name}/archive/{file}", d.Archive) - mux.HandleFunc("GET /{name}/commit/{ref}", d.Diff) - mux.HandleFunc("GET /{name}/refs/{$}", d.Refs) - mux.HandleFunc("GET /{name}/{rest...}", d.Multiplex) - mux.HandleFunc("POST /{name}/{rest...}", d.Multiplex) + mux.GET("/:category/:name/tree/:ref/*rest", d.RepoTree) + mux.GET("/:category/:name/blob/:ref/*rest", d.FileContent) + mux.GET("/:category/:name/tree/:ref/", d.RepoTree) + mux.GET("/:category/:name/blob/:ref/", d.FileContent) + mux.GET("/:category/:name/log/:ref", d.Log) + mux.GET("/:category/:name/archive/:file", d.Archive) + mux.GET("/:category/:name/commit/:ref", d.Diff) + mux.GET("/:category/:name/refs/", d.Refs) + mux.GET("/:category/:name", d.Multiplex) + mux.POST("/:category/:name", d.Multiplex) + mux.GET("/:category/:name/", d.Multiplex) + mux.POST("/:category/:name/", d.Multiplex) + mux.GET("/:category/:name/*rest", d.Multiplex) + mux.POST("/:category/:name/*rest", d.Multiplex) return mux }