Merge pull request #34 from alexquick/fix-parsing-issues

Fix some small parsing bugs
This commit is contained in:
John Barton 2017-08-22 14:21:26 +10:00 committed by GitHub
commit c9360df4d1
2 changed files with 45 additions and 14 deletions

View File

@ -19,6 +19,7 @@ import (
"io" "io"
"os" "os"
"os/exec" "os/exec"
"regexp"
"strings" "strings"
) )
@ -203,11 +204,11 @@ func parseLine(line string) (key string, value string, err error) {
line = strings.Join(segmentsToKeep, "#") line = strings.Join(segmentsToKeep, "#")
} }
// now split key from value firstEquals := strings.Index(line, "=")
firstColon := strings.Index(line, ":")
splitString := strings.SplitN(line, "=", 2) splitString := strings.SplitN(line, "=", 2)
if firstColon != -1 && (firstColon < firstEquals || firstEquals == -1) {
if len(splitString) != 2 { //this is a yaml-style line
// try yaml mode!
splitString = strings.SplitN(line, ":", 2) splitString = strings.SplitN(line, ":", 2)
} }
@ -224,27 +225,39 @@ func parseLine(line string) (key string, value string, err error) {
key = strings.Trim(key, " ") key = strings.Trim(key, " ")
// Parse the value // Parse the value
value = splitString[1] value = parseValue(splitString[1])
return
}
func parseValue(value string) string {
// trim // trim
value = strings.Trim(value, " ") value = strings.Trim(value, " ")
// check if we've got quoted values // check if we've got quoted values or possible escapes
if value != "" { if len(value) > 1 {
first := string(value[0:1]) first := string(value[0:1])
last := string(value[len(value)-1:]) last := string(value[len(value)-1:])
if first == last && strings.ContainsAny(first, `"'`) { if first == last && strings.ContainsAny(first, `"'`) {
// pull the quotes off the edges // pull the quotes off the edges
value = strings.Trim(value, `"'`) value = value[1 : len(value)-1]
// handle escapes
// expand quotes escapeRegex := regexp.MustCompile(`\\.`)
value = strings.Replace(value, `\"`, `"`, -1) value = escapeRegex.ReplaceAllStringFunc(value, func(match string) string {
// expand newlines c := strings.TrimPrefix(match, `\`)
value = strings.Replace(value, `\n`, "\n", -1) switch c {
case "n":
return "\n"
case "r":
return "\r"
default:
return c
}
})
} }
} }
return return value
} }
func isIgnoredLine(line string) bool { func isIgnoredLine(line string) bool {

View File

@ -217,9 +217,18 @@ func TestParsing(t *testing.T) {
// parses escaped double quotes // parses escaped double quotes
parseAndCompare(t, `FOO="escaped\"bar"`, "FOO", `escaped"bar`) parseAndCompare(t, `FOO="escaped\"bar"`, "FOO", `escaped"bar`)
// parses single quotes inside double quotes
parseAndCompare(t, `FOO="'d'"`, "FOO", `'d'`)
// parses yaml style options // parses yaml style options
parseAndCompare(t, "OPTION_A: 1", "OPTION_A", "1") parseAndCompare(t, "OPTION_A: 1", "OPTION_A", "1")
//parses yaml values with equal signs
parseAndCompare(t, "OPTION_A: Foo=bar", "OPTION_A", "Foo=bar")
// parses non-yaml options with colons
parseAndCompare(t, "OPTION_A=1:B", "OPTION_A", "1:B")
// parses export keyword // parses export keyword
parseAndCompare(t, "export OPTION_A=2", "OPTION_A", "2") parseAndCompare(t, "export OPTION_A=2", "OPTION_A", "2")
parseAndCompare(t, `export OPTION_B='\n'`, "OPTION_B", "\n") parseAndCompare(t, `export OPTION_B='\n'`, "OPTION_B", "\n")
@ -256,6 +265,15 @@ func TestParsing(t *testing.T) {
parseAndCompare(t, `FOO="ba#r"`, "FOO", "ba#r") parseAndCompare(t, `FOO="ba#r"`, "FOO", "ba#r")
parseAndCompare(t, "FOO='ba#r'", "FOO", "ba#r") parseAndCompare(t, "FOO='ba#r'", "FOO", "ba#r")
//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")
parseAndCompare(t, `="value"`, "", "value")
parseAndCompare(t, `KEY="`, "KEY", "\"")
parseAndCompare(t, `KEY="value`, "KEY", "\"value")
// it 'throws an error if line format is incorrect' do // it 'throws an error if line format is incorrect' do
// expect{env('lol$wut')}.to raise_error(Dotenv::FormatError) // expect{env('lol$wut')}.to raise_error(Dotenv::FormatError)
badlyFormattedLine := "lol$wut" badlyFormattedLine := "lol$wut"