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.
Serve changes at /r/<repo>/changes
8fb7aabf534adf208cd795724b1e3d287dc62f5a · Keenan Nemetz · 3d ago · parent b492b557
Serve changes at /r/<repo>/changes The metadata tree and the interface say changes; the browser was the last place spelling the route requests. Rename every method on that subtree and the URLs the server builds: redirects, activity and search results, the number alias, code links, templates, and the CLI's page links. The old route is gone rather than aliased. Nothing has been publicly released, so there is no bookmark or client to keep working, and a redirect would leave two spellings of the same page in the code. Refs #204 (01M6S6685JFG8S64ZFF452217W).
server/web/writes.go +8−8
| @@ -216,7 +216,7 @@ func (w *Web) ApproveRequest(rw http.ResponseWriter, r *http.Request) { | |||
| 216 | 216 | w.render(rw, "request_live_write", w.requestLiveWrite(r, m, updated, ""), 0) | |
| 217 | 217 | return | |
| 218 | 218 | } | |
| 219 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+id, http.StatusSeeOther) | ||
| 219 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+id, http.StatusSeeOther) | ||
| 220 | 220 | } | |
| 221 | 221 | ||
| 222 | 222 | // CreateChangeRequest is the browser counterpart of `vole change new`. The head | |
| @@ -297,7 +297,7 @@ func (w *Web) CreateChangeRequest(rw http.ResponseWriter, r *http.Request) { | |||
| 297 | 297 | if problems := metadata.ValidateRequests(m.Git(), metadata.Ref); len(problems) > 0 { | |
| 298 | 298 | w.Logger("web: request %s left the request tree invalid: %v", req.ID, problems) | |
| 299 | 299 | } | |
| 300 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+req.ID, http.StatusSeeOther) | ||
| 300 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+req.ID, http.StatusSeeOther) | ||
| 301 | 301 | } | |
| 302 | 302 | ||
| 303 | 303 | // ChangeIssueState closes or reopens an issue. The author can do this without a | |
| @@ -365,7 +365,7 @@ func (w *Web) ChangeRequestState(rw http.ResponseWriter, r *http.Request) { | |||
| 365 | 365 | if problems := metadata.ValidateRequests(m.Git(), metadata.Ref); len(problems) > 0 { | |
| 366 | 366 | w.Logger("web: request state %s left the request tree invalid: %v", id, problems) | |
| 367 | 367 | } | |
| 368 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+id, http.StatusSeeOther) | ||
| 368 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+id, http.StatusSeeOther) | ||
| 369 | 369 | } | |
| 370 | 370 | ||
| 371 | 371 | // UpdateRequestTarget moves an open request's base and the branch it follows. The | |
| @@ -451,7 +451,7 @@ func (w *Web) UpdateRequestTarget(rw http.ResponseWriter, r *http.Request) { | |||
| 451 | 451 | w.Logger("web: request target %s left the request tree invalid: %v", id, problems) | |
| 452 | 452 | } | |
| 453 | 453 | } | |
| 454 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+id, http.StatusSeeOther) | ||
| 454 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+id, http.StatusSeeOther) | ||
| 455 | 455 | } | |
| 456 | 456 | ||
| 457 | 457 | // UpdateRequestIssues adds or removes one issue linked to an open change request. | |
| @@ -535,7 +535,7 @@ func (w *Web) UpdateRequestIssues(rw http.ResponseWriter, r *http.Request) { | |||
| 535 | 535 | w.render(rw, "request_issues", w.requestSidebar(r, m, updated, "", ""), 0) | |
| 536 | 536 | return | |
| 537 | 537 | } | |
| 538 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+id, http.StatusSeeOther) | ||
| 538 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+id, http.StatusSeeOther) | ||
| 539 | 539 | } | |
| 540 | 540 | ||
| 541 | 541 | // landGate is the landing gate wired to the stores this process already holds. The | |
| @@ -636,7 +636,7 @@ func (w *Web) MergeRequest(rw http.ResponseWriter, r *http.Request) { | |||
| 636 | 636 | w.Logger("web: merge left the request tree invalid: %v", problems) | |
| 637 | 637 | } | |
| 638 | 638 | // The redirect shows the request page, which now reads as merged. | |
| 639 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+id, http.StatusSeeOther) | ||
| 639 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+id, http.StatusSeeOther) | ||
| 640 | 640 | } | |
| 641 | 641 | ||
| 642 | 642 | // armMerge records "merge when ready" and answers the click. The intent is a wait, | |
| @@ -657,7 +657,7 @@ func (w *Web) armMerge(rw http.ResponseWriter, r *http.Request, m *repo.Meta, re | |||
| 657 | 657 | w.render(rw, "request_live_write", view, 0) | |
| 658 | 658 | return | |
| 659 | 659 | } | |
| 660 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+req.ID+"?merging=1", http.StatusSeeOther) | ||
| 660 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+req.ID+"?merging=1", http.StatusSeeOther) | ||
| 661 | 661 | } | |
| 662 | 662 | ||
| 663 | 663 | // CancelMerge turns off merge-when-ready. It cannot cancel a landing that already | |
| @@ -682,7 +682,7 @@ func (w *Web) CancelMerge(rw http.ResponseWriter, r *http.Request) { | |||
| 682 | 682 | return | |
| 683 | 683 | } | |
| 684 | 684 | w.audit("web.request.merge_cancel", ctx.Name, m.Name, id) | |
| 685 | http.Redirect(rw, r, "/r/"+m.Name+"/requests/"+id, http.StatusSeeOther) | ||
| 685 | http.Redirect(rw, r, "/r/"+m.Name+"/changes/"+id, http.StatusSeeOther) | ||
| 686 | 686 | } | |
| 687 | 687 | ||
| 688 | 688 | // mergeRefused renders a refusal where the reader can see the review, the conflict | |