diff --git a/README.md b/README.md index a6fb495..f45458b 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,13 @@ myEnv, err := godotenv.Read() s3Bucket := myEnv["S3_BUCKET"] ``` +... or from an `io.Reader` instead of a local file + +```go +reader := getRemoteFile() +myEnv, err := godotenv.Parse(reader) +``` + ### Command Mode Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH` diff --git a/godotenv.go b/godotenv.go index 0d9066c..f44a58d 100644 --- a/godotenv.go +++ b/godotenv.go @@ -16,6 +16,7 @@ package godotenv import ( "bufio" "errors" + "io" "os" "os/exec" "strings" @@ -89,6 +90,34 @@ func Read(filenames ...string) (envMap map[string]string, err error) { return } +// Parse reads an env file from io.Reader, returning a map of keys and values. +func Parse(r io.Reader) (envMap map[string]string, err error) { + envMap = make(map[string]string) + + var lines []string + scanner := bufio.NewScanner(r) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + + if err = scanner.Err(); err != nil { + return + } + + for _, fullLine := range lines { + if !isIgnoredLine(fullLine) { + var key, value string + key, value, err = parseLine(fullLine) + + if err != nil { + return + } + envMap[key] = value + } + } + return +} + // Exec loads env vars from the specified filenames (empty map falls back to default) // then executes the cmd specified. // @@ -142,30 +171,7 @@ func readFile(filename string) (envMap map[string]string, err error) { } defer file.Close() - envMap = make(map[string]string) - - var lines []string - scanner := bufio.NewScanner(file) - for scanner.Scan() { - lines = append(lines, scanner.Text()) - } - - if err = scanner.Err(); err != nil { - return - } - - for _, fullLine := range lines { - if !isIgnoredLine(fullLine) { - var key, value string - key, value, err = parseLine(fullLine) - - if err != nil { - return - } - envMap[key] = value - } - } - return + return Parse(file) } func parseLine(line string) (key string, value string, err error) { diff --git a/godotenv_test.go b/godotenv_test.go index a62bf87..2d46b19 100644 --- a/godotenv_test.go +++ b/godotenv_test.go @@ -1,6 +1,7 @@ package godotenv import ( + "bytes" "os" "testing" ) @@ -94,6 +95,23 @@ func TestReadPlainEnv(t *testing.T) { } } +func TestParse(t *testing.T) { + envMap, err := Parse(bytes.NewReader([]byte("ONE=1\nTWO='2'\nTHREE = \"3\""))) + expectedValues := map[string]string{ + "ONE": "1", + "TWO": "2", + "THREE": "3", + } + if err != nil { + t.Fatalf("error parsing env: %v", err) + } + for key, value := range expectedValues { + if envMap[key] != value { + t.Errorf("expected %s to be %s, got %s", key, value, envMap[key]) + } + } +} + func TestLoadDoesNotOverride(t *testing.T) { envFileName := "fixtures/plain.env"