pgservicefile.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Package pgservicefile is a parser for PostgreSQL service files (e.g. .pg_service.conf).
  2. package pgservicefile
  3. import (
  4. "bufio"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "os"
  9. "strings"
  10. )
  11. type Service struct {
  12. Name string
  13. Settings map[string]string
  14. }
  15. type Servicefile struct {
  16. Services []*Service
  17. servicesByName map[string]*Service
  18. }
  19. // GetService returns the named service.
  20. func (sf *Servicefile) GetService(name string) (*Service, error) {
  21. service, present := sf.servicesByName[name]
  22. if !present {
  23. return nil, errors.New("not found")
  24. }
  25. return service, nil
  26. }
  27. // ReadServicefile reads the file at path and parses it into a Servicefile.
  28. func ReadServicefile(path string) (*Servicefile, error) {
  29. f, err := os.Open(path)
  30. if err != nil {
  31. return nil, err
  32. }
  33. defer f.Close()
  34. return ParseServicefile(f)
  35. }
  36. // ParseServicefile reads r and parses it into a Servicefile.
  37. func ParseServicefile(r io.Reader) (*Servicefile, error) {
  38. servicefile := &Servicefile{}
  39. var service *Service
  40. scanner := bufio.NewScanner(r)
  41. lineNum := 0
  42. for scanner.Scan() {
  43. lineNum += 1
  44. line := scanner.Text()
  45. line = strings.TrimSpace(line)
  46. if line == "" || strings.HasPrefix(line, "#") {
  47. // ignore comments and empty lines
  48. } else if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
  49. service = &Service{Name: line[1 : len(line)-1], Settings: make(map[string]string)}
  50. servicefile.Services = append(servicefile.Services, service)
  51. } else {
  52. parts := strings.SplitN(line, "=", 2)
  53. if len(parts) != 2 {
  54. return nil, fmt.Errorf("unable to parse line %d", lineNum)
  55. }
  56. key := strings.TrimSpace(parts[0])
  57. value := strings.TrimSpace(parts[1])
  58. service.Settings[key] = value
  59. }
  60. }
  61. servicefile.servicesByName = make(map[string]*Service, len(servicefile.Services))
  62. for _, service := range servicefile.Services {
  63. servicefile.servicesByName[service.Name] = service
  64. }
  65. return servicefile, scanner.Err()
  66. }