flag.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package flag
  2. import (
  3. "errors"
  4. "flag"
  5. "github.com/imdario/mergo"
  6. "gogs.baozhida.cn/zoie/OAuth-core/config/source"
  7. "strings"
  8. "time"
  9. )
  10. type flagsrc struct {
  11. opts source.Options
  12. }
  13. func (fs *flagsrc) Read() (*source.ChangeSet, error) {
  14. if !flag.Parsed() {
  15. return nil, errors.New("flags not parsed")
  16. }
  17. var changes map[string]interface{}
  18. visitFn := func(f *flag.Flag) {
  19. n := strings.ToLower(f.Name)
  20. keys := strings.FieldsFunc(n, split)
  21. reverse(keys)
  22. tmp := make(map[string]interface{})
  23. for i, k := range keys {
  24. if i == 0 {
  25. tmp[k] = f.Value
  26. continue
  27. }
  28. tmp = map[string]interface{}{k: tmp}
  29. }
  30. _ = mergo.Map(&changes, tmp) // need to sort error handling
  31. return
  32. }
  33. unset, ok := fs.opts.Context.Value(includeUnsetKey{}).(bool)
  34. if ok && unset {
  35. flag.VisitAll(visitFn)
  36. } else {
  37. flag.Visit(visitFn)
  38. }
  39. b, err := fs.opts.Encoder.Encode(changes)
  40. if err != nil {
  41. return nil, err
  42. }
  43. cs := &source.ChangeSet{
  44. Format: fs.opts.Encoder.String(),
  45. Data: b,
  46. Timestamp: time.Now(),
  47. Source: fs.String(),
  48. }
  49. cs.Checksum = cs.Sum()
  50. return cs, nil
  51. }
  52. func split(r rune) bool {
  53. return r == '-' || r == '_'
  54. }
  55. func reverse(ss []string) {
  56. for i := len(ss)/2 - 1; i >= 0; i-- {
  57. opp := len(ss) - 1 - i
  58. ss[i], ss[opp] = ss[opp], ss[i]
  59. }
  60. }
  61. func (fs *flagsrc) Watch() (source.Watcher, error) {
  62. return source.NewNoopWatcher()
  63. }
  64. func (fs *flagsrc) Write(cs *source.ChangeSet) error {
  65. return nil
  66. }
  67. func (fs *flagsrc) String() string {
  68. return "flag"
  69. }
  70. // NewSource returns a config source for integrating parsed flags.
  71. // Hyphens are delimiters for nesting, and all keys are lowercased.
  72. //
  73. // Example:
  74. //
  75. // dbhost := flag.String("database-host", "localhost", "the db host name")
  76. //
  77. // {
  78. // "database": {
  79. // "host": "localhost"
  80. // }
  81. // }
  82. func NewSource(opts ...source.Option) source.Source {
  83. return &flagsrc{opts: source.NewOptions(opts...)}
  84. }