mirror of https://github.com/joho/godotenv.git
Compare commits
7 Commits
Author | SHA1 | Date |
---|---|---|
|
3a7a190201 | |
|
a7f6c4c583 | |
|
32e64fa834 | |
|
7765d9d198 | |
|
383d64cb7e | |
|
e3b6eee84d | |
|
193c9aba29 |
|
@ -14,7 +14,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: ${{ matrix.go }}
|
||||||
- run: go test
|
- run: go test
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
# Full line comment
|
# Full line comment
|
||||||
|
qux=thud # fred # other
|
||||||
|
thud=fred#qux # other
|
||||||
|
fred=qux#baz # other # more
|
||||||
foo=bar # baz
|
foo=bar # baz
|
||||||
bar=foo#baz
|
bar=foo#baz
|
||||||
baz="foo"#bar
|
baz="foo"#bar
|
||||||
|
|
|
@ -3,3 +3,4 @@ OPTION_B=${OPTION_A}
|
||||||
OPTION_C=$OPTION_B
|
OPTION_C=$OPTION_B
|
||||||
OPTION_D=${OPTION_A}${OPTION_B}
|
OPTION_D=${OPTION_A}${OPTION_B}
|
||||||
OPTION_E=${OPTION_NOT_DEFINED}
|
OPTION_E=${OPTION_NOT_DEFINED}
|
||||||
|
OPTION_F=${GLOBAL_OPTION}
|
||||||
|
|
|
@ -207,15 +207,21 @@ func TestLoadQuotedEnv(t *testing.T) {
|
||||||
|
|
||||||
func TestSubstitutions(t *testing.T) {
|
func TestSubstitutions(t *testing.T) {
|
||||||
envFileName := "fixtures/substitutions.env"
|
envFileName := "fixtures/substitutions.env"
|
||||||
|
|
||||||
|
presets := map[string]string{
|
||||||
|
"GLOBAL_OPTION": "global",
|
||||||
|
}
|
||||||
|
|
||||||
expectedValues := map[string]string{
|
expectedValues := map[string]string{
|
||||||
"OPTION_A": "1",
|
"OPTION_A": "1",
|
||||||
"OPTION_B": "1",
|
"OPTION_B": "1",
|
||||||
"OPTION_C": "1",
|
"OPTION_C": "1",
|
||||||
"OPTION_D": "11",
|
"OPTION_D": "11",
|
||||||
"OPTION_E": "",
|
"OPTION_E": "",
|
||||||
|
"OPTION_F": "global",
|
||||||
}
|
}
|
||||||
|
|
||||||
loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
loadEnvAndCompareValues(t, Load, envFileName, expectedValues, presets)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpanding(t *testing.T) {
|
func TestExpanding(t *testing.T) {
|
||||||
|
@ -471,9 +477,12 @@ func TestErrorParsing(t *testing.T) {
|
||||||
func TestComments(t *testing.T) {
|
func TestComments(t *testing.T) {
|
||||||
envFileName := "fixtures/comments.env"
|
envFileName := "fixtures/comments.env"
|
||||||
expectedValues := map[string]string{
|
expectedValues := map[string]string{
|
||||||
"foo": "bar",
|
"qux": "thud",
|
||||||
"bar": "foo#baz",
|
"thud": "fred#qux",
|
||||||
"baz": "foo",
|
"fred": "qux#baz",
|
||||||
|
"foo": "bar",
|
||||||
|
"bar": "foo#baz",
|
||||||
|
"baz": "foo",
|
||||||
}
|
}
|
||||||
|
|
||||||
loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
||||||
|
@ -573,3 +582,64 @@ func TestTrailingNewlines(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWhitespace(t *testing.T) {
|
||||||
|
cases := map[string]struct {
|
||||||
|
input string
|
||||||
|
key string
|
||||||
|
value string
|
||||||
|
}{
|
||||||
|
"Leading whitespace": {
|
||||||
|
input: " A=a\n",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"Leading tab": {
|
||||||
|
input: "\tA=a\n",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"Leading mixed whitespace": {
|
||||||
|
input: " \t \t\n\t \t A=a\n",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"Leading whitespace before export": {
|
||||||
|
input: " \t\t export A=a\n",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"Trailing whitespace": {
|
||||||
|
input: "A=a \t \t\n",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"Trailing whitespace with export": {
|
||||||
|
input: "export A=a\t \t \n",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"No EOL": {
|
||||||
|
input: "A=a",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
"Trailing whitespace with no EOL": {
|
||||||
|
input: "A=a ",
|
||||||
|
key: "A",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for n, c := range cases {
|
||||||
|
t.Run(n, func(t *testing.T) {
|
||||||
|
result, err := Unmarshal(c.input)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Input: %q Unexpected error:\t%q", c.input, err)
|
||||||
|
}
|
||||||
|
if result[c.key] != c.value {
|
||||||
|
t.Errorf("Input %q Expected:\t %q/%q\nGot:\t %q", c.input, c.key, c.value, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
13
parser.go
13
parser.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
@ -142,9 +143,9 @@ func extractVarValue(src []byte, vars map[string]string) (value string, rest []b
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work backwards to check if the line ends in whitespace then
|
// Work backwards to check if the line ends in whitespace then
|
||||||
// a comment (ie asdasd # some comment)
|
// a comment, ie: foo=bar # baz # other
|
||||||
for i := endOfVar - 1; i >= 0; i-- {
|
for i := 0; i < endOfVar; i++ {
|
||||||
if line[i] == charComment && i > 0 {
|
if line[i] == charComment && i < endOfVar {
|
||||||
if isSpace(line[i-1]) {
|
if isSpace(line[i-1]) {
|
||||||
endOfVar = i
|
endOfVar = i
|
||||||
break
|
break
|
||||||
|
@ -264,6 +265,12 @@ func expandVariables(v string, m map[string]string) string {
|
||||||
if submatch[1] == "\\" || submatch[2] == "(" {
|
if submatch[1] == "\\" || submatch[2] == "(" {
|
||||||
return submatch[0][1:]
|
return submatch[0][1:]
|
||||||
} else if submatch[4] != "" {
|
} else if submatch[4] != "" {
|
||||||
|
if val, ok := m[submatch[4]]; ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
if val, ok := os.LookupEnv(submatch[4]); ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
return m[submatch[4]]
|
return m[submatch[4]]
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
|
Loading…
Reference in New Issue