pax_global_header00006660000000000000000000000064133360366560014525gustar00rootroot0000000000000052 comment=3c96536452167a705ca5a70b831d3810e1e10452 envy-1.6.4/000077500000000000000000000000001333603665600125165ustar00rootroot00000000000000envy-1.6.4/.env000066400000000000000000000001441333603665600133060ustar00rootroot00000000000000# This is a comment # We can use equal or colon notation DIR: root FLAVOUR: none INSIDE_FOLDER=falseenvy-1.6.4/.gitignore000066400000000000000000000003761333603665600145140ustar00rootroot00000000000000*.log .DS_Store doc tmp pkg *.gem *.pid coverage coverage.data build/* *.pbxuser *.mode1v3 .svn profile .console_history .sass-cache/* .rake_tasks~ *.log.lck solr/ .jhw-cache/ jhw.* *.sublime* node_modules/ dist/ generated/ .vendor/ bin/* gin-bin .idea/ envy-1.6.4/.travis.yml000066400000000000000000000001651333603665600146310ustar00rootroot00000000000000language: go sudo: false go: - 1.7 - 1.8 - 1.9 - "1.10" - tip matrix: allow_failures: - go: 'tip' envy-1.6.4/LICENSE.txt000066400000000000000000000020641333603665600143430ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2018 Mark Bates Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. envy-1.6.4/README.md000066400000000000000000000050711333603665600140000ustar00rootroot00000000000000# envy [![Build Status](https://travis-ci.org/gobuffalo/envy.svg?branch=master)](https://travis-ci.org/gobuffalo/envy) Envy makes working with ENV variables in Go trivial. * Get ENV variables with default values. * Set ENV variables safely without affecting the underlying system. * Temporarily change ENV vars; useful for testing. * Map all of the key/values in the ENV. * Loads .env files (by using [godotenv](https://github.com/joho/godotenv/)) * More! ## Installation ```text $ go get -u github.com/gobuffalo/envy ``` ## Usage ```go func Test_Get(t *testing.T) { r := require.New(t) r.NotZero(os.Getenv("GOPATH")) r.Equal(os.Getenv("GOPATH"), envy.Get("GOPATH", "foo")) r.Equal("bar", envy.Get("IDONTEXIST", "bar")) } func Test_MustGet(t *testing.T) { r := require.New(t) r.NotZero(os.Getenv("GOPATH")) v, err := envy.MustGet("GOPATH") r.NoError(err) r.Equal(os.Getenv("GOPATH"), v) _, err = envy.MustGet("IDONTEXIST") r.Error(err) } func Test_Set(t *testing.T) { r := require.New(t) _, err := envy.MustGet("FOO") r.Error(err) envy.Set("FOO", "foo") r.Equal("foo", envy.Get("FOO", "bar")) } func Test_Temp(t *testing.T) { r := require.New(t) _, err := envy.MustGet("BAR") r.Error(err) envy.Temp(func() { envy.Set("BAR", "foo") r.Equal("foo", envy.Get("BAR", "bar")) _, err = envy.MustGet("BAR") r.NoError(err) }) _, err = envy.MustGet("BAR") r.Error(err) } ``` ## .env files support Envy now supports loading `.env` files by using the [godotenv library](https://github.com/joho/godotenv/). That means one can use and define multiple `.env` files which will be loaded on-demand. By default, no env files will be loaded. To load one or more, you need to call the `envy.Load` function in one of the following ways: ```go envy.Load() // 1 envy.Load("MY_ENV_FILE") // 2 envy.Load(".env", ".env.prod") // 3 envy.Load(".env", "NON_EXISTING_FILE") // 4 // 5 envy.Load(".env") envy.Load("NON_EXISTING_FILE") // 6 envy.Load(".env", "NON_EXISTING_FILE", ".env.prod") ``` 1. Will load the default `.env` file 2. Will load the file `MY_ENV_FILE`, **but not** `.env` 3. Will load the file `.env`, and after that will load the `.env.prod` file. If any variable is redefined in `. env.prod` it will be overwritten (will contain the `env.prod` value) 4. Will load the `.env` file and return an error as the second file does not exist. The values in `.env` will be loaded and available. 5. Same as 4 6. Will load the `.env` file and return an error as the second file does not exist. The values in `.env` will be loaded and available, **but the ones in** `.env.prod` **won't**. envy-1.6.4/envy.go000066400000000000000000000115641333603665600140350ustar00rootroot00000000000000package envy import ( "flag" "fmt" "os" "os/exec" "path/filepath" "runtime" "strconv" "strings" "sync" "github.com/joho/godotenv" ) var gil = &sync.RWMutex{} var env = map[string]string{} func init() { Load() loadEnv() } // Load the ENV variables to the env map func loadEnv() { gil.Lock() defer gil.Unlock() // Detect the Go version on the user system, not the one that was used to compile the binary v := "" out, err := exec.Command("go", "version").Output() if err == nil { // This will break when Go 2 lands v = strings.Split(string(out), " ")[2][4:] } else { v = runtime.Version()[4:] } goRuntimeVersion, _ := strconv.ParseFloat(runtime.Version()[4:], 64) goVersion, err := strconv.ParseFloat(v, 64) if err != nil { goVersion = goRuntimeVersion } if os.Getenv("GO_ENV") == "" { if v := flag.Lookup("test.v"); v != nil && v.Value.String() == "true" { env["GO_ENV"] = "test" } } // set the GOPATH if using >= 1.8 and the GOPATH isn't set if goVersion >= 8 && os.Getenv("GOPATH") == "" { out, err := exec.Command("go", "env", "GOPATH").Output() if err == nil { gp := strings.TrimSpace(string(out)) os.Setenv("GOPATH", gp) } } for _, e := range os.Environ() { pair := strings.Split(e, "=") env[pair[0]] = os.Getenv(pair[0]) } } // Reload the ENV variables. Useful if // an external ENV manager has been used func Reload() { env = map[string]string{} loadEnv() } // Load .env files. Files will be loaded in the same order that are received. // Redefined vars will override previously existing values. // IE: envy.Load(".env", "test_env/.env") will result in DIR=test_env // If no arg passed, it will try to load a .env file. func Load(files ...string) error { // If no files received, load the default one if len(files) == 0 { err := godotenv.Overload() if err == nil { Reload() } return err } // We received a list of files for _, file := range files { // Check if it exists or we can access if _, err := os.Stat(file); err != nil { // It does not exist or we can not access. // Return and stop loading return err } // It exists and we have permission. Load it if err := godotenv.Overload(file); err != nil { return err } // Reload the env so all new changes are noticed Reload() } return nil } // Get a value from the ENV. If it doesn't exist the // default value will be returned. func Get(key string, value string) string { gil.RLock() defer gil.RUnlock() if v, ok := env[key]; ok { return v } return value } // Get a value from the ENV. If it doesn't exist // an error will be returned func MustGet(key string) (string, error) { gil.RLock() defer gil.RUnlock() if v, ok := env[key]; ok { return v, nil } return "", fmt.Errorf("could not find ENV var with %s", key) } // Set a value into the ENV. This is NOT permanent. It will // only affect values accessed through envy. func Set(key string, value string) { gil.Lock() defer gil.Unlock() env[key] = value } // MustSet the value into the underlying ENV, as well as envy. // This may return an error if there is a problem setting the // underlying ENV value. func MustSet(key string, value string) error { gil.Lock() defer gil.Unlock() err := os.Setenv(key, value) if err != nil { return err } env[key] = value return nil } // Map all of the keys/values set in envy. func Map() map[string]string { gil.RLock() defer gil.RUnlock() cp := map[string]string{} for k, v := range env { cp[k] = v } return env } // Temp makes a copy of the values and allows operation on // those values temporarily during the run of the function. // At the end of the function run the copy is discarded and // the original values are replaced. This is useful for testing. // Warning: This function is NOT safe to use from a goroutine or // from code which may access any Get or Set function from a goroutine func Temp(f func()) { oenv := env env = map[string]string{} for k, v := range oenv { env[k] = v } defer func() { env = oenv }() f() } func GoPath() string { return Get("GOPATH", "") } // GoPaths returns all possible GOPATHS that are set. func GoPaths() []string { gp := Get("GOPATH", "") if runtime.GOOS == "windows" { return strings.Split(gp, ";") // Windows uses a different separator } return strings.Split(gp, ":") } func importPath(path string) string { for _, gopath := range GoPaths() { srcpath := filepath.Join(gopath, "src") rel, err := filepath.Rel(srcpath, path) if err == nil { return filepath.ToSlash(rel) } } // fallback to trim rel := strings.TrimPrefix(path, filepath.Join(GoPath(), "src")) rel = strings.TrimPrefix(rel, string(filepath.Separator)) return filepath.ToSlash(rel) } func CurrentPackage() string { pwd, _ := os.Getwd() return importPath(pwd) } func Environ() []string { gil.RLock() defer gil.RUnlock() var e []string for k, v := range env { e = append(e, fmt.Sprintf("%s=%s", k, v)) } return e } envy-1.6.4/envy_test.go000066400000000000000000000072511333603665600150720ustar00rootroot00000000000000package envy import ( "os" "runtime" "testing" "github.com/stretchr/testify/require" ) func Test_Get(t *testing.T) { r := require.New(t) r.NotZero(os.Getenv("GOPATH")) r.Equal(os.Getenv("GOPATH"), Get("GOPATH", "foo")) r.Equal("bar", Get("IDONTEXIST", "bar")) } func Test_MustGet(t *testing.T) { r := require.New(t) r.NotZero(os.Getenv("GOPATH")) v, err := MustGet("GOPATH") r.NoError(err) r.Equal(os.Getenv("GOPATH"), v) _, err = MustGet("IDONTEXIST") r.Error(err) } func Test_Set(t *testing.T) { r := require.New(t) _, err := MustGet("FOO") r.Error(err) Set("FOO", "foo") r.Equal("foo", Get("FOO", "bar")) } func Test_MustSet(t *testing.T) { r := require.New(t) r.Zero(os.Getenv("FOO")) err := MustSet("FOO", "BAR") r.NoError(err) r.Equal("BAR", os.Getenv("FOO")) } func Test_Temp(t *testing.T) { r := require.New(t) _, err := MustGet("BAR") r.Error(err) Temp(func() { Set("BAR", "foo") r.Equal("foo", Get("BAR", "bar")) _, err = MustGet("BAR") r.NoError(err) }) _, err = MustGet("BAR") r.Error(err) } func Test_GoPath(t *testing.T) { r := require.New(t) Temp(func() { Set("GOPATH", "/foo") r.Equal("/foo", GoPath()) }) } func Test_GoPaths(t *testing.T) { r := require.New(t) Temp(func() { if runtime.GOOS == "windows" { Set("GOPATH", "/foo;/bar") } else { Set("GOPATH", "/foo:/bar") } r.Equal([]string{"/foo", "/bar"}, GoPaths()) }) } func Test_CurrentPackage(t *testing.T) { r := require.New(t) r.Equal("github.com/gobuffalo/envy", CurrentPackage()) } // Env files loading func Test_LoadEnvLoadsEnvFile(t *testing.T) { r := require.New(t) Temp(func() { r.Equal("root", Get("DIR", "")) r.Equal("none", Get("FLAVOUR", "")) r.Equal("false", Get("INSIDE_FOLDER", "")) }) } func Test_LoadDefaultEnvWhenNoArgsPassed(t *testing.T) { r := require.New(t) Temp(func() { err := Load() r.NoError(err) r.Equal("root", Get("DIR", "")) r.Equal("none", Get("FLAVOUR", "")) r.Equal("false", Get("INSIDE_FOLDER", "")) }) } func Test_DoNotLoadDefaultEnvWhenArgsPassed(t *testing.T) { r := require.New(t) Temp(func() { err := Load("test_env/.env") r.NoError(err) r.Equal("test_env", Get("DIR", "")) r.Equal("none", Get("FLAVOUR", "")) r.Equal("true", Get("INSIDE_FOLDER", "")) }) } func Test_OverloadParams(t *testing.T) { r := require.New(t) Temp(func() { err := Load("test_env/.env.test", "test_env/.env.prod") r.NoError(err) r.Equal("production", Get("FLAVOUR", "")) }) } func Test_ErrorWhenSingleFileLoadDoesNotExist(t *testing.T) { r := require.New(t) Temp(func() { delete(env, "FLAVOUR") err := Load(".env.fake") r.Error(err) r.Equal("FAILED", Get("FLAVOUR", "FAILED")) }) } func Test_KeepEnvWhenFileInListFails(t *testing.T) { r := require.New(t) Temp(func() { err := Load(".env", ".env.FAKE") r.Error(err) r.Equal("none", Get("FLAVOUR", "FAILED")) r.Equal("root", Get("DIR", "FAILED")) }) } func Test_KeepEnvWhenSecondLoadFails(t *testing.T) { r := require.New(t) Temp(func() { err := Load(".env") r.NoError(err) r.Equal("none", Get("FLAVOUR", "FAILED")) r.Equal("root", Get("DIR", "FAILED")) err = Load(".env.FAKE") r.Equal("none", Get("FLAVOUR", "FAILED")) r.Equal("root", Get("DIR", "FAILED")) }) } func Test_StopLoadingWhenFileInListFails(t *testing.T) { r := require.New(t) Temp(func() { err := Load(".env", ".env.FAKE", "test_env/.env.prod") r.Error(err) r.Equal("none", Get("FLAVOUR", "FAILED")) r.Equal("root", Get("DIR", "FAILED")) }) } func Test_GOPATH_Not_Set(t *testing.T) { r := require.New(t) Temp(func() { MustSet("GOPATH", "/go") loadEnv() r.Equal("/go", Get("GOPATH", "notset")) }) r.Equal("github.com/gobuffalo/envy", CurrentPackage()) } envy-1.6.4/go.mod000066400000000000000000000003241333603665600136230ustar00rootroot00000000000000module github.com/gobuffalo/envy require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/joho/godotenv v1.2.0 github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.2.2 ) envy-1.6.4/go.sum000066400000000000000000000012601333603665600136500ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/joho/godotenv v1.2.0 h1:vGTvz69FzUFp+X4/bAkb0j5BoLC+9bpqTWY8mjhA9pc= github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= envy-1.6.4/test_env/000077500000000000000000000000001333603665600143455ustar00rootroot00000000000000envy-1.6.4/test_env/.env000066400000000000000000000000541333603665600151350ustar00rootroot00000000000000DIR=test_env FLAVOUR=none INSIDE_FOLDER=trueenvy-1.6.4/test_env/.env.prod000066400000000000000000000000221333603665600160730ustar00rootroot00000000000000FLAVOUR=productionenvy-1.6.4/test_env/.env.test000066400000000000000000000000141333603665600161070ustar00rootroot00000000000000FLAVOUR=test