package config import ( "errors" "fmt" "os" "gopkg.in/yaml.v3" ) type LoadOptions struct { Path string Units string Timezone string Output string } func Load(opts LoadOptions) (Config, error) { cfg := Defaults() path := opts.Path if path == "" { path = DefaultPath } if err := mergeFile(&cfg, path); err != nil { if opts.Path != "" || !errors.Is(err, os.ErrNotExist) { return Config{}, err } } if opts.Units != "" { cfg.WeatherAPI.Units = opts.Units } if opts.Timezone != "" { cfg.WeatherAPI.Timezone = opts.Timezone } if opts.Output != "" { cfg.Reports.OutputDir = opts.Output } if err := Validate(cfg); err != nil { return Config{}, err } return cfg, nil } func LoadFile(path string) (Config, error) { return Load(LoadOptions{Path: path}) } func mergeFile(cfg *Config, path string) error { data, err := os.ReadFile(path) if err != nil { return fmt.Errorf("read config %q: %w", path, err) } if err := yaml.Unmarshal(data, cfg); err != nil { return fmt.Errorf("parse config %q: %w", path, err) } if cfg.MissingSource.Sources == nil { cfg.MissingSource.Sources = map[string]MissingSourcePolicy{} } if cfg.Reports.Paths == nil { cfg.Reports.Paths = map[string]string{} } return nil }