Skip to content

Commit faf711c

Browse files
committed
Multiline following spec from ruby
1 parent c7ddf64 commit faf711c

File tree

5 files changed

+33
-40
lines changed

5 files changed

+33
-40
lines changed

fixtures/invalid2.env

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
INVALID_MULTILINE='bar
1+
INVALID_MULTILINE="bar
22
ASDFASDF
3-
VALID_MULTILINE='ASDFASDFADF
4-
ASDFASDFASDFADF'
3+
VALID_MULTILINE=ASDFASDFADF

fixtures/invalid3.env

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
INVALID_MULTILINE='bar
1+
INVALID_MULTILINE="bar
22
ASDFASDF

fixtures/multiline.env

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
SINGLE_LINE=Single Line Value
2-
MULTI_LINE='This is a
3-
multiline value
4-
should be properly parsed'
2+
MULTI_LINE="This is a
3+
multiline value = not breaking the line
4+
should be properly parsed"
55
SINGLE_LINE_2="Another single line"

godotenv.go

+24-30
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,6 @@ func Parse(r io.Reader) (envMap map[string]string, err error) {
121121
return
122122
}
123123

124-
// Previous multi-line value was not closed. We shouldn't find new keys until closing the multi-line value
125-
if isMultilineValue && len(multilineKey) > 0 && len(key) > 0 {
126-
err = fmt.Errorf("Multiline value for key %s reached key %s without closing the single quotes", multilineKey, key)
127-
return
128-
}
129-
130124
if multilineValue == true && isMultilineValue == false && len(key) <= 0 {
131125
// We are on a multi-line; but last line closed the multi-line single quote
132126
value = fmt.Sprintf("%s\n%s", buffer, value)
@@ -282,44 +276,44 @@ func parseLine(line string, envMap map[string]string, isMultiline bool) (key str
282276
multilineValue = quotesAreOpen
283277
}
284278

285-
firstEquals := strings.Index(line, "=")
286-
firstColon := strings.Index(line, ":")
287-
splitString := strings.SplitN(line, "=", 2)
288-
if firstColon != -1 && (firstColon < firstEquals || firstEquals == -1) {
289-
//this is a yaml-style line
290-
splitString = strings.SplitN(line, ":", 2)
291-
}
279+
if !isMultiline {
280+
firstEquals := strings.Index(line, "=")
281+
firstColon := strings.Index(line, ":")
282+
splitString := strings.SplitN(line, "=", 2)
283+
if firstColon != -1 && (firstColon < firstEquals || firstEquals == -1) {
284+
//this is a yaml-style line
285+
splitString = strings.SplitN(line, ":", 2)
286+
}
292287

293-
// Only check key, value pair if is not a multi-line value
294-
if isMultiline == false && len(splitString) != 2 {
295-
err = errors.New("Can't separate key from value")
296-
return
297-
}
288+
// Only check key, value pair if is not a multi-line value
289+
if isMultiline == false && len(splitString) != 2 {
290+
err = errors.New("Can't separate key from value")
291+
return
292+
}
298293

299-
if len(splitString) == 2 {
300-
// Parse the key
301-
key = splitString[0]
302-
if strings.HasPrefix(key, "export") {
303-
key = strings.TrimPrefix(key, "export")
294+
if len(splitString) == 2 {
295+
// Parse the key
296+
key = splitString[0]
297+
if strings.HasPrefix(key, "export") {
298+
key = strings.TrimPrefix(key, "export")
299+
}
300+
key = strings.Trim(key, " ")
304301
}
305-
key = strings.Trim(key, " ")
306-
}
307302

308-
if !isMultiline {
309303
// Parse the value
310304
value = parseValue(splitString[1], envMap)
311305
if len(value) <= 0 {
312306
return
313307
}
314308

315-
// Multi-line delimiting character is a single quote '
316-
if multilineValue = (value[0:1] == "'" && value[len(value)-1:] != "'"); multilineValue == true {
309+
// Multi-line delimiting character is a double quote "
310+
if multilineValue = (value[0:1] == "\"" && value[len(value)-1:] != "\""); multilineValue == true {
317311
value = value[1:len(value)]
318312
}
319313
} else {
320-
value = parseValue(splitString[0], envMap)
314+
value = parseValue(line, envMap)
321315
// Check if we reached the end of the multi-line value
322-
multilineValue = value[len(value)-1:] != "'"
316+
multilineValue = value[len(value)-1:] != "\""
323317
}
324318

325319
return

godotenv_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func loadEnvAndCompareValues(t *testing.T, loader func(files ...string) error, e
2828

2929
err := loader(envFileName)
3030
if err != nil {
31-
t.Fatalf("Error loading %v", envFileName)
31+
t.Fatalf("Error loading %v. +%v", envFileName, err)
3232
}
3333

3434
for k := range expectedValues {
@@ -199,7 +199,7 @@ func TestMultilineEnv(t *testing.T) {
199199
expectedValues := map[string]string{
200200
"SINGLE_LINE": "Single Line Value",
201201
"MULTI_LINE": `This is a
202-
multiline value
202+
multiline value = not breaking the line
203203
should be properly parsed`,
204204
"SINGLE_LINE_2": "Another single line",
205205
}
@@ -366,7 +366,7 @@ func TestParsing(t *testing.T) {
366366

367367
parseAndCompare(t, `="value"`, "", "value")
368368
parseAndCompare(t, `KEY="`, "KEY", "\"")
369-
parseAndCompare(t, `KEY="value`, "KEY", "\"value")
369+
parseAndCompare(t, `KEY="value`, "KEY", "value")
370370

371371
// it 'throws an error if line format is incorrect' do
372372
// expect{env('lol$wut')}.to raise_error(Dotenv::FormatError)

0 commit comments

Comments
 (0)