vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Render the styled error page for every miss and failure
e84a66f5b53c269d8b0c207d0335b537e1646cb3 · Keenan Nemetz · 15d ago · parent f6f4b1db
Render the styled error page for every miss and failure Handler-level 404s now use the same view as the catch-all, including unknown detail resources and download paths. Internal 500s render the shared error layout and log the detail instead of exposing it. A panic before the first byte is recovered into that page; a partial response is left to net/http. Also mark label/assignee triage and inline review comments done in the UI plan, where the slice order was stale.
server/web/releases.go +7−7
| @@ -35,7 +35,7 @@ func (w *Web) Releases(rw http.ResponseWriter, r *http.Request) { | |||
| 35 | 35 | } | |
| 36 | 36 | tags, err := m.Git().Tags() | |
| 37 | 37 | if err != nil { | |
| 38 | http.Error(rw, "vole: cannot list tags", http.StatusInternalServerError) | ||
| 38 | w.serverError(rw, r, "cannot list tags: "+err.Error()) | ||
| 39 | 39 | return | |
| 40 | 40 | } | |
| 41 | 41 | light := 0 | |
| @@ -60,7 +60,7 @@ func (w *Web) ReleaseView(rw http.ResponseWriter, r *http.Request) { | |||
| 60 | 60 | g := m.Git() | |
| 61 | 61 | t, err := g.Tag(r.PathValue("tag")) | |
| 62 | 62 | if err != nil { | |
| 63 | http.NotFound(rw, r) | ||
| 63 | w.notFound(rw, r) | ||
| 64 | 64 | return | |
| 65 | 65 | } | |
| 66 | 66 | // The previous release is the nearest one behind this commit, not the next | |
| @@ -139,13 +139,13 @@ func (w *Web) ReleaseArtifact(rw http.ResponseWriter, r *http.Request) { | |||
| 139 | 139 | g := m.Git() | |
| 140 | 140 | t, err := g.Tag(r.PathValue("tag")) | |
| 141 | 141 | if err != nil { | |
| 142 | http.NotFound(rw, r) | ||
| 142 | w.notFound(rw, r) | ||
| 143 | 143 | return | |
| 144 | 144 | } | |
| 145 | 145 | name := r.PathValue("artifact") | |
| 146 | 146 | artifacts, err := metadata.ListReleaseArtifacts(g, t.Name) | |
| 147 | 147 | if err != nil { | |
| 148 | http.Error(rw, "vole: cannot read that release", http.StatusInternalServerError) | ||
| 148 | w.serverError(rw, r, "cannot read that release: "+err.Error()) | ||
| 149 | 149 | return | |
| 150 | 150 | } | |
| 151 | 151 | var art *metadata.Artifact | |
| @@ -156,7 +156,7 @@ func (w *Web) ReleaseArtifact(rw http.ResponseWriter, r *http.Request) { | |||
| 156 | 156 | } | |
| 157 | 157 | } | |
| 158 | 158 | if art == nil || w.LFS == nil { | |
| 159 | http.NotFound(rw, r) | ||
| 159 | w.notFound(rw, r) | ||
| 160 | 160 | return | |
| 161 | 161 | } | |
| 162 | 162 | f, size, err := w.LFS.Open(m.Name, art.OID) | |
| @@ -164,7 +164,7 @@ func (w *Web) ReleaseArtifact(rw http.ResponseWriter, r *http.Request) { | |||
| 164 | 164 | // A pointer whose object is gone is a store that lost bytes, not a | |
| 165 | 165 | // client mistake; it still cannot be served. | |
| 166 | 166 | w.Logger("artifact %s/%s/%s: %v", m.Name, t.Name, name, err) | |
| 167 | http.NotFound(rw, r) | ||
| 167 | w.notFound(rw, r) | ||
| 168 | 168 | return | |
| 169 | 169 | } | |
| 170 | 170 | defer f.Close() | |
| @@ -214,7 +214,7 @@ func (w *Web) releaseArchive(rw http.ResponseWriter, r *http.Request, format str | |||
| 214 | 214 | g := m.Git() | |
| 215 | 215 | t, err := g.Tag(r.PathValue("tag")) | |
| 216 | 216 | if err != nil { | |
| 217 | http.NotFound(rw, r) | ||
| 217 | w.notFound(rw, r) | ||
| 218 | 218 | return | |
| 219 | 219 | } | |
| 220 | 220 | ||