1
2
3
4
5
6
7 package imports
8
9 import (
10 "bytes"
11 "strings"
12 "unicode"
13 )
14
15 var slashslash = []byte("//")
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 func ShouldBuild(content []byte, tags map[string]bool) bool {
37
38
39 end := 0
40 p := content
41 for len(p) > 0 {
42 line := p
43 if i := bytes.IndexByte(line, '\n'); i >= 0 {
44 line, p = line[:i], p[i+1:]
45 } else {
46 p = p[len(p):]
47 }
48 line = bytes.TrimSpace(line)
49 if len(line) == 0 {
50 end = len(content) - len(p)
51 continue
52 }
53 if !bytes.HasPrefix(line, slashslash) {
54 break
55 }
56 }
57 content = content[:end]
58
59
60 p = content
61 allok := true
62 for len(p) > 0 {
63 line := p
64 if i := bytes.IndexByte(line, '\n'); i >= 0 {
65 line, p = line[:i], p[i+1:]
66 } else {
67 p = p[len(p):]
68 }
69 line = bytes.TrimSpace(line)
70 if !bytes.HasPrefix(line, slashslash) {
71 continue
72 }
73 line = bytes.TrimSpace(line[len(slashslash):])
74 if len(line) > 0 && line[0] == '+' {
75
76 f := strings.Fields(string(line))
77 if f[0] == "+build" {
78 ok := false
79 for _, tok := range f[1:] {
80 if matchTags(tok, tags) {
81 ok = true
82 }
83 }
84 if !ok {
85 allok = false
86 }
87 }
88 }
89 }
90
91 return allok
92 }
93
94
95
96
97
98
99
100 func matchTags(name string, tags map[string]bool) bool {
101 if name == "" {
102 return false
103 }
104 if i := strings.Index(name, ","); i >= 0 {
105
106 ok1 := matchTags(name[:i], tags)
107 ok2 := matchTags(name[i+1:], tags)
108 return ok1 && ok2
109 }
110 if strings.HasPrefix(name, "!!") {
111 return false
112 }
113 if strings.HasPrefix(name, "!") {
114 return len(name) > 1 && matchTag(name[1:], tags, false)
115 }
116 return matchTag(name, tags, true)
117 }
118
119
120 func matchTag(name string, tags map[string]bool, want bool) bool {
121
122
123 for _, c := range name {
124 if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
125 return false
126 }
127 }
128
129 if tags["*"] && name != "" && name != "ignore" {
130
131
132
133
134 return true
135 }
136
137 have := tags[name]
138 if name == "linux" {
139 have = have || tags["android"]
140 }
141 if name == "solaris" {
142 have = have || tags["illumos"]
143 }
144 if name == "darwin" {
145 have = have || tags["ios"]
146 }
147 return have == want
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 func MatchFile(name string, tags map[string]bool) bool {
170 if tags["*"] {
171 return true
172 }
173 if dot := strings.Index(name, "."); dot != -1 {
174 name = name[:dot]
175 }
176
177
178
179
180
181
182
183
184 i := strings.Index(name, "_")
185 if i < 0 {
186 return true
187 }
188 name = name[i:]
189
190 l := strings.Split(name, "_")
191 if n := len(l); n > 0 && l[n-1] == "test" {
192 l = l[:n-1]
193 }
194 n := len(l)
195 if n >= 2 && KnownOS[l[n-2]] && KnownArch[l[n-1]] {
196 return matchTag(l[n-2], tags, true) && matchTag(l[n-1], tags, true)
197 }
198 if n >= 1 && KnownOS[l[n-1]] {
199 return matchTag(l[n-1], tags, true)
200 }
201 if n >= 1 && KnownArch[l[n-1]] {
202 return matchTag(l[n-1], tags, true)
203 }
204 return true
205 }
206
207 var KnownOS = map[string]bool{
208 "aix": true,
209 "android": true,
210 "darwin": true,
211 "dragonfly": true,
212 "freebsd": true,
213 "hurd": true,
214 "illumos": true,
215 "ios": true,
216 "js": true,
217 "linux": true,
218 "nacl": true,
219 "netbsd": true,
220 "openbsd": true,
221 "plan9": true,
222 "solaris": true,
223 "windows": true,
224 "zos": true,
225 }
226
227 var KnownArch = map[string]bool{
228 "386": true,
229 "amd64": true,
230 "amd64p32": true,
231 "arm": true,
232 "armbe": true,
233 "arm64": true,
234 "arm64be": true,
235 "ppc64": true,
236 "ppc64le": true,
237 "mips": true,
238 "mipsle": true,
239 "mips64": true,
240 "mips64le": true,
241 "mips64p32": true,
242 "mips64p32le": true,
243 "ppc": true,
244 "riscv": true,
245 "riscv64": true,
246 "s390": true,
247 "s390x": true,
248 "sparc": true,
249 "sparc64": true,
250 "wasm": true,
251 }
252
View as plain text