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.

Compact the change request target controls

41d1fee900568b1bff5c7cff3b4c52942f47fabd · Keenan Nemetz · 13d ago · parent e050e14a

Compact the change request target controls

Replace the separate base and head forms and the duplicated labels with one
row: base picker, head picker, update. The pickers preselect the current
targets, and a pinned head appears as the current commit. Collapse the help
text to one line.

Post both targets to one /target handler and write them in one metadata
commit. Either change invalidates approvals; keeping the current value is
allowed even if its branch has gone missing so the other side can still be
repaired.

server/web/request_view.go +40−26

@@ -34,6 +34,30 @@ type requestCheck struct {
34 34 Exit int
35 35 }
36 36
37 // branchOption is one choice in the request target picker. The selected flag is
38 // built here so the template does not have to compare strings, and so a branch that
39 // has gone missing can stay visible as the current value instead of silently
40 // selecting a different branch.
41 type branchOption struct {
42 Name string
43 Selected bool
44 }
45
46 func branchOptions(names []string, selected string) []branchOption {
47 out := make([]branchOption, 0, len(names)+1)
48 found := false
49 for _, name := range names {
50 if name == selected {
51 found = true
52 }
53 out = append(out, branchOption{Name: name, Selected: name == selected})
54 }
55 if selected != "" && !found {
56 out = append([]branchOption{{Name: selected, Selected: true}}, out...)
57 }
58 return out
59 }
60
37 61 // requestCI is the approval a contributor branch needs before its workflow may
38 62 // run. It belongs on the request because that is where a maintainer reviews the
39 63 // code the tip contains.
@@ -60,21 +84,15 @@ type requestSidebarView struct {
60 84 // the head with the branch, so "branch moved" means that sync did not happen and
61 85 // the approval control is withheld until the request catches up.
62 86 HeadRefNote string
63 // CanMoveHead is the control that repoints an open request at another branch.
64 // A request opened from a branch follows it automatically, so this is only for
65 // changing which branch it follows (or attaching a request opened from a commit).
66 // It is offered to the author and to maintainers, and only while the request is
67 // open: a merged request's head is the record of what landed.
68 CanMoveHead bool
69 // HeadBranches are the branches that control may name: every normal branch for
70 // a maintainer, the viewer's own namespace for a contributor.
71 HeadBranches []string
72 // CanChangeBase is the control that retargets a stacked request at another base.
73 // A new base changes the diff, so the approvals that named the old base stop
74 // counting.
75 CanChangeBase bool
76 // BaseBranches are the branches that control may name: every normal branch.
77 BaseBranches []string
87 // CanRetarget is the combined base/head control. It is offered to the author and
88 // to maintainers, and only while the request is open: a merged request's target is
89 // the record of what landed. A request opened from a branch follows it already;
90 // this is for changing which branch, or attaching a request opened from a commit.
91 CanRetarget bool
92 // BaseOptions and HeadOptions are the branches the picker may name. HeadOptions
93 // is narrowed to the viewer's own namespace for a contributor.
94 BaseOptions []branchOption
95 HeadOptions []branchOption
78 96 // CanMerge is the merge control: true only when the gate would accept the
79 97 // landing now, so the button never offers something the handler would refuse.
80 98 CanMerge bool
@@ -148,15 +166,12 @@ func (w *Web) requestSidebar(r *http.Request, m *repo.Meta, req *metadata.Reques
148 166 // approve it while the followed branch is known to be ahead: the page is showing
149 167 // an older tip than the branch, and the head control is the way to catch up.
150 168 approvable := req.Open() && canApproveRequest(acl, who, req.Author) && headRefNote != "branch moved"
151 canMoveHead := req.Open() && canTriage(acl, who, req.Author)
152 var headChoices []string
153 if canMoveHead {
154 headChoices = headBranches(branchNames(m), acl, who)
155 }
156 canChangeBase := req.Open() && canTriage(acl, who, req.Author)
157 var baseChoices []string
158 if canChangeBase {
159 baseChoices = branchNames(m)
169 canRetarget := req.Open() && canTriage(acl, who, req.Author)
170 var baseOptions, headOptions []branchOption
171 if canRetarget {
172 branches := branchNames(m)
173 baseOptions = branchOptions(branches, req.Base)
174 headOptions = branchOptions(headBranches(branches, acl, who), req.HeadRef)
160 175 }
161 176 // Preflight the landing rather than guessing from the approval count: the same
162 177 // gate the handler calls is asked here, so the button and the write agree about
@@ -190,8 +205,7 @@ func (w *Web) requestSidebar(r *http.Request, m *repo.Meta, req *metadata.Reques
190 205 Page: w.page(r, title), Name: m.Name, Request: req,
191 206 Approvals: approvals, Checks: checks, Required: required, Current: current,
192 207 CanApprove: approvable, CanClose: canClose, HeadRefNote: headRefNote,
193 CanMoveHead: canMoveHead, HeadBranches: headChoices,
194 CanChangeBase: canChangeBase, BaseBranches: baseChoices,
208 CanRetarget: canRetarget, BaseOptions: baseOptions, HeadOptions: headOptions,
195 209 CanMerge: mergeable, MergeBlocked: mergeBlocked,
196 210 CanDiscuss: w.canDiscuss(r, acl),
197 211 ContributorCI: contributorCI,