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/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.

Let an author move their change request's head from the browser

53ff967be619894b62ca0ca69cd9a9f5f52bce01 · Keenan Nemetz · 13d ago · parent 8e1005eb

Let an author move their change request's head from the browser

A request names the exact commit under review, so a fixup pushed after it
was opened is invisible until the head moves. The only mover was
`vole change update --head`, which writes the metadata branch — a write a
contributor cannot make. The person who owns the branch was the one person
who could not keep the request current.

The request page now offers the author (or a maintainer) a branch picker
that moves an open request's head to that branch's tip. It applies the
same rule the new-request form does: the head must be a branch tip, and a
contributor may only name a branch under their own namespace, which is
what the pre-receive hook would have let them push. Approvals stay in the
tree as history and stop matching, which is what a new head already means.

SetRequestHead now refuses a closed or merged request, so the CLI and the
browser share that rule instead of the web handler owning it alone.

server/web/request_view.go +13

@@ -59,6 +59,13 @@ type requestSidebarView struct {
59 59 // commit under review ("branch moved", "branch deleted"), so the name is read as
60 60 // provenance rather than as a claim about what is being reviewed.
61 61 HeadRefNote string
62 // CanMoveHead is the control that points an open request at a newer commit. It
63 // is offered to the author and to maintainers, and only while the request is
64 // open: a merged request's head is the record of what landed.
65 CanMoveHead bool
66 // HeadBranches are the branches that control may name: every normal branch for
67 // a maintainer, the viewer's own namespace for a contributor.
68 HeadBranches []string
62 69 // CanMerge is the merge control: true only when the gate would accept the
63 70 // landing now, so the button never offers something the handler would refuse.
64 71 CanMerge bool
@@ -129,6 +136,11 @@ func (w *Web) requestSidebar(r *http.Request, m *repo.Meta, req *metadata.Reques
129 136 headRefNote = "branch moved"
130 137 }
131 138 }
139 canMoveHead := req.Open() && canTriage(acl, who, req.Author)
140 var headChoices []string
141 if canMoveHead {
142 headChoices = headBranches(branchNames(m), acl, who)
143 }
132 144 // Preflight the landing rather than guessing from the approval count: the same
133 145 // gate the handler calls is asked here, so the button and the write agree about
134 146 // approvals, checks and conflicts.
@@ -161,6 +173,7 @@ func (w *Web) requestSidebar(r *http.Request, m *repo.Meta, req *metadata.Reques
161 173 Page: w.page(r, title), Name: m.Name, Request: req,
162 174 Approvals: approvals, Checks: checks, Required: required, Current: current,
163 175 CanApprove: approvable, CanClose: canClose, HeadRefNote: headRefNote,
176 CanMoveHead: canMoveHead, HeadBranches: headChoices,
164 177 CanMerge: mergeable, MergeBlocked: mergeBlocked,
165 178 CanDiscuss: w.canDiscuss(r, acl),
166 179 ContributorCI: contributorCI,