vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Show which branch a change request came from
8e1005eb2c104934adef950c5afc090d4025ce06 · Keenan Nemetz · 13d ago · parent b7ac1a00
Show which branch a change request came from A request records the exact commit under review, and the page showed only that: `main ← 43f98bcd`. The branch the work is on is how people talk about a change, fetch it, and find it after it lands, and it was being thrown away when the request was opened — the web form resolved the chosen branch to a commit and kept only the commit. `request.md` now records `head_ref:` beside `head:`. It is a display hint and nothing else: approvals, checks, the diff and the landing gate still name the commit, and a test pins that a branch name cannot authorise a different tip. The request page, the request list and `vole change show` show it, and the page marks the branch as moved or deleted when it no longer points at the reviewed commit, so the name reads as provenance rather than as a claim about what is being reviewed. It is optional on read: records written before it existed still load, and a request opened from a bare commit id records no branch.
server/web/writes.go +8
| @@ -242,6 +242,13 @@ func (w *Web) CreateChangeRequest(rw http.ResponseWriter, r *http.Request) { | |||
| 242 | 242 | http.Error(rw, "choose a base and a head branch", http.StatusBadRequest) | |
| 243 | 243 | return | |
| 244 | 244 | } | |
| 245 | // The head is a commit; the branch it came from is recorded as a display hint. | ||
| 246 | // It has to be a real branch name, or a hand-edited form could store something | ||
| 247 | // the metadata reader would refuse. | ||
| 248 | if !m.Git().ValidBranch(head) { | ||
| 249 | http.Error(rw, "that head branch does not exist yet; push it first", http.StatusBadRequest) | ||
| 250 | return | ||
| 251 | } | ||
| 245 | 252 | headRef := "refs/heads/" + head | |
| 246 | 253 | if contributorOnly(ctx.ACL, ctx.Name) { | |
| 247 | 254 | // A contributor's head must be a branch the hook would let them push. The | |
| @@ -266,6 +273,7 @@ func (w *Web) CreateChangeRequest(rw http.ResponseWriter, r *http.Request) { | |||
| 266 | 273 | http.Error(rw, err.Error(), http.StatusBadRequest) | |
| 267 | 274 | return | |
| 268 | 275 | } | |
| 276 | req.HeadRef = head | ||
| 269 | 277 | // Issues this request promises to close. They are checked when the request is | |
| 270 | 278 | // written, so a typo fails here rather than at the landing. | |
| 271 | 279 | req.Closes = closesField(r.PostFormValue("closes")) | |