Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

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.

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/requests.go +37−5

@@ -46,11 +46,17 @@ var (
46 46 )
47 47
48 48 type Request struct {
49 ID string
50 Title string
51 Author string // account name: what the approval gate compares against
52 Base string // branch name, e.g. "main"
53 Head string // commit sha under review
49 ID string
50 Title string
51 Author string // account name: what the approval gate compares against
52 Base string // branch name, e.g. "main"
53 Head string // commit sha under review
54 // HeadRef is the branch the head was taken from when the request was opened,
55 // e.g. "contrib/alice/fix". It is a display hint, not part of the review: the
56 // commit in Head is what approvals, checks, the diff and the landing gate name.
57 // It is empty for requests opened from a bare commit, for older records, and it
58 // may no longer point at Head if the branch has moved or been deleted.
59 HeadRef string
54 60 State string // open | merged | closed
55 61 Created time.Time
56 62 Description string
@@ -109,6 +115,7 @@ type requestMeta struct {
109 115 Author string `yaml:"author"`
110 116 Base string `yaml:"base"`
111 117 Head string `yaml:"head"`
118 HeadRef string `yaml:"head_ref"`
112 119 State string `yaml:"state"`
113 120 Closes []string `yaml:"closes"`
114 121 Created string `yaml:"created"`
@@ -256,6 +263,19 @@ func applyRequest(req *Request, raw, path string, problems *[]string) {
256 263 if req.Head != "" && !shaRE.MatchString(req.Head) {
257 264 *problems = append(*problems, fmt.Sprintf("%s: head must be a full 40-character commit id, got %q", path, req.Head))
258 265 }
266 // The branch is a display hint, and a branch with no commit behind it says
267 // nothing: the commit is what the request is about.
268 req.HeadRef = strings.TrimSpace(m.HeadRef)
269 if req.HeadRef != "" {
270 switch {
271 case !validHeadRef(req.HeadRef):
272 *problems = append(*problems, fmt.Sprintf(
273 "%s: head_ref must be a branch name, got %q", path, req.HeadRef))
274 case req.Head == "":
275 *problems = append(*problems, fmt.Sprintf(
276 "%s: head_ref names a branch, so head must name the commit it pointed at", path))
277 }
278 }
259 279 if m.State == "" {
260 280 m.State = "open"
261 281 }
@@ -318,6 +338,18 @@ func applyRequest(req *Request, raw, path string, problems *[]string) {
318 338 req.Description = body
319 339 }
320 340
341 // validHeadRef is the file-format check for head_ref: one line, no spaces, and not a
342 // full ref. It is deliberately looser than git's ref rules because the branch the
343 // request names may not exist yet on the reader's side, and because git is the
344 // authority where the branch does exist (Repo.ValidBranch at the writer). A reader
345 // that refused a name git accepts would reject a request that was written correctly.
346 func validHeadRef(name string) bool {
347 if name == "" || strings.HasPrefix(name, "refs/") || strings.ContainsAny(name, " \t") {
348 return false
349 }
350 return ValidText(name) == nil
351 }
352
321 353 // parseCloses validates and normalises the issues a request closes: full ids, no
322 354 // duplicates, sorted, so two writers that link the same issues render the same file.
323 355 func parseCloses(raw []string, path string) ([]string, []string) {