-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile.go
101 lines (84 loc) · 2.36 KB
/
file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package cli
import (
"encoding/json"
"github.com/BurntSushi/toml"
"github.com/ghodss/yaml"
"io/ioutil"
"os"
)
// DefaultYAML contains the most common configuration
// for loading options from a YAML config file.
var DefaultYAML = FileOpts{
Paths: []string{"config.yaml", "config.yml"},
OptKey: []string{"config"},
}
// DefaultJSON contains the most common configuration
// for loading options from a JSON config file.
var DefaultJSON = FileOpts{
Paths: []string{"config.json"},
OptKey: []string{"config"},
}
// DefaultTOML contains the most common configuration
// for loading options from a TOML config file.
var DefaultTOML = FileOpts{
Paths: []string{"config.toml"},
OptKey: []string{"config"},
}
// FileOpts describes options related to loading
// options from a file.
type FileOpts struct {
// Paths is a list of paths to look for a config file.
// Environment variables will be expanded using `os.ExpandEnv`.
// Loading will stop on the first path that exists.
Paths []string
// OptKey is used to look for a config file path set by
// an option (e.g. by a flag or env. var). For example,
// an OptKey of ["config", "file"] could load the config
// file from a "--config.file" flag. OptKey is prepended
// to the Paths list, so it takes priority.
OptKey []string
}
// YAML loads options from a YAML file.
func YAML(opts FileOpts) Provider {
return &fileProvider{opts, unmarshalYAML}
}
// JSON loads options from a JSON file.
func JSON(opts FileOpts) Provider {
return &fileProvider{opts, json.Unmarshal}
}
// TOML loads options from a TOML file.
func TOML(opts FileOpts) Provider {
return &fileProvider{opts, toml.Unmarshal}
}
type fileProvider struct {
opts FileOpts
unm unmarshaler
}
func (f *fileProvider) Provide(l *Loader) error {
optKey := f.opts.OptKey
paths := f.opts.Paths
opt := l.GetString(optKey)
paths = append([]string{opt}, paths...)
for _, path := range paths {
path := os.ExpandEnv(path)
if path == "" || !exists(path) {
continue
}
b, err := ioutil.ReadFile(path)
if err != nil {
return err
}
data := map[string]interface{}{}
err = f.unm(b, &data)
if err != nil {
return err
}
flatten2(data, l, nil)
}
return nil
}
// wrap yaml.Unmarshal because they changed the interface.
func unmarshalYAML(b []byte, i interface{}) error {
return yaml.Unmarshal(b, i)
}
type unmarshaler func([]byte, interface{}) error