parent:
e4c00fc2a01331bb0b70d8f881ce63a4d7dbccbf
nmyk <nick@nmyk.io>
2026-02-16T14:29:45-05:00
handle / in branch or tag name
diff --git a/main.go b/main.go
index dd2b8362d9ad56026e91aec6f22cff4c7bb00e0f..d0625a493efbdfe4acbcd61d40408adf8d9c2357 100644
--- a/main.go
+++ b/main.go
@@ -39,9 +39,8 @@ mux.HandleFunc("GET /", listRepos)
mux.HandleFunc("GET /{name}", repoIndex)
mux.HandleFunc("GET /{name}/refs", refs)
mux.HandleFunc("GET /{name}/refs/{type}", refs)
- mux.HandleFunc("GET /{name}/tree/{ref}", repoTree)
- mux.HandleFunc("GET /{name}/tree/{ref}/{path...}", repoTree)
- mux.HandleFunc("GET /{name}/blob/{ref}/{path...}", blob)
+ mux.HandleFunc("GET /{name}/tree/{path...}", repoTree)
+ mux.HandleFunc("GET /{name}/blob/{path...}", blob)
return mux
}
@@ -159,6 +158,29 @@ }
serve(w, "refs", data)
}
+func parse(repo *git.Repository, refAndPath string) (refName string, urlPath string) {
+ if refAndPath == "" {
+ return "", ""
+ }
+ candidate := strings.TrimPrefix(refAndPath, "/")
+ for {
+ ref, err := resolve(repo, candidate)
+ if err == nil {
+ if len(candidate) < len(refAndPath) {
+ urlPath = strings.TrimPrefix(refAndPath[len(candidate):], "/")
+ }
+ refName = ref.Name().Short()
+ return
+ }
+ parent := path.Dir(candidate)
+ if parent == "." || parent == candidate {
+ break
+ }
+ candidate = parent
+ }
+ return "", ""
+}
+
func blob(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
if _, err := os.Stat(repoName + DOT_GIT); os.IsNotExist(err) {
@@ -170,7 +192,7 @@ if err != nil {
http.Error(w, err.Error(), 500)
return
}
- refName := r.PathValue("ref")
+ refName, filePath := parse(repo, r.PathValue("path"))
ref, err := resolve(repo, refName)
if err != nil {
http.NotFound(w, r)
@@ -186,7 +208,6 @@ if err != nil {
http.Error(w, err.Error(), 500)
return
}
- filePath := r.PathValue("path")
entry, err := tree.FindEntry(filePath)
if err != nil {
http.NotFound(w, nil)
@@ -262,13 +283,12 @@ if err != nil {
http.Error(w, err.Error(), 500)
return
}
- refName := r.PathValue("ref")
+ refName, treePath := parse(repo, r.PathValue("path"))
head, err := repo.Head()
if err != nil {
http.Error(w, "Cannot resolve HEAD state", 500)
}
headRef := head.Name().Short()
- treePath := r.PathValue("path")
if refName == headRef && treePath == "" {
repoIndex(w, r)
return