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.

Blame · metadata/request_find.go

Line attribution on main · 58 line(s)

c5902451
Keenan Nemetz
16d ago
1 package metadata
2
3 import (
4 "fmt"
5 "strings"
6
d37d301f
Keenan Nemetz
16h ago
7 "rodent.software/vole/core/git"
c5902451
Keenan Nemetz
16d ago
8 )
9
10 // Find returns one request by id. A unique prefix is accepted, because the list
e05f1c48
Keenan Nemetz
13d ago
11 // command prints full ids but people type the part they read. A bare number is
12 // the alias `#42` names, shared with issues, so the kind is checked rather than
13 // assumed: asking for a change request by an issue's number is a mistake worth
14 // naming.
c5902451
Keenan Nemetz
16d ago
15 func FindRequest(g *git.Repo, id string) (*Request, error) {
e05f1c48
Keenan Nemetz
13d ago
16 id = TrimReference(id)
17 if num, ok := ParseNumber(id); ok {
18 nums, err := LoadNumbers(g, Ref)
19 if err != nil {
20 return nil, err
21 }
22 found, kind, ok := nums.At(num)
23 if !ok {
24 return nil, fmt.Errorf("no change request or issue is #%d", num)
25 }
26 if kind != KindRequest {
27 return nil, fmt.Errorf("#%d is an issue, not a change request: %s", num, found)
28 }
29 id = found
30 }
c5902451
Keenan Nemetz
16d ago
31 list, err := LoadRequests(g, Ref)
32 if err != nil {
33 return nil, err
34 }
35 for _, r := range list {
36 if r.ID == id || (len(id) >= 4 && strings.HasPrefix(r.ID, strings.ToUpper(id))) {
37 return r, nil
38 }
39 }
40 return nil, fmt.Errorf("no change request matches %q", id)
41 }
42
43 // CurrentApprovals counts the approvals that still name the request's current
44 // head and base. An approval of an older head is history, not a vote.
e5478085
Keenan Nemetz
11d ago
45 func (r *Request) CurrentApprovals() int { return r.CurrentApprovalsBy(nil) }
46
47 // CurrentApprovalsBy is CurrentApprovals with the eligibility rule the gate and the
48 // page use: an approval counts only while its author is still an active account
49 // that maintains the repository.
50 func (r *Request) CurrentApprovalsBy(eligible func(string) bool) int {
c5902451
Keenan Nemetz
16d ago
51 n := 0
52 for _, a := range r.Approvals {
e5478085
Keenan Nemetz
11d ago
53 if a.Head == r.Head && a.Base == r.Base && (eligible == nil || eligible(a.Principal)) {
c5902451
Keenan Nemetz
16d ago
54 n++
55 }
56 }
57 return n
58 }