-
Notifications
You must be signed in to change notification settings - Fork 16
/
dotenv.go
206 lines (170 loc) · 3.69 KB
/
dotenv.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// Package dotenv provide load .env data to os ENV
package dotenv
import (
"bufio"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/gookit/ini/v2/parser"
)
var (
// UpperEnvKey change key to upper on set ENV
UpperEnvKey = true
// DefaultName default file name
DefaultName = ".env"
// OnlyLoadExists only load on file exists
OnlyLoadExists bool
// save original Env data
// originalEnv []string
// cache all loaded ENV data
loadedData = map[string]string{}
)
// LoadedData get all loaded data by dontenv
func LoadedData() map[string]string {
return loadedData
}
// Reset clear the previously set ENV value
func Reset() { ClearLoaded() }
// ClearLoaded clear the previously set ENV value
func ClearLoaded() {
for key := range loadedData {
_ = os.Unsetenv(key)
}
// reset
loadedData = map[string]string{}
}
// DontUpperEnvKey don't change key to upper on set ENV
func DontUpperEnvKey() {
UpperEnvKey = false
}
// Load parse .env file data to os ENV.
//
// Usage:
//
// dotenv.Load("./", ".env")
func Load(dir string, filenames ...string) (err error) {
if len(filenames) == 0 {
filenames = []string{DefaultName}
}
for _, filename := range filenames {
file := filepath.Join(dir, filename)
if err = loadFile(file); err != nil {
break
}
}
return
}
// LoadExists only load on file exists
func LoadExists(dir string, filenames ...string) error {
oldVal := OnlyLoadExists
OnlyLoadExists = true
err := Load(dir, filenames...)
OnlyLoadExists = oldVal
return err
}
// LoadFiles load ENV from given file
func LoadFiles(filePaths ...string) (err error) {
for _, filePath := range filePaths {
if err = loadFile(filePath); err != nil {
break
}
}
return
}
// LoadExistFiles load ENV from given files, only load exists
func LoadExistFiles(filePaths ...string) error {
oldVal := OnlyLoadExists
defer func() {
OnlyLoadExists = oldVal
}()
OnlyLoadExists = true
return LoadFiles(filePaths...)
}
// LoadFromMap load data from given string map
func LoadFromMap(kv map[string]string) (err error) {
for key, val := range kv {
if UpperEnvKey {
key = strings.ToUpper(key)
}
err = os.Setenv(key, val)
if err != nil {
break
}
// cache it
loadedData[key] = val
}
return
}
// Get get os ENV value by name
func Get(name string, defVal ...string) (val string) {
if val, ok := getVal(name); ok {
return val
}
if len(defVal) > 0 {
val = defVal[0]
}
return
}
// Bool get a bool value by key
func Bool(name string, defVal ...bool) (val bool) {
if str, ok := getVal(name); ok {
val, err := strconv.ParseBool(str)
if err == nil {
return val
}
}
if len(defVal) > 0 {
val = defVal[0]
}
return
}
// Int get a int value by key
func Int(name string, defVal ...int) (val int) {
if str, ok := getVal(name); ok {
val, err := strconv.ParseInt(str, 10, 0)
if err == nil {
return int(val)
}
}
if len(defVal) > 0 {
val = defVal[0]
}
return
}
func getVal(name string) (val string, ok bool) {
if UpperEnvKey {
name = strings.ToUpper(name)
}
// cached
if val = loadedData[name]; val != "" {
ok = true
return
}
// NOTICE: if is windows OS, os.Getenv() Key is not case-sensitive
return os.LookupEnv(name)
}
// load and parse .env file data to os ENV
func loadFile(file string) (err error) {
fd, err := os.Open(file)
if err != nil {
if OnlyLoadExists && os.IsNotExist(err) {
return nil
}
return err
}
//noinspection GoUnhandledErrorResult
defer fd.Close()
// parse file contents
p := parser.NewLite(func(opt *parser.Options) {
opt.InlineComment = true
})
if _, err = p.ParseFrom(bufio.NewScanner(fd)); err != nil {
return
}
// set data to os ENV
if mp := p.LiteSection(p.DefSection); len(mp) > 0 {
err = LoadFromMap(mp)
}
return
}