-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparseoption.go
162 lines (133 loc) · 3.15 KB
/
parseoption.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package flag2
import (
"encoding/json"
"errors"
"io/ioutil"
"os"
"strings"
)
// ErrNoValue is the error returned if the config file doesn't contain a value
// for the requested flag
var ErrNoValue = errors.New("flag: help requested")
// ParseOption is a hook that allows mixins to update a FlagSet after command line
// args are parsed, but before envvar and config file.
type ParseOption func(*FlagSet) error
// JSONFileVia will set the config file based on the value of the given flag
func JSONFileVia(flagName string) ParseOption {
return func(f *FlagSet) error {
if f.configFile != nil {
return f.failf("error handling %v flag, config file already set", flagName)
}
flag := f.Lookup(flagName)
f.configFile = &jsonConfigFile{
fs: f,
fileNameFlag: flag,
}
return nil
}
}
type jsonConfigFile struct {
fs *FlagSet
fileNameFlag *Flag
file *os.File
data map[string]string
}
func (j *jsonConfigFile) FileName() string {
return j.fileNameFlag.Value.String()
}
func (j *jsonConfigFile) ConfigValue(name string) (string, error) {
if j.data == nil {
return "", ErrNoValue
}
value, ok := j.data[name]
if !ok {
return "", ErrNoValue
}
return value, nil
}
func (j *jsonConfigFile) Open() error {
if j.file != nil {
return nil
}
// open the file
fileName := j.FileName()
if fileName == "" {
// no file, no values
return nil
}
file, err := os.Open(fileName)
if err != nil {
return err
}
j.file = file
bytes, err := ioutil.ReadAll(j.file)
if err != nil {
return err
}
if err := json.Unmarshal(bytes, &j.data); err != nil {
return err
}
return nil
}
func (j *jsonConfigFile) Close() {
if j.file != nil {
j.file.Close()
}
}
// AddEnvPrefix will prepend all flag Env names with a given prefix
func AddEnvPrefix(prefix string) ParseOption {
return func(f *FlagSet) error {
f.VisitAll(func(flag *Flag) {
if flag.NameInEnv != "" {
flag.NameInEnv = prefix + flag.NameInEnv
}
})
return nil
}
}
// UseDefaultNamesInConfigFile will allow every flag to be found in the Config file
func UseDefaultNamesInConfigFile() ParseOption {
return func(f *FlagSet) error {
f.VisitAll(func(flag *Flag) {
if flag.NameInConfigFile == "" {
flag.NameInConfigFile = flag.Name
}
})
return nil
}
}
// UseDefaultNamesInEnvVars will allow every flag to be found in the EnvVars
func UseDefaultNamesInEnvVars() ParseOption {
return func(f *FlagSet) error {
f.VisitAll(func(flag *Flag) {
if flag.NameInEnv == "" {
flag.NameInEnv = strings.ToUpper(flag.Name)
}
})
return nil
}
}
// InMemoryConfig will set the config file data to a given map of data
func InMemoryConfig(data map[string]string) ParseOption {
return func(f *FlagSet) error {
f.configFile = &memoryConfigFile{data: data}
return nil
}
}
type memoryConfigFile struct {
data map[string]string
}
func (m *memoryConfigFile) ConfigValue(name string) (string, error) {
val, found := m.data[name]
if !found {
return "", ErrNoValue
}
return val, nil
}
func (m *memoryConfigFile) FileName() string {
return "in memory"
}
func (m *memoryConfigFile) Open() error {
return nil
}
func (m *memoryConfigFile) Close() {}