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

Line attribution on main · 103 line(s)

c5902451
Keenan Nemetz
16d ago
1 package metadata
2
3 import (
4 "sort"
5 "strings"
6 )
7
8 // NormalizeLabels accepts what people type: a comma-separated list or the option
9 // repeated. Labels are sorted so the written file does not depend on argument
10 // order.
11 func NormalizeLabels(in []string) []string {
12 var out []string
13 for _, v := range in {
14 for _, part := range strings.Split(v, ",") {
15 if l := strings.TrimSpace(part); l != "" {
16 out = append(out, l)
17 }
18 }
19 }
20 sort.Strings(out)
21 return out
22 }
23
24 // NormalizeAssignees accepts an optional leading @, a comma-separated list, or
25 // the option repeated. Names are returned sorted and unique.
26 func NormalizeAssignees(in []string) []string {
27 seen := map[string]bool{}
28 for _, v := range in {
29 for _, part := range strings.Split(v, ",") {
30 n := strings.ToLower(strings.TrimPrefix(strings.TrimSpace(part), "@"))
31 if n != "" {
32 seen[n] = true
33 }
34 }
35 }
36 return SortedNames(seen)
37 }
38
39 // SortedNames renders a set of names in the order the writer stores them.
40 func SortedNames(set map[string]bool) []string {
41 if len(set) == 0 {
42 return nil
43 }
44 out := make([]string, 0, len(set))
45 for n := range set {
46 out = append(out, n)
47 }
48 sort.Strings(out)
49 return out
50 }
51
52 // SameNames reports whether have is already exactly set, so a command that
53 // changes nothing commits nothing.
54 func SameNames(have []string, set map[string]bool) bool {
55 if len(have) != len(set) {
56 return false
57 }
58 for _, n := range have {
59 if !set[n] {
60 return false
61 }
62 }
63 return true
64 }
65
66 // IncludesAll reports whether every wanted value is present in have.
67 func IncludesAll(have, want []string) bool {
68 if len(want) == 0 {
69 return true
70 }
71 present := map[string]bool{}
72 for _, v := range have {
73 present[v] = true
74 }
75 for _, v := range want {
76 if !present[v] {
77 return false
78 }
79 }
80 return true
81 }
82
83 // Same reports whether two issues would render to the same file. Slices are
84 // compared position by position because the writer sorts them: a different order
85 // is not a different file.
86 func Same(a, b Issue) bool {
87 if a.Title != b.Title || a.State != b.State || a.Description != b.Description {
88 return false
89 }
90 return sameList(a.Labels, b.Labels) && sameList(a.Assignees, b.Assignees)
91 }
92
93 func sameList(a, b []string) bool {
94 if len(a) != len(b) {
95 return false
96 }
97 for i := range a {
98 if a[i] != b[i] {
99 return false
100 }
101 }
102 return true
103 }