parser.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. package srcinfo
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "strings"
  6. )
  7. // parser is used to track our current state as we parse the srcinfo.
  8. type parser struct {
  9. // srcinfo is a Pointer to the Srcinfo we are currently building.
  10. srcinfo *Srcinfo
  11. // seenPkgnames is a set of pkgnames we have seen
  12. seenPkgnames map[string]struct{}
  13. }
  14. func (psr *parser) currentPackage() (*Package, error) {
  15. if psr.srcinfo.Pkgbase == "" {
  16. return nil, fmt.Errorf("Not in pkgbase or pkgname")
  17. } else if len(psr.srcinfo.Packages) == 0 {
  18. return &psr.srcinfo.Package, nil
  19. } else {
  20. return &psr.srcinfo.Packages[len(psr.srcinfo.Packages) - 1], nil
  21. }
  22. }
  23. func (psr *parser) setHeaderOrField(key, value string) error {
  24. pkgbase := &psr.srcinfo.PackageBase
  25. switch key {
  26. case "pkgbase":
  27. if psr.srcinfo.Pkgbase != "" {
  28. return fmt.Errorf("key \"%s\" can not occur after pkgbase or pkgname", key)
  29. }
  30. pkgbase.Pkgbase = value
  31. return nil
  32. case "pkgname":
  33. if psr.srcinfo.Pkgbase == "" {
  34. return fmt.Errorf("key \"%s\" can not occur before pkgbase", key)
  35. }
  36. if _, ok := psr.seenPkgnames[value]; ok {
  37. return fmt.Errorf("pkgname \"%s\" can not occur more than once", value)
  38. }
  39. psr.seenPkgnames[value] = struct{}{}
  40. psr.srcinfo.Packages = append(psr.srcinfo.Packages, Package{Pkgname: value})
  41. return nil
  42. }
  43. if psr.srcinfo.Pkgbase == "" {
  44. return fmt.Errorf("key \"%s\" can not occur before pkgbase or pkgname", key)
  45. }
  46. return psr.setField(key, value)
  47. }
  48. func (psr *parser) setField(archKey, value string) error {
  49. pkg, err := psr.currentPackage()
  50. if err != nil {
  51. return err
  52. }
  53. pkgbase := &psr.srcinfo.PackageBase
  54. key, arch := splitArchFromKey(archKey)
  55. err = checkArch(psr.srcinfo.Arch, archKey, arch)
  56. if err != nil {
  57. return err
  58. }
  59. if value == "" {
  60. value = EmptyOverride
  61. }
  62. // pkgbase only + not arch dependent
  63. found := true
  64. switch archKey {
  65. case "pkgver":
  66. pkgbase.Pkgver = value
  67. case "pkgrel":
  68. pkgbase.Pkgrel = value
  69. case "epoch":
  70. pkgbase.Epoch = value
  71. case "validpgpkeys":
  72. pkgbase.ValidPGPKeys = append(pkgbase.ValidPGPKeys, value)
  73. case "noextract":
  74. pkgbase.NoExtract = append(pkgbase.NoExtract, value)
  75. default:
  76. found = false
  77. }
  78. if found {
  79. if len(psr.srcinfo.Packages) > 0 {
  80. return fmt.Errorf("key \"%s\" can not occur after pkgname", archKey)
  81. }
  82. return nil
  83. }
  84. // pkgbase only + arch dependent
  85. found = true
  86. switch key {
  87. case "source":
  88. pkgbase.Source = append(pkgbase.Source, ArchString{arch, value})
  89. case "md5sums":
  90. pkgbase.MD5Sums = append(pkgbase.MD5Sums, ArchString{arch, value})
  91. case "sha1sums":
  92. pkgbase.SHA1Sums = append(pkgbase.SHA1Sums, ArchString{arch, value})
  93. case "sha224sums":
  94. pkgbase.SHA224Sums = append(pkgbase.SHA224Sums, ArchString{arch, value})
  95. case "sha256sums":
  96. pkgbase.SHA256Sums = append(pkgbase.SHA256Sums, ArchString{arch, value})
  97. case "sha384sums":
  98. pkgbase.SHA384Sums = append(pkgbase.SHA384Sums, ArchString{arch, value})
  99. case "sha512sums":
  100. pkgbase.SHA512Sums = append(pkgbase.SHA512Sums, ArchString{arch, value})
  101. case "makedepends":
  102. pkgbase.MakeDepends = append(pkgbase.MakeDepends, ArchString{arch, value})
  103. case "checkdepends":
  104. pkgbase.CheckDepends = append(pkgbase.CheckDepends, ArchString{arch, value})
  105. default:
  106. found = false
  107. }
  108. if found {
  109. if len(psr.srcinfo.Packages) > 0 {
  110. return fmt.Errorf("key \"%s\" can not occur after pkgname", archKey)
  111. }
  112. return nil
  113. }
  114. // pkgbase or pkgname + not arch dependent
  115. found = true
  116. switch archKey {
  117. case "pkgdesc":
  118. pkg.Pkgdesc = value
  119. case "url":
  120. pkg.URL = value
  121. case "license":
  122. pkg.License = append(pkg.License, value)
  123. case "install":
  124. pkg.Install = value
  125. case "changelog":
  126. pkg.Changelog = value
  127. case "groups":
  128. pkg.Groups = append(pkg.Groups, value)
  129. case "arch":
  130. pkg.Arch = append(pkg.Arch, value)
  131. case "backup":
  132. pkg.Backup = append(pkg.Backup, value)
  133. case "options":
  134. pkg.Options = append(pkg.Options, value)
  135. default:
  136. found = false
  137. }
  138. if found {
  139. return nil
  140. }
  141. // pkgbase or pkgname + arch dependent
  142. switch key {
  143. case "depends":
  144. pkg.Depends = append(pkg.Depends, ArchString{arch, value})
  145. case "optdepends":
  146. pkg.OptDepends = append(pkg.OptDepends, ArchString{arch, value})
  147. case "conflicts":
  148. pkg.Conflicts = append(pkg.Conflicts, ArchString{arch, value})
  149. case "provides":
  150. pkg.Provides = append(pkg.Provides, ArchString{arch, value})
  151. case "replaces":
  152. pkg.Replaces = append(pkg.Replaces, ArchString{arch, value})
  153. default:
  154. return fmt.Errorf("Unknown key: \"%s\"", archKey)
  155. }
  156. return nil
  157. }
  158. func parse(data string) (*Srcinfo, error) {
  159. psr := &parser{
  160. &Srcinfo{},
  161. make(map[string]struct{}),
  162. }
  163. lines := strings.Split(data, "\n")
  164. for n, line := range lines {
  165. line = strings.TrimSpace(line)
  166. if line == "" || strings.HasPrefix(line, "#") {
  167. continue
  168. }
  169. key, value, err := splitPair(line)
  170. if err != nil {
  171. return nil, Error(n+1, line, err.Error())
  172. }
  173. err = psr.setHeaderOrField(key, value)
  174. if err != nil {
  175. return nil, Error(n+1, line, err.Error())
  176. }
  177. }
  178. if psr.srcinfo.Pkgbase == "" {
  179. return nil, fmt.Errorf("No pkgbase field")
  180. }
  181. if len(psr.srcinfo.Packages) == 0 {
  182. return nil, fmt.Errorf("No pkgname field")
  183. }
  184. if psr.srcinfo.Pkgver == "" {
  185. return nil, fmt.Errorf("No pkgver field")
  186. }
  187. if psr.srcinfo.Pkgrel == "" {
  188. return nil, fmt.Errorf("No pkgrel field")
  189. }
  190. if len(psr.srcinfo.Arch) == 0 {
  191. return nil, fmt.Errorf("No arch field")
  192. }
  193. return psr.srcinfo, nil
  194. }
  195. // splitPair splits a key value string in the form of "key = value",
  196. // whitespace being ignored. The key and the value is returned.
  197. func splitPair(line string) (string, string, error) {
  198. split := strings.SplitN(line, "=", 2)
  199. if len(split) != 2 {
  200. return "", "", fmt.Errorf("Line does not contain =")
  201. }
  202. key := strings.TrimSpace(split[0])
  203. value := strings.TrimSpace(split[1])
  204. if key == "" {
  205. return "", "", fmt.Errorf("Key is empty")
  206. }
  207. return key, value, nil
  208. }
  209. // splitArchFromKey splits up architecture dependent field names, separating
  210. // the field name from the architecture they depend on.
  211. func splitArchFromKey(key string) (string, string) {
  212. split := strings.SplitN(key, "_", 2)
  213. if len(split) == 2 {
  214. return split[0], split[1]
  215. }
  216. return split[0], ""
  217. }
  218. // checkArg checks that the arch from an arch dependent string is actually
  219. // defined inside of the srcinfo and speicifly disallows the arch "any" as it
  220. // is not a real arch
  221. func checkArch(arches []string, key string, arch string) error {
  222. if arch == "" {
  223. return nil
  224. }
  225. if arch == "any" {
  226. return fmt.Errorf("Invalid key \"%s\" arch \"%s\" is not allowed", key, arch)
  227. }
  228. for _, a := range arches {
  229. if a == arch {
  230. return nil
  231. }
  232. }
  233. return fmt.Errorf("Invalid key \"%s\" unsupported arch \"%s\"", key, arch)
  234. }
  235. // ParseFile parses a srcinfo file as specified by path.
  236. func ParseFile(path string) (*Srcinfo, error) {
  237. file, err := ioutil.ReadFile(path)
  238. if err != nil {
  239. return nil, fmt.Errorf("Unable to read file: %s: %s", path, err.Error())
  240. }
  241. return Parse(string(file))
  242. }
  243. // Parse parses a srcinfo in string form. Parsing will fail if:
  244. // A srcinfo does not contain all required fields
  245. // The same pkgname is specified more then once
  246. // arch is missing
  247. // pkgver is mising
  248. // pkgrel is missing
  249. // An architecture specific field is defined for an architecture that does not exist
  250. // An unknown key is specified
  251. // An empty value is specified
  252. //
  253. // Required fields are:
  254. // pkgbase
  255. // pkname
  256. // arch
  257. // pkgrel
  258. // pkgver
  259. func Parse(data string) (*Srcinfo, error) {
  260. return parse(data)
  261. }