config.go raw
1 package lintcmd
2
3 import (
4 "bufio"
5 "errors"
6 "fmt"
7 "io"
8 "strings"
9 "unicode"
10 )
11
12 type parseBuildConfigError struct {
13 line int
14 err error
15 }
16
17 func (err parseBuildConfigError) Error() string { return err.err.Error() }
18
19 func parseBuildConfigs(r io.Reader) ([]buildConfig, error) {
20 var builds []buildConfig
21 br := bufio.NewReader(r)
22 i := 0
23 for {
24 line, err := br.ReadString('\n')
25 if err != nil {
26 if err == io.EOF {
27 break
28 } else {
29 return nil, err
30 }
31 }
32 line = strings.TrimSpace(line)
33 if line == "" {
34 continue
35 }
36 name, envs, flags, err := parseBuildConfig(line)
37 if err != nil {
38 return nil, parseBuildConfigError{line: i + 1, err: err}
39 }
40
41 bc := buildConfig{
42 Name: name,
43 Envs: envs,
44 Flags: flags,
45 }
46 builds = append(builds, bc)
47
48 i++
49 }
50 return builds, nil
51 }
52
53 func parseBuildConfig(line string) (name string, envs []string, flags []string, err error) {
54 if line == "" {
55 return "", nil, nil, errors.New("couldn't parse empty build config")
56 }
57 if strings.Index(line, ":") == len(line)-1 {
58 name = line[:len(line)-1]
59 } else {
60 idx := strings.Index(line, ": ")
61 if idx == -1 {
62 return name, envs, flags, errors.New("missing build name")
63 }
64 name = line[:idx]
65
66 var buf []rune
67 var inQuote bool
68 args := &envs
69 for _, r := range strings.TrimSpace(line[idx+2:]) {
70 switch r {
71 case ' ':
72 if inQuote {
73 buf = append(buf, r)
74 } else if len(buf) != 0 {
75 if buf[0] == '-' {
76 args = &flags
77 }
78 *args = append(*args, string(buf))
79 buf = buf[:0]
80 }
81 case '"':
82 inQuote = !inQuote
83 default:
84 buf = append(buf, r)
85 }
86 }
87
88 if len(buf) > 0 {
89 if inQuote {
90 return "", nil, nil, errors.New("unterminated quoted string")
91 }
92 if buf[0] == '-' {
93 args = &flags
94 }
95 *args = append(*args, string(buf))
96 }
97 }
98
99 for _, r := range name {
100 if !(r == '_' || unicode.IsLetter(r) || unicode.IsNumber(r)) {
101 return "", nil, nil, fmt.Errorf("invalid build name %q", name)
102 }
103 }
104 return name, envs, flags, nil
105 }
106