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

Fix override for OverLoad and co. #15

Merged
merged 1 commit into from May 22, 2022
Merged
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
25 changes: 14 additions & 11 deletions gotenv.go
Expand Up @@ -84,7 +84,7 @@ func loadenv(override bool, filenames ...string) error {

// parse and set :)
func parset(r io.Reader, override bool) error {
env, err := StrictParse(r)
env, err := strictParse(r, override)
if err != nil {
return err
}
Expand All @@ -110,14 +110,18 @@ func setenv(key, val string, override bool) {
// It expands the value of a variable from the environment variable but does not set the value to the environment itself.
// This function is skipping any invalid lines and only processing the valid one.
func Parse(r io.Reader) Env {
env, _ := StrictParse(r)
env, _ := strictParse(r, false)
return env
}

// StrictParse is a function to parse line by line any io.Reader supplied and returns the valid Env key/value pair of valid variables.
// It expands the value of a variable from the environment variable but does not set the value to the environment itself.
// This function is returning an error if there are any invalid lines.
func StrictParse(r io.Reader) (Env, error) {
return strictParse(r, false)
}

func strictParse(r io.Reader, override bool) (Env, error) {
env := make(Env)
scanner := bufio.NewScanner(r)

Expand All @@ -133,16 +137,15 @@ func StrictParse(r io.Reader) (Env, error) {

i++

err := parseLine(line, env)
err := parseLine(line, env, override)
if err != nil {
return env, err
}
}

return env, nil
}

func parseLine(s string, env Env) error {
func parseLine(s string, env Env, override bool) error {
rl := regexp.MustCompile(linePattern)
rm := rl.FindStringSubmatch(s)

Expand Down Expand Up @@ -177,11 +180,11 @@ func parseLine(s string, env Env) error {

rv := regexp.MustCompile(variablePattern)
fv := func(s string) string {
return varReplacement(s, hsq, env)
return varReplacement(s, hsq, env, override)
}

val = rv.ReplaceAllStringFunc(val, fv)
val = parseVal(val, env, hdq)
val = parseVal(val, env, hdq, override)

env[key] = val
return nil
Expand All @@ -201,7 +204,7 @@ func parseExport(st string, env Env) error {
return nil
}

func varReplacement(s string, hsq bool, env Env) string {
func varReplacement(s string, hsq bool, env Env, override bool) string {
if strings.HasPrefix(s, "\\") {
return strings.TrimPrefix(s, "\\")
}
Expand All @@ -220,7 +223,7 @@ func varReplacement(s string, hsq bool, env Env) string {

v := mn[3]

if replace, ok := os.LookupEnv(v); ok {
if replace, ok := os.LookupEnv(v); ok && !override {
return replace
}

Expand All @@ -246,15 +249,15 @@ func checkFormat(s string, env Env) error {
return fmt.Errorf("line `%s` doesn't match format", s)
}

func parseVal(val string, env Env, ignoreNewlines bool) string {
func parseVal(val string, env Env, ignoreNewlines bool, override bool) string {
if strings.Contains(val, "=") && !ignoreNewlines {
kv := strings.Split(val, "\r")

if len(kv) > 1 {
val = kv[0]

for i := 1; i < len(kv); i++ {
parseLine(kv[i], env)
parseLine(kv[i], env, override)
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions gotenv_test.go
Expand Up @@ -342,6 +342,24 @@ func TestOverLoad_overriding(t *testing.T) {
os.Clearenv()
}

func TestOverLoad_overrideVars(t *testing.T) {
os.Setenv("A", "fromEnv")
err := gotenv.OverLoad("fixtures/vars.env")
assert.Nil(t, err)
assert.Equal(t, "fromFile", os.Getenv("B"))
os.Clearenv()
}

func TestOverLoad_overrideVars2(t *testing.T) {
os.Setenv("C", "fromEnv")
err := gotenv.OverLoad("fixtures/vars.env")
assert.Nil(t, err)
// The value for D is not "fromFile" because C is defined after the
// definition of D.
assert.Equal(t, "fromEnv", os.Getenv("D"), "C defined after usage")
os.Clearenv()
}

func TestMustOverLoad_nonExist(t *testing.T) {
assert.Panics(t, func() { gotenv.Must(gotenv.OverLoad, ".env.not.exist") }, "Caling gotenv.Must with Overgotenv.Load and non exist file SHOULD panic")
}
Expand Down