Repository: compose-spec/compose-go
Pull request #217 (2022-01-12 13:33:25)

Handle inline comments on unquoted values


Patch:
diff --git a/dotenv/fixtures/plain.env b/dotenv/fixtures/plain.env
index 43f7e44..430914d 100644
--- a/dotenv/fixtures/plain.env
+++ b/dotenv/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/dotenv/fixtures/quoted.env b/dotenv/fixtures/quoted.env
index 7c4c19c..2f05d19 100644
--- a/dotenv/fixtures/quoted.env
+++ b/dotenv/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/dotenv/parser.go b/dotenv/parser.go
index e657c8d..cbba8d1 100644
--- a/dotenv/parser.go
+++ b/dotenv/parser.go
@@ -132,14 +132,14 @@ 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)
-			rest = nil
-			return expandVariables(value, envMap, lookupFn), rest, nil
+			value := strings.Split(string(src), "#")[0] // Remove inline comments on unquoted lines
+			value = strings.TrimRightFunc(value, unicode.IsSpace)
+			return expandVariables(value, envMap, lookupFn), nil, 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
 	}


Test patch:
diff --git a/dotenv/godotenv_test.go b/dotenv/godotenv_test.go
index 7fa718f..51bd8b7 100644
--- a/dotenv/godotenv_test.go
+++ b/dotenv/godotenv_test.go
@@ -79,6 +79,7 @@ func TestReadPlainEnv(t *testing.T) {
 		"OPTION_E": "5",
 		"OPTION_F": "",
 		"OPTION_G": "",
+		"OPTION_H": "my string",
 	}
 
 	envMap, err := Read(envFileName)
@@ -92,7 +93,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])
 		}
 	}
 }
@@ -349,7 +350,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
@@ -398,7 +399,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")
@@ -482,14 +483,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\!"`)