From d97b5f3080bfff4a5ddd3d22930c3465c9c8fdba Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Tue, 11 Jan 2022 14:02:06 +0100 Subject: [PATCH] Handle inline comments on unquoted values Signed-off-by: Ulysses Souza --- fixtures/plain.env | 3 ++- fixtures/quoted.env | 2 +- godotenv_test.go | 17 +++++++++-------- parser.go | 10 +++++----- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/fixtures/plain.env b/fixtures/plain.env index 43f7e44..430914d 100644 --- a/fixtures/plain.env +++ b/fixtures/plain.env @@ -4,4 +4,5 @@ OPTION_C= 3 OPTION_D =4 OPTION_E = 5 OPTION_F = -OPTION_G= \ No newline at end of file +OPTION_G= +OPTION_H = my string # Inline comment diff --git a/fixtures/quoted.env b/fixtures/quoted.env index 7c4c19c..2f05d19 100644 --- a/fixtures/quoted.env +++ b/fixtures/quoted.env @@ -6,7 +6,7 @@ OPTION_E="1" OPTION_F="2" OPTION_G="" OPTION_H="\n" -OPTION_I = "echo 'asd'" +OPTION_I = "echo 'asd'" # Inline comment OPTION_J = 'first line second line third line diff --git a/godotenv_test.go b/godotenv_test.go index ad46519..97435ed 100644 --- a/godotenv_test.go +++ b/godotenv_test.go @@ -80,6 +80,7 @@ func TestReadPlainEnv(t *testing.T) { "OPTION_E": "5", "OPTION_F": "", "OPTION_G": "", + "OPTION_H": "my string", } envMap, err := Read(envFileName) @@ -93,7 +94,7 @@ func TestReadPlainEnv(t *testing.T) { for key, value := range expectedValues { if envMap[key] != value { - t.Error("Read got one of the keys wrong") + t.Errorf("Read got one of the keys wrong. Expected: %q got %q", value, envMap[key]) } } } @@ -350,7 +351,7 @@ func TestParsing(t *testing.T) { // parses yaml style options parseAndCompare(t, "OPTION_A: 1", "OPTION_A", "1") - //parses yaml values with equal signs + // parses yaml values with equal signs parseAndCompare(t, "OPTION_A: Foo=bar", "OPTION_A", "Foo=bar") // parses non-yaml options with colons @@ -399,7 +400,7 @@ func TestParsing(t *testing.T) { parseAndCompare(t, `FOO="ba#r"`, "FOO", "ba#r") parseAndCompare(t, "FOO='ba#r'", "FOO", "ba#r") - //newlines and backslashes should be escaped + // newlines and backslashes should be escaped parseAndCompare(t, `FOO="bar\n\ b\az"`, "FOO", "bar\n baz") parseAndCompare(t, `FOO="bar\\\n\ b\az"`, "FOO", "bar\\\n baz") parseAndCompare(t, `FOO="bar\\r\ b\az"`, "FOO", "bar\\r baz") @@ -483,14 +484,14 @@ func TestWrite(t *testing.T) { t.Errorf("Expected '%v' (%v) to write as '%v', got '%v' instead.", env, envMap, expected, actual) } } - //just test some single lines to show the general idea - //TestRoundtrip makes most of the good assertions + // just test some single lines to show the general idea + // TestRoundtrip makes most of the good assertions - //values are always double-quoted + // values are always double-quoted writeAndCompare(`key=value`, `key="value"`) - //double-quotes are escaped + // double-quotes are escaped writeAndCompare(`key=va"lu"e`, `key="va\"lu\"e"`) - //but single quotes are left alone + // but single quotes are left alone writeAndCompare(`key=va'lu'e`, `key="va'lu'e"`) // newlines, backslashes, and some other special chars are escaped writeAndCompare(`foo="\n\r\\r!"`, `foo="\n\r\\r\!"`) diff --git a/parser.go b/parser.go index 1d144de..8339cb6 100644 --- a/parser.go +++ b/parser.go @@ -132,14 +132,15 @@ func extractVarValue(src []byte, envMap map[string]string, lookupFn LookupFn) (v // unquoted value - read until new line end := bytes.IndexFunc(src, isNewLine) var rest []byte - var value string + if end < 0 { - value := strings.TrimRightFunc(string(src), unicode.IsSpace) + value := strings.Split(string(src), "#")[0] // Remove inline comments on unquoted lines + value = strings.TrimRightFunc(value, unicode.IsSpace) rest = nil return expandVariables(value, envMap, lookupFn), rest, nil } - - value = strings.TrimRightFunc(string(src[0:end]), unicode.IsSpace) + value := strings.Split(string(src[0:end]), "#")[0] + value = strings.TrimRightFunc(value, unicode.IsSpace) rest = src[end:] return expandVariables(value, envMap, lookupFn), rest, nil } @@ -228,7 +229,6 @@ func isSpace(r rune) bool { return false } - // isNewLine reports whether the rune is a new line character func isNewLine(r rune) bool { return r == '\n'