Skip to content

Commit 6bb0851

Browse files
authored
Merge pull request #47 from sachaos/feature-expand-variables-on-value
Support variable substitution in dotenv files
2 parents 06e67b5 + 2707e9f commit 6bb0851

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

fixtures/substitutions.env

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
OPTION_A=1
2+
OPTION_B=${OPTION_A}
3+
OPTION_C=$OPTION_B
4+
OPTION_D=${OPTION_A}${OPTION_B}
5+
OPTION_E=${OPTION_NOT_DEFINED}

godotenv.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func Parse(r io.Reader) (envMap map[string]string, err error) {
112112
for _, fullLine := range lines {
113113
if !isIgnoredLine(fullLine) {
114114
var key, value string
115-
key, value, err = parseLine(fullLine)
115+
key, value, err = parseLine(fullLine, envMap)
116116

117117
if err != nil {
118118
return
@@ -209,7 +209,7 @@ func readFile(filename string) (envMap map[string]string, err error) {
209209
return Parse(file)
210210
}
211211

212-
func parseLine(line string) (key string, value string, err error) {
212+
func parseLine(line string, envMap map[string]string) (key string, value string, err error) {
213213
if len(line) == 0 {
214214
err = errors.New("zero length string")
215215
return
@@ -259,11 +259,11 @@ func parseLine(line string) (key string, value string, err error) {
259259
key = strings.Trim(key, " ")
260260

261261
// Parse the value
262-
value = parseValue(splitString[1])
262+
value = parseValue(splitString[1], envMap)
263263
return
264264
}
265265

266-
func parseValue(value string) string {
266+
func parseValue(value string, envMap map[string]string) string {
267267

268268
// trim
269269
value = strings.Trim(value, " ")
@@ -291,6 +291,13 @@ func parseValue(value string) string {
291291
}
292292
}
293293

294+
// expand variables
295+
value = os.Expand(value, func(key string) string {
296+
if val, ok := envMap[key]; ok {
297+
return val
298+
}
299+
return ""
300+
})
294301
return value
295302
}
296303

godotenv_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
var noopPresets = make(map[string]string)
1212

1313
func parseAndCompare(t *testing.T, rawEnvLine string, expectedKey string, expectedValue string) {
14-
key, value, _ := parseLine(rawEnvLine)
14+
key, value, _ := parseLine(rawEnvLine, noopPresets)
1515
if key != expectedKey || value != expectedValue {
1616
t.Errorf("Expected '%v' to parse as '%v' => '%v', got '%v' => '%v' instead", rawEnvLine, expectedKey, expectedValue, key, value)
1717
}
@@ -193,6 +193,19 @@ func TestLoadQuotedEnv(t *testing.T) {
193193
loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
194194
}
195195

196+
func TestSubstituitions(t *testing.T) {
197+
envFileName := "fixtures/substitutions.env"
198+
expectedValues := map[string]string{
199+
"OPTION_A": "1",
200+
"OPTION_B": "1",
201+
"OPTION_C": "1",
202+
"OPTION_D": "11",
203+
"OPTION_E": "",
204+
}
205+
206+
loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
207+
}
208+
196209
func TestActualEnvVarsAreLeftAlone(t *testing.T) {
197210
os.Clearenv()
198211
os.Setenv("OPTION_A", "actualenv")
@@ -280,7 +293,7 @@ func TestParsing(t *testing.T) {
280293
// it 'throws an error if line format is incorrect' do
281294
// expect{env('lol$wut')}.to raise_error(Dotenv::FormatError)
282295
badlyFormattedLine := "lol$wut"
283-
_, _, err := parseLine(badlyFormattedLine)
296+
_, _, err := parseLine(badlyFormattedLine, noopPresets)
284297
if err == nil {
285298
t.Errorf("Expected \"%v\" to return error, but it didn't", badlyFormattedLine)
286299
}
@@ -348,7 +361,7 @@ func TestWrite(t *testing.T) {
348361
//but single quotes are left alone
349362
writeAndCompare(`key=va'lu'e`, `key="va'lu'e"`)
350363
// newlines, backslashes, and some other special chars are escaped
351-
writeAndCompare(`foo="$ba\n\r\\r!"`, `foo="\$ba\n\r\\r\!"`)
364+
writeAndCompare(`foo="\n\r\\r!"`, `foo="\n\r\\r\!"`)
352365
// lines should be sorted
353366
writeAndCompare("foo=bar\nbaz=buzz", "baz=\"buzz\"\nfoo=\"bar\"")
354367

0 commit comments

Comments
 (0)