config.go 2.0 KB

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