package service import ( "fmt" "os" "time" "git.server.ky/slackcoder/mirror/internal" "github.com/BurntSushi/toml" ) type Duration struct { time.Duration } func (s Duration) MarshalText() ([]byte, error) { return []byte(s.Duration.String()), nil } func (s *Duration) UnmarshalText(text []byte) error { v, err := time.ParseDuration(string(text)) if err != nil { return err } *s = Duration{v} return nil } // Global parameters type GlobalConfig struct { MaxInterval Duration `toml:"max-interval"` MinInterval Duration `toml:"min-interval"` } type Config struct { *GlobalConfig `toml:"global"` Mirrors []*Mirror `toml:"mirrors,omitempty"` } func (c *Config) String() string { return internal.MustTOML(c) } var DefaultConfig = Config{ GlobalConfig: &GlobalConfig{ MaxInterval: Duration{24 * time.Hour}, MinInterval: Duration{time.Hour}, }, } func (c *Config) Apply(src Config) { if c.MaxInterval.Duration == 0 && src.MaxInterval.Duration != 0 { c.MaxInterval = src.MaxInterval } if c.MinInterval.Duration == 0 && src.MinInterval.Duration != 0 { c.MinInterval = src.MinInterval } if len(c.Mirrors) == 0 { c.Mirrors = src.Mirrors } } // ApplyFileConfig loads the configuration described by the given yaml file. func ApplyFileConfig(cfg *Config, filePath string) error { var ret Config f, err := os.Open(filePath) if os.IsNotExist(err) { return nil } else if err != nil { return err } defer f.Close() _, err = toml.NewDecoder(f).Decode(&ret) if err != nil { return fmt.Errorf("loading configuration file: %w", err) } cfg.Apply(ret) return nil }