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.
metadata/request_write.go +11
| @@ -53,6 +53,14 @@ func validateRequestForWrite(r *Request) error { | |||
| 53 | 53 | if r.Head != "" && !shaRE.MatchString(r.Head) { | |
| 54 | 54 | return fmt.Errorf("requests: head %q is not a full commit id", r.Head) | |
| 55 | 55 | } | |
| 56 | if r.HeadRef != "" { | ||
| 57 | if !validHeadRef(r.HeadRef) { | ||
| 58 | return fmt.Errorf("requests: head_ref %q is not a branch name", r.HeadRef) | ||
| 59 | } | ||
| 60 | if r.Head == "" { | ||
| 61 | return fmt.Errorf("requests: head_ref names a branch, so head must name the commit it pointed at") | ||
| 62 | } | ||
| 63 | } | ||
| 56 | 64 | if r.MergedBase != "" && !shaRE.MatchString(r.MergedBase) { | |
| 57 | 65 | return fmt.Errorf("requests: merged base %q is not a full commit id", r.MergedBase) | |
| 58 | 66 | } | |
| @@ -71,6 +79,9 @@ func renderRequest(r *Request) ([]byte, error) { | |||
| 71 | 79 | d.Word("author", r.Author) | |
| 72 | 80 | d.Word("base", r.Base) | |
| 73 | 81 | d.Word("head", r.Head) | |
| 82 | if r.HeadRef != "" { | ||
| 83 | d.Word("head_ref", r.HeadRef) | ||
| 84 | } | ||
| 74 | 85 | d.List("closes", r.Closes) | |
| 75 | 86 | d.Word("created", r.Created.UTC().Format(time.RFC3339)) | |
| 76 | 87 | if r.State == "merged" { | |