From 0682cbb9353e8f70fb2bf3f7a6c9f7d1345afda5 Mon Sep 17 00:00:00 2001 From: Energy Star Date: Wed, 28 Sep 2022 20:55:05 -0700 Subject: [PATCH 1/2] Allows to prefix exported env vars --- godotenv.go | 44 ++++++++++++++++++++++++++++++++++++++++---- godotenv_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/godotenv.go b/godotenv.go index 975d7bc..34edcc7 100644 --- a/godotenv.go +++ b/godotenv.go @@ -40,10 +40,26 @@ const doubleQuoteSpecialChars = "\\\n\r\"!$`" // // It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults func Load(filenames ...string) (err error) { + return LoadWithPrefix("", filenames...) +} + +// LoadWithPrefix will read your env file(s) and load them into ENV for this +// process. It allows you to specify a prefix for the env variables. +// +// Call this function as close as possible to the start of your program (ideally in main) +// +// If you call Load without any args it will default to loading .env in the current path +// +// You can otherwise tell it which files to load (there can be more than one) like +// +// godotenv.Load("fileone", "filetwo") +// +// It's important to note that it WILL NOT OVERRIDE an env variable that already exists - consider the .env file to set dev vars or sensible defaults +func LoadWithPrefix(prefix string, filenames ...string) (err error) { filenames = filenamesOrDefault(filenames) for _, filename := range filenames { - err = loadFile(filename, false) + err = loadFileWithPrefix(prefix, filename, false) if err != nil { return // return early on a spazout } @@ -63,10 +79,26 @@ func Load(filenames ...string) (err error) { // // It's important to note this WILL OVERRIDE an env variable that already exists - consider the .env file to forcefully set all vars. func Overload(filenames ...string) (err error) { + return OverloadWithPrefix("", filenames...) +} + +// OverloadWithPrefix will read your env file(s) and load them into ENV for this +// process. It allows you to specify a prefix for the env variables. +// +// Call this function as close as possible to the start of your program (ideally in main) +// +// If you call Overload without any args it will default to loading .env in the current path +// +// You can otherwise tell it which files to load (there can be more than one) like +// +// godotenv.Overload("fileone", "filetwo") +// +// It's important to note this WILL OVERRIDE an env variable that already exists - consider the .env file to forcefully set all vars. +func OverloadWithPrefix(prefix string, filenames ...string) (err error) { filenames = filenamesOrDefault(filenames) for _, filename := range filenames { - err = loadFile(filename, true) + err = loadFileWithPrefix(prefix, filename, true) if err != nil { return // return early on a spazout } @@ -124,7 +156,7 @@ func Parse(r io.Reader) (envMap map[string]string, err error) { return } -//Unmarshal reads an env file from a string, returning a map of keys and values. +// Unmarshal reads an env file from a string, returning a map of keys and values. func Unmarshal(str string) (envMap map[string]string, err error) { return Parse(strings.NewReader(str)) } @@ -188,6 +220,10 @@ func filenamesOrDefault(filenames []string) []string { } func loadFile(filename string, overload bool) error { + return loadFileWithPrefix("", filename, overload) +} + +func loadFileWithPrefix(prefix, filename string, overload bool) error { envMap, err := readFile(filename) if err != nil { return err @@ -202,7 +238,7 @@ func loadFile(filename string, overload bool) error { for key, value := range envMap { if !currentEnv[key] || overload { - os.Setenv(key, value) + os.Setenv(fmt.Sprintf("%s%s", prefix, key), value) } } diff --git a/godotenv_test.go b/godotenv_test.go index 49f6fe0..d884e48 100644 --- a/godotenv_test.go +++ b/godotenv_test.go @@ -177,6 +177,36 @@ func TestLoadEqualsEnv(t *testing.T) { loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets) } +func TestLoadEqualsEnvPrefix(t *testing.T) { + os.Unsetenv("OPTION_A") + + envFileName := "fixtures/equals.env" + expectedValues := "postgres://localhost:5432/database?sslmode=disable" + prefix := "TEXTPREFIX_" + + LoadWithPrefix(prefix, envFileName) + + if os.Getenv(fmt.Sprintf("%sOPTION_A", prefix)) != expectedValues { + t.Errorf("Expected %s got %s", expectedValues, os.Getenv(fmt.Sprintf("%sOPTION_A", prefix))) + } +} + +func TestLoadEqualsEnvEmptyPrefix(t *testing.T) { + envFileName := "fixtures/equals.env" + expectedValues := "postgres://localhost:5432/database?sslmode=disable" + prefix := "" + + LoadWithPrefix(prefix, envFileName) + + if os.Getenv(fmt.Sprintf("%sOPTION_A", prefix)) != expectedValues { + t.Errorf("Expected %s got %s", expectedValues, os.Getenv(fmt.Sprintf("%sOPTION_A", prefix))) + } + + if os.Getenv("OPTION_A") != expectedValues { + t.Errorf("Expected %s got %s", expectedValues, os.Getenv("OPTION_A")) + } +} + func TestLoadQuotedEnv(t *testing.T) { envFileName := "fixtures/quoted.env" expectedValues := map[string]string{ From c3bc30b445bab200bd701c022f267552106a60d1 Mon Sep 17 00:00:00 2001 From: Energy Star Date: Wed, 28 Sep 2022 21:37:23 -0700 Subject: [PATCH 2/2] rename go mod so I can import it --- README.md | 18 ++++---- autoload/autoload.go | 4 +- cmd/godotenv/cmd.go | 2 +- coverage.out | 103 +++++++++++++++++++++++++++++++++++++++++++ go.mod | 4 +- godotenv.go | 2 +- 6 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 coverage.out diff --git a/README.md b/README.md index 0f170cb..1919450 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GoDotEnv ![CI](https://github.com/joho/godotenv/workflows/CI/badge.svg) [![Go Report Card](https://goreportcard.com/badge/github.com/joho/godotenv)](https://goreportcard.com/report/github.com/joho/godotenv) +# GoDotEnv ![CI](https://github.com/thalesfsp/godotenv/workflows/CI/badge.svg) [![Go Report Card](https://goreportcard.com/badge/github.com/thalesfsp/godotenv)](https://goreportcard.com/report/github.com/thalesfsp/godotenv) A Go (golang) port of the Ruby [dotenv](https://github.com/bkeepers/dotenv) project (which loads env vars from a .env file). @@ -17,19 +17,19 @@ There is test coverage and CI for both linuxish and Windows environments, but I As a library ```shell -go get github.com/joho/godotenv +go get github.com/thalesfsp/godotenv ``` or if you want to use it as a bin command go >= 1.17 ```shell -go install github.com/joho/godotenv/cmd/godotenv@latest +go install github.com/thalesfsp/godotenv/cmd/godotenv@latest ``` go < 1.17 ```shell -go get github.com/joho/godotenv/cmd/godotenv +go get github.com/thalesfsp/godotenv/cmd/godotenv ``` ## Usage @@ -50,7 +50,7 @@ import ( "log" "os" - "github.com/joho/godotenv" + "github.com/thalesfsp/godotenv" ) func main() { @@ -69,7 +69,7 @@ func main() { If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import ```go -import _ "github.com/joho/godotenv/autoload" +import _ "github.com/thalesfsp/godotenv/autoload" ``` While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit @@ -173,7 +173,7 @@ content, err := godotenv.Marshal(env) Contributions are welcome, but with some caveats. -This library has been declared feature complete (see [#182](https://github.com/joho/godotenv/issues/182) for background) and will not be accepting issues or pull requests adding new functionality or breaking the library API. +This library has been declared feature complete (see [#182](https://github.com/thalesfsp/godotenv/issues/182) for background) and will not be accepting issues or pull requests adding new functionality or breaking the library API. Contributions would be gladly accepted that: @@ -193,8 +193,10 @@ Contributions would be gladly accepted that: Releases should follow [Semver](http://semver.org/) though the first couple of releases are `v1` and `v1.1`. -Use [annotated tags for all releases](https://github.com/joho/godotenv/issues/30). Example `git tag -a v1.2.1` +Use [annotated tags for all releases](https://github.com/thalesfsp/godotenv/issues/30). Example `git tag -a v1.2.1` ## Who? The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](https://johnbarton.co/) based off the tests/fixtures in the original library. + +This is the work of John Barton, with addition to allow to specify a prefix for the exported env vars. diff --git a/autoload/autoload.go b/autoload/autoload.go index fbcd2bd..332eacf 100644 --- a/autoload/autoload.go +++ b/autoload/autoload.go @@ -3,12 +3,12 @@ package autoload /* You can just read the .env file on import just by doing - import _ "github.com/joho/godotenv/autoload" + import _ "github.com/thalesfsp/godotenv/autoload" And bob's your mother's brother */ -import "github.com/joho/godotenv" +import "github.com/thalesfsp/godotenv" func init() { godotenv.Load() diff --git a/cmd/godotenv/cmd.go b/cmd/godotenv/cmd.go index 8dce420..7d91f1b 100644 --- a/cmd/godotenv/cmd.go +++ b/cmd/godotenv/cmd.go @@ -7,7 +7,7 @@ import ( "strings" - "github.com/joho/godotenv" + "github.com/thalesfsp/godotenv" ) func main() { diff --git a/coverage.out b/coverage.out new file mode 100644 index 0000000..edec359 --- /dev/null +++ b/coverage.out @@ -0,0 +1,103 @@ +mode: set +github.com/thalesfsp/godotenv/godotenv.go:42.44,44.2 1 1 +github.com/thalesfsp/godotenv/godotenv.go:58.69,61.37 2 1 +github.com/thalesfsp/godotenv/godotenv.go:67.2,67.8 1 1 +github.com/thalesfsp/godotenv/godotenv.go:61.37,63.17 2 1 +github.com/thalesfsp/godotenv/godotenv.go:63.17,65.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:81.48,83.2 1 1 +github.com/thalesfsp/godotenv/godotenv.go:97.73,100.37 2 1 +github.com/thalesfsp/godotenv/godotenv.go:106.2,106.8 1 1 +github.com/thalesfsp/godotenv/godotenv.go:100.37,102.17 2 1 +github.com/thalesfsp/godotenv/godotenv.go:102.17,104.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:111.70,115.37 3 1 +github.com/thalesfsp/godotenv/godotenv.go:128.2,128.8 1 1 +github.com/thalesfsp/godotenv/godotenv.go:115.37,118.27 2 1 +github.com/thalesfsp/godotenv/godotenv.go:123.3,123.44 1 1 +github.com/thalesfsp/godotenv/godotenv.go:118.27,121.4 2 1 +github.com/thalesfsp/godotenv/godotenv.go:123.44,125.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:132.63,137.21 4 1 +github.com/thalesfsp/godotenv/godotenv.go:141.2,141.37 1 1 +github.com/thalesfsp/godotenv/godotenv.go:145.2,145.33 1 1 +github.com/thalesfsp/godotenv/godotenv.go:156.2,156.8 1 1 +github.com/thalesfsp/godotenv/godotenv.go:137.21,139.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:141.37,143.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:145.33,146.31 1 1 +github.com/thalesfsp/godotenv/godotenv.go:146.31,150.18 3 1 +github.com/thalesfsp/godotenv/godotenv.go:153.4,153.23 1 1 +github.com/thalesfsp/godotenv/godotenv.go:150.18,152.5 1 1 +github.com/thalesfsp/godotenv/godotenv.go:160.66,162.2 1 1 +github.com/thalesfsp/godotenv/godotenv.go:171.67,179.2 6 0 +github.com/thalesfsp/godotenv/godotenv.go:182.61,184.16 2 0 +github.com/thalesfsp/godotenv/godotenv.go:187.2,188.16 2 0 +github.com/thalesfsp/godotenv/godotenv.go:191.2,193.16 3 0 +github.com/thalesfsp/godotenv/godotenv.go:196.2,197.12 2 0 +github.com/thalesfsp/godotenv/godotenv.go:184.16,186.3 1 0 +github.com/thalesfsp/godotenv/godotenv.go:188.16,190.3 1 0 +github.com/thalesfsp/godotenv/godotenv.go:193.16,195.3 1 0 +github.com/thalesfsp/godotenv/godotenv.go:202.56,204.27 2 1 +github.com/thalesfsp/godotenv/godotenv.go:211.2,212.39 2 1 +github.com/thalesfsp/godotenv/godotenv.go:204.27,205.44 1 1 +github.com/thalesfsp/godotenv/godotenv.go:205.44,207.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:207.9,209.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:215.54,216.25 1 1 +github.com/thalesfsp/godotenv/godotenv.go:219.2,219.18 1 1 +github.com/thalesfsp/godotenv/godotenv.go:216.25,218.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:222.53,224.2 1 0 +github.com/thalesfsp/godotenv/godotenv.go:226.71,228.16 2 1 +github.com/thalesfsp/godotenv/godotenv.go:232.2,234.36 3 1 +github.com/thalesfsp/godotenv/godotenv.go:239.2,239.33 1 1 +github.com/thalesfsp/godotenv/godotenv.go:245.2,245.12 1 1 +github.com/thalesfsp/godotenv/godotenv.go:228.16,230.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:234.36,237.3 2 1 +github.com/thalesfsp/godotenv/godotenv.go:239.33,240.35 1 1 +github.com/thalesfsp/godotenv/godotenv.go:240.35,242.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:248.70,250.16 2 1 +github.com/thalesfsp/godotenv/godotenv.go:253.2,255.20 2 1 +github.com/thalesfsp/godotenv/godotenv.go:250.16,252.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:260.93,261.20 1 1 +github.com/thalesfsp/godotenv/godotenv.go:267.2,267.33 1 1 +github.com/thalesfsp/godotenv/godotenv.go:289.2,292.73 4 1 +github.com/thalesfsp/godotenv/godotenv.go:297.2,297.27 1 1 +github.com/thalesfsp/godotenv/godotenv.go:303.2,304.38 2 1 +github.com/thalesfsp/godotenv/godotenv.go:307.2,313.8 4 1 +github.com/thalesfsp/godotenv/godotenv.go:261.20,264.3 2 0 +github.com/thalesfsp/godotenv/godotenv.go:267.33,271.49 4 1 +github.com/thalesfsp/godotenv/godotenv.go:286.3,286.43 1 1 +github.com/thalesfsp/godotenv/godotenv.go:271.49,272.77 1 1 +github.com/thalesfsp/godotenv/godotenv.go:281.4,281.49 1 1 +github.com/thalesfsp/godotenv/godotenv.go:272.77,273.22 1 1 +github.com/thalesfsp/godotenv/godotenv.go:273.22,276.6 2 1 +github.com/thalesfsp/godotenv/godotenv.go:276.11,278.6 1 1 +github.com/thalesfsp/godotenv/godotenv.go:281.49,283.5 1 1 +github.com/thalesfsp/godotenv/godotenv.go:292.73,295.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:297.27,300.3 2 1 +github.com/thalesfsp/godotenv/godotenv.go:304.38,306.3 1 1 +github.com/thalesfsp/godotenv/godotenv.go:323.64,329.20 2 1 +github.com/thalesfsp/godotenv/godotenv.go:361.2,361.14 1 1 +github.com/thalesfsp/godotenv/godotenv.go:329.20,334.49 3 1 +github.com/thalesfsp/godotenv/godotenv.go:339.3,339.26 1 1 +github.com/thalesfsp/godotenv/godotenv.go:356.3,356.26 1 1 +github.com/thalesfsp/godotenv/godotenv.go:334.49,337.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:339.26,341.78 1 1 +github.com/thalesfsp/godotenv/godotenv.go:353.4,353.60 1 1 +github.com/thalesfsp/godotenv/godotenv.go:341.78,343.14 2 1 +github.com/thalesfsp/godotenv/godotenv.go:344.14,345.17 1 1 +github.com/thalesfsp/godotenv/godotenv.go:346.14,347.17 1 1 +github.com/thalesfsp/godotenv/godotenv.go:348.13,349.18 1 1 +github.com/thalesfsp/godotenv/godotenv.go:356.26,358.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:366.60,367.70 1 1 +github.com/thalesfsp/godotenv/godotenv.go:367.70,370.22 2 1 +github.com/thalesfsp/godotenv/godotenv.go:373.3,373.48 1 1 +github.com/thalesfsp/godotenv/godotenv.go:378.3,378.11 1 0 +github.com/thalesfsp/godotenv/godotenv.go:370.22,372.4 1 0 +github.com/thalesfsp/godotenv/godotenv.go:373.48,375.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:375.9,375.31 1 1 +github.com/thalesfsp/godotenv/godotenv.go:375.31,377.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:382.38,385.2 2 1 +github.com/thalesfsp/godotenv/godotenv.go:387.44,388.44 1 1 +github.com/thalesfsp/godotenv/godotenv.go:398.2,398.13 1 1 +github.com/thalesfsp/godotenv/godotenv.go:388.44,390.16 2 1 +github.com/thalesfsp/godotenv/godotenv.go:393.3,393.16 1 1 +github.com/thalesfsp/godotenv/godotenv.go:396.3,396.57 1 1 +github.com/thalesfsp/godotenv/godotenv.go:390.16,392.4 1 1 +github.com/thalesfsp/godotenv/godotenv.go:393.16,395.4 1 1 diff --git a/go.mod b/go.mod index 126e61d..3c1c3b4 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/joho/godotenv +module github.com/thalesfsp/godotenv -go 1.12 +go 1.18 \ No newline at end of file diff --git a/godotenv.go b/godotenv.go index 34edcc7..1a52eb5 100644 --- a/godotenv.go +++ b/godotenv.go @@ -1,6 +1,6 @@ // Package godotenv is a go port of the ruby dotenv library (https://github.com/bkeepers/dotenv) // -// Examples/readme can be found on the GitHub page at https://github.com/joho/godotenv +// Examples/readme can be found on the GitHub page at https://github.com/thalesfsp/godotenv // // The TL;DR is that you make a .env file that looks something like //