...
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 func ShouldBuild(content []byte, tags map[string]bool) bool {
36
37
38 end := 0
39 p := content
40 for len(p) > 0 {
41 line := p
42 if i := bytes.IndexByte(line, '\n'); i >= 0 {
43 line, p = line[:i], p[i+1:]
44 } else {
45 p = p[len(p):]
46 }
47 line = bytes.TrimSpace(line)
48 if len(line) == 0 {
49 end = len(content) - len(p)
50 continue
51 }
52 if !bytes.HasPrefix(line, slashslash) {
53 break
54 }
55 }
56 content = content[:end]
57
58
59 p = content
60 allok := true
61 for len(p) > 0 {
62 line := p
63 if i := bytes.IndexByte(line, '\n'); i >= 0 {
64 line, p = line[:i], p[i+1:]
65 } else {
66 p = p[len(p):]
67 }
68 line = bytes.TrimSpace(line)
69 if !bytes.HasPrefix(line, slashslash) {
70 continue
71 }
72 line = bytes.TrimSpace(line[len(slashslash):])
73 if len(line) > 0 && line[0] == '+' {
74
75 f := strings.Fields(string(line))
76 if f[0] == "+build" {
77 ok := false
78 for _, tok := range f[1:] {
79 if matchTags(tok, tags) {
80 ok = true
81 }
82 }
83 if !ok {
84 allok = false
85 }
86 }
87 }
88 }
89
90 return allok
91 }
92
93
94
95
96
97
98 func matchTags(name string, tags map[string]bool) bool {
99 if name == "" {
100 return false
101 }
102 if i := strings.Index(name, ","); i >= 0 {
103
104 ok1 := matchTags(name[:i], tags)
105 ok2 := matchTags(name[i+1:], tags)
106 return ok1 && ok2
107 }
108 if strings.HasPrefix(name, "!!") {
109 return false
110 }
111 if strings.HasPrefix(name, "!") {
112 return len(name) > 1 && matchTag(name[1:], tags, false)
113 }
114 return matchTag(name, tags, true)
115 }
116
117
118 func matchTag(name string, tags map[string]bool, want bool) bool {
119
120
121 for _, c := range name {
122 if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
123 return false
124 }
125 }
126
127 if tags["*"] && name != "" && name != "ignore" {
128
129
130
131
132 return true
133 }
134
135 have := tags[name]
136 if name == "linux" {
137 have = have || tags["android"]
138 }
139 return have == want
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 func MatchFile(name string, tags map[string]bool) bool {
159 if tags["*"] {
160 return true
161 }
162 if dot := strings.Index(name, "."); dot != -1 {
163 name = name[:dot]
164 }
165
166
167
168
169
170
171
172
173 i := strings.Index(name, "_")
174 if i < 0 {
175 return true
176 }
177 name = name[i:]
178
179 l := strings.Split(name, "_")
180 if n := len(l); n > 0 && l[n-1] == "test" {
181 l = l[:n-1]
182 }
183 n := len(l)
184 if n >= 2 && KnownOS[l[n-2]] && KnownArch[l[n-1]] {
185 return tags[l[n-2]] && tags[l[n-1]]
186 }
187 if n >= 1 && KnownOS[l[n-1]] {
188 return tags[l[n-1]]
189 }
190 if n >= 1 && KnownArch[l[n-1]] {
191 return tags[l[n-1]]
192 }
193 return true
194 }
195
196 var (
197 KnownOS = make(map[string]bool)
198 UnixOS = make(map[string]bool)
199 KnownArch = make(map[string]bool)
200 )
201
202 func init() {
203 for _, v := range strings.Fields(goosList) {
204 KnownOS[v] = true
205 }
206 for _, v := range strings.Fields(unixList) {
207 UnixOS[v] = true
208 }
209 for _, v := range strings.Fields(goarchList) {
210 KnownArch[v] = true
211 }
212 }
213
214
215
216 const (
217 goosList = "aix android darwin dragonfly freebsd hurd illumos ios js linux nacl netbsd openbsd plan9 solaris windows zos "
218 unixList = "aix android darwin dragonfly freebsd hurd illumos ios linux netbsd openbsd solaris "
219 goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc ppc64 ppc64le riscv riscv64 s390 s390x sparc sparc64 wasm "
220 )
221
View as plain text