Skip to content

Commit

Permalink
feat: add Marshal and Unmarshal methods
Browse files Browse the repository at this point in the history
Signed-off-by: Luis Davim <luis.davim@sendoso.com>
  • Loading branch information
luisdavim committed May 22, 2022
1 parent 95f38e8 commit 31e5477
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
49 changes: 49 additions & 0 deletions gotenv.go
Expand Up @@ -6,7 +6,10 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
)

Expand Down Expand Up @@ -114,6 +117,52 @@ func StrictParse(r io.Reader) (Env, error) {
return strictParse(r, false)
}

//Unmarshal reads a string line by line 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 Unmarshal(str string) (Env, error) {
return strictParse(strings.NewReader(str), false)
}

// Marshal outputs the given environment as a env file.
// Variables will be sorted by name.
func Marshal(env Env) (string, error) {
lines := make([]string, 0, len(env))
for k, v := range env {
if d, err := strconv.Atoi(v); err == nil {
lines = append(lines, fmt.Sprintf(`%s=%d`, k, d))
} else {
lines = append(lines, fmt.Sprintf(`%s=%q`, k, v))
}
}
sort.Strings(lines)
return strings.Join(lines, "\n"), nil
}

// Write serializes the given environment and writes it to a file
func Write(env Env, filename string) error {
content, err := Marshal(env)
if err != nil {
return err
}
// ensure the path exists
if err := os.MkdirAll(filepath.Dir(filename), 0o775); err != nil {
return err
}
// create or truncate the file
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(content + "\n")
if err != nil {
return err
}
file.Sync()
return err
}

func strictParse(r io.Reader, override bool) (Env, error) {
env := make(Env)
scanner := bufio.NewScanner(r)
Expand Down
21 changes: 21 additions & 0 deletions gotenv_test.go
Expand Up @@ -405,3 +405,24 @@ func TestOverApply(t *testing.T) {
assert.Equal(t, "universe", os.Getenv("HELLO"))
os.Clearenv()
}

func TestMarshal(t *testing.T) {
env := gotenv.Env{
"FOO": "BAR",
"ONE": "1",
"QUOTED": `some "quoted" text`,
"EMPTY": "",
}
expected := `EMPTY=""
FOO="BAR"
ONE=1
QUOTED="some \"quoted\" text"`

actual, err := gotenv.Marshal(env)
assert.Nil(t, err)
assert.Equal(t, expected, actual)

out, err := gotenv.Unmarshal(expected)
assert.Nil(t, err)
assert.Equal(t, env, out)
}

0 comments on commit 31e5477

Please sign in to comment.