Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows to prefix exported env vars #194

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -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).

Expand All @@ -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
Expand All @@ -50,7 +50,7 @@ import (
"log"
"os"

"github.com/joho/godotenv"
"github.com/thalesfsp/godotenv"
)

func main() {
Expand All @@ -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
Expand Down Expand Up @@ -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:

Expand All @@ -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.
4 changes: 2 additions & 2 deletions autoload/autoload.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion cmd/godotenv/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"strings"

"github.com/joho/godotenv"
"github.com/thalesfsp/godotenv"
)

func main() {
Expand Down
103 changes: 103 additions & 0 deletions coverage.out
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/joho/godotenv
module github.com/thalesfsp/godotenv

go 1.12
go 1.18
46 changes: 41 additions & 5 deletions godotenv.go
Original file line number Diff line number Diff line change
@@ -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
//
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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))
}
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
}

Expand Down
30 changes: 30 additions & 0 deletions godotenv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down