config.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "text/template"
  9. "time"
  10. )
  11. type Options struct {
  12. Listen string `ini:"listen-address" default:":22000" description:"ip:port to for incoming sync connections"`
  13. ReadOnly bool `ini:"read-only" description:"Allow changes to the local repository"`
  14. Delete bool `ini:"allow-delete" default:"true" description:"Allow deletes of files in the local repository"`
  15. Symlinks bool `ini:"follow-symlinks" default:"true" description:"Follow symbolic links at the top level of the repository"`
  16. GUI bool `ini:"gui-enabled" default:"true" description:"Enable the HTTP GUI"`
  17. GUIAddr string `ini:"gui-address" default:"127.0.0.1:8080" description:"ip:port for GUI connections"`
  18. ExternalServer string `ini:"global-announce-server" default:"syncthing.nym.se:22025" description:"Global server for announcements"`
  19. ExternalDiscovery bool `ini:"global-announce-enabled" default:"true" description:"Announce to the global announce server"`
  20. LocalDiscovery bool `ini:"local-announce-enabled" default:"true" description:"Announce to the local network"`
  21. ParallelRequests int `ini:"parallel-requests" default:"16" description:"Maximum number of blocks to request in parallel"`
  22. LimitRate int `ini:"max-send-kbps" description:"Limit outgoing data rate (kbyte/s)"`
  23. ScanInterval time.Duration `ini:"rescan-interval" default:"60s" description:"Scan repository for changes this often"`
  24. ConnInterval time.Duration `ini:"reconnection-interval" default:"60s" description:"Attempt to (re)connect to peers this often"`
  25. MaxChangeBW int `ini:"max-change-bw" default:"1000" description:"Suppress files changing more than this (kbyte/s)"`
  26. }
  27. func loadConfig(m map[string]string, data interface{}) error {
  28. s := reflect.ValueOf(data).Elem()
  29. t := s.Type()
  30. for i := 0; i < s.NumField(); i++ {
  31. f := s.Field(i)
  32. tag := t.Field(i).Tag
  33. name := tag.Get("ini")
  34. if len(name) == 0 {
  35. name = strings.ToLower(t.Field(i).Name)
  36. }
  37. v, ok := m[name]
  38. if !ok {
  39. v = tag.Get("default")
  40. }
  41. if len(v) > 0 {
  42. switch f.Interface().(type) {
  43. case time.Duration:
  44. d, err := time.ParseDuration(v)
  45. if err != nil {
  46. return err
  47. }
  48. f.SetInt(int64(d))
  49. case string:
  50. f.SetString(v)
  51. case int:
  52. i, err := strconv.ParseInt(v, 10, 64)
  53. if err != nil {
  54. return err
  55. }
  56. f.SetInt(i)
  57. case bool:
  58. f.SetBool(v == "true")
  59. default:
  60. panic(f.Type())
  61. }
  62. }
  63. }
  64. return nil
  65. }
  66. type cfg struct {
  67. Key string
  68. Value string
  69. Comment string
  70. }
  71. func structToValues(data interface{}) []cfg {
  72. s := reflect.ValueOf(data).Elem()
  73. t := s.Type()
  74. var vals []cfg
  75. for i := 0; i < s.NumField(); i++ {
  76. f := s.Field(i)
  77. tag := t.Field(i).Tag
  78. var c cfg
  79. c.Key = tag.Get("ini")
  80. if len(c.Key) == 0 {
  81. c.Key = strings.ToLower(t.Field(i).Name)
  82. }
  83. c.Value = fmt.Sprint(f.Interface())
  84. c.Comment = tag.Get("description")
  85. vals = append(vals, c)
  86. }
  87. return vals
  88. }
  89. var configTemplateStr = `[repository]
  90. {{if .comments}}; The directory to synchronize. Will be created if it does not exist.
  91. {{end}}dir = {{.dir}}
  92. [nodes]
  93. {{if .comments}}; Map of node ID to addresses, or "dynamic" for automatic discovery. Examples:
  94. ; J3MZ4G5O4CLHJKB25WX47K5NUJUWDOLO2TTNY3TV3NRU4HVQRKEQ = 172.16.32.24:22000
  95. ; ZNJZRXQKYHF56A2VVNESRZ6AY4ZOWGFJCV6FXDZJUTRVR3SNBT6Q = dynamic
  96. {{end}}{{range $n, $a := .nodes}}{{$n}} = {{$a}}
  97. {{end}}
  98. [settings]
  99. {{range $v := .settings}}; {{$v.Comment}}
  100. {{$v.Key}} = {{$v.Value}}
  101. {{end}}
  102. `
  103. var configTemplate = template.Must(template.New("config").Parse(configTemplateStr))
  104. func writeConfig(wr io.Writer, dir string, nodes map[string]string, opts Options, comments bool) {
  105. configTemplate.Execute(wr, map[string]interface{}{
  106. "dir": dir,
  107. "nodes": nodes,
  108. "settings": structToValues(&opts),
  109. "comments": comments,
  110. })
  111. }