summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/subosito
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/subosito')
-rw-r--r--vendor/github.com/subosito/gotenv/.gitignore1
-rw-r--r--vendor/github.com/subosito/gotenv/.golangci.yaml7
-rw-r--r--vendor/github.com/subosito/gotenv/CHANGELOG.md12
-rw-r--r--vendor/github.com/subosito/gotenv/README.md3
-rw-r--r--vendor/github.com/subosito/gotenv/gotenv.go189
5 files changed, 151 insertions, 61 deletions
diff --git a/vendor/github.com/subosito/gotenv/.gitignore b/vendor/github.com/subosito/gotenv/.gitignore
index 2b8d4561..7db37c1d 100644
--- a/vendor/github.com/subosito/gotenv/.gitignore
+++ b/vendor/github.com/subosito/gotenv/.gitignore
@@ -1,3 +1,4 @@
*.test
*.out
annotate.json
+profile.cov
diff --git a/vendor/github.com/subosito/gotenv/.golangci.yaml b/vendor/github.com/subosito/gotenv/.golangci.yaml
new file mode 100644
index 00000000..8c82a762
--- /dev/null
+++ b/vendor/github.com/subosito/gotenv/.golangci.yaml
@@ -0,0 +1,7 @@
+# Options for analysis running.
+run:
+ timeout: 1m
+
+linters-settings:
+ gofmt:
+ simplify: true
diff --git a/vendor/github.com/subosito/gotenv/CHANGELOG.md b/vendor/github.com/subosito/gotenv/CHANGELOG.md
index 24b096b9..757caad2 100644
--- a/vendor/github.com/subosito/gotenv/CHANGELOG.md
+++ b/vendor/github.com/subosito/gotenv/CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog
+## [1.4.0] - 2022-06-02
+
+### Added
+
+- Add `Marshal` and `Unmarshal` helpers
+
+### Changed
+
+- The CI will now run a linter and the tests on PRs.
+
## [1.3.0] - 2022-05-23
### Added
@@ -41,7 +51,7 @@
### Added
- Supports carriage return in env
-- Handle files with UTF-8 BOM
+- Handle files with UTF-8 BOM
### Changed
diff --git a/vendor/github.com/subosito/gotenv/README.md b/vendor/github.com/subosito/gotenv/README.md
index 3ce9a410..fc9616e3 100644
--- a/vendor/github.com/subosito/gotenv/README.md
+++ b/vendor/github.com/subosito/gotenv/README.md
@@ -28,7 +28,7 @@ Once loaded you can use `os.Getenv()` to get the value of the variable.
Let's say you have `.env` file:
-```
+```sh
APP_ID=1234567
APP_SECRET=abcdef
```
@@ -78,7 +78,6 @@ Besides above functions, `gotenv` also provides another functions that overrides
- `gotenv.OverLoad`
- `gotenv.OverApply`
-
Here's the example of this overrides behavior:
```go
diff --git a/vendor/github.com/subosito/gotenv/gotenv.go b/vendor/github.com/subosito/gotenv/gotenv.go
index c4c1e50e..dc013e1e 100644
--- a/vendor/github.com/subosito/gotenv/gotenv.go
+++ b/vendor/github.com/subosito/gotenv/gotenv.go
@@ -3,10 +3,14 @@ package gotenv
import (
"bufio"
+ "bytes"
"fmt"
"io"
"os"
+ "path/filepath"
"regexp"
+ "sort"
+ "strconv"
"strings"
)
@@ -24,41 +28,31 @@ const (
// Env holds key/value pair of valid environment variable
type Env map[string]string
-/*
-Load is a function to load a file or multiple files and then export the valid variables into environment variables if they do not exist.
-When it's called with no argument, it will load `.env` file on the current path and set the environment variables.
-Otherwise, it will loop over the filenames parameter and set the proper environment variables.
-*/
+// Load is a function to load a file or multiple files and then export the valid variables into environment variables if they do not exist.
+// When it's called with no argument, it will load `.env` file on the current path and set the environment variables.
+// Otherwise, it will loop over the filenames parameter and set the proper environment variables.
func Load(filenames ...string) error {
return loadenv(false, filenames...)
}
-/*
-OverLoad is a function to load a file or multiple files and then export and override the valid variables into environment variables.
-*/
+// OverLoad is a function to load a file or multiple files and then export and override the valid variables into environment variables.
func OverLoad(filenames ...string) error {
return loadenv(true, filenames...)
}
-/*
-Must is wrapper function that will panic when supplied function returns an error.
-*/
+// Must is wrapper function that will panic when supplied function returns an error.
func Must(fn func(filenames ...string) error, filenames ...string) {
if err := fn(filenames...); err != nil {
panic(err.Error())
}
}
-/*
-Apply is a function to load an io Reader then export the valid variables into environment variables if they do not exist.
-*/
+// Apply is a function to load an io Reader then export the valid variables into environment variables if they do not exist.
func Apply(r io.Reader) error {
return parset(r, false)
}
-/*
-OverApply is a function to load an io Reader then export and override the valid variables into environment variables.
-*/
+// OverApply is a function to load an io Reader then export and override the valid variables into environment variables.
func OverApply(r io.Reader) error {
return parset(r, true)
}
@@ -75,11 +69,10 @@ func loadenv(override bool, filenames ...string) error {
}
err = parset(f, override)
+ f.Close()
if err != nil {
return err
}
-
- f.Close()
}
return nil
@@ -124,9 +117,94 @@ func StrictParse(r io.Reader) (Env, error) {
return strictParse(r, false)
}
+// Read is a function to parse a file 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 skipping any invalid lines and only processing the valid one.
+func Read(filename string) (Env, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return strictParse(f, 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
+ }
+
+ return file.Sync()
+}
+
+// splitLines is a valid SplitFunc for a bufio.Scanner. It will split lines on CR ('\r'), LF ('\n') or CRLF (any of the three sequences).
+// If a CR is immediately followed by a LF, it is treated as a CRLF (one single line break).
+func splitLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, bufio.ErrFinalToken
+ }
+
+ idx := bytes.IndexAny(data, "\r\n")
+ switch {
+ case atEOF && idx < 0:
+ return len(data), data, bufio.ErrFinalToken
+
+ case idx < 0:
+ return 0, nil, nil
+ }
+
+ // consume CR or LF
+ eol := idx + 1
+ // detect CRLF
+ if len(data) > eol && data[eol-1] == '\r' && data[eol] == '\n' {
+ eol++
+ }
+
+ return eol, data[:idx], nil
+}
+
func strictParse(r io.Reader, override bool) (Env, error) {
env := make(Env)
scanner := bufio.NewScanner(r)
+ scanner.Split(splitLines)
firstLine := true
@@ -143,28 +221,34 @@ func strictParse(r io.Reader, override bool) (Env, error) {
}
quote := ""
+ // look for the delimiter character
idx := strings.Index(line, "=")
if idx == -1 {
idx = strings.Index(line, ":")
}
+ // look for a quote character
if idx > 0 && idx < len(line)-1 {
val := strings.TrimSpace(line[idx+1:])
if val[0] == '"' || val[0] == '\'' {
quote = val[:1]
+ // look for the closing quote character within the same line
idx = strings.LastIndex(strings.TrimSpace(val[1:]), quote)
if idx >= 0 && val[idx] != '\\' {
quote = ""
}
}
}
+ // look for the closing quote character
for quote != "" && scanner.Scan() {
l := scanner.Text()
line += "\n" + l
idx := strings.LastIndex(l, quote)
if idx > 0 && l[idx-1] == '\\' {
+ // foud a matching quote character but it's escaped
continue
}
if idx >= 0 {
+ // foud a matching quote
quote = ""
}
}
@@ -195,21 +279,23 @@ func parseLine(s string, env Env, override bool) error {
return checkFormat(s, env)
}
- key := rm[1]
- val := rm[2]
-
- // trim whitespace
- val = strings.TrimSpace(val)
+ key := strings.TrimSpace(rm[1])
+ val := strings.TrimSpace(rm[2])
- // determine if string has quote prefix
- hdq := strings.HasPrefix(val, `"`)
+ var hsq, hdq bool
- // determine if string has single quote prefix
- hsq := strings.HasPrefix(val, `'`)
+ // check if the value is quoted
+ if l := len(val); l >= 2 {
+ l -= 1
+ // has double quotes
+ hdq = val[0] == '"' && val[l] == '"'
+ // has single quotes
+ hsq = val[0] == '\'' && val[l] == '\''
- // remove quotes '' or ""
- if l := len(val); (hsq || hdq) && l >= 2 {
- val = val[1 : l-1]
+ // remove quotes '' or ""
+ if hsq || hdq {
+ val = val[1:l]
+ }
}
if hdq {
@@ -220,13 +306,11 @@ func parseLine(s string, env Env, override bool) error {
val = unescapeRgx.ReplaceAllString(val, "$1")
}
- fv := func(s string) string {
- return varReplacement(s, hsq, env, override)
- }
-
if !hsq {
+ fv := func(s string) string {
+ return varReplacement(s, hsq, env, override)
+ }
val = varRgx.ReplaceAllStringFunc(val, fv)
- val = parseVal(val, env, hdq, override)
}
env[key] = val
@@ -250,8 +334,13 @@ func parseExport(st string, env Env) error {
var varNameRgx = regexp.MustCompile(`(\$)(\{?([A-Z0-9_]+)\}?)`)
func varReplacement(s string, hsq bool, env Env, override bool) string {
- if strings.HasPrefix(s, "\\") {
- return strings.TrimPrefix(s, "\\")
+ if s == "" {
+ return s
+ }
+
+ if s[0] == '\\' {
+ // the dollar sign is escaped
+ return s[1:]
}
if hsq {
@@ -270,18 +359,17 @@ func varReplacement(s string, hsq bool, env Env, override bool) string {
return replace
}
- replace, ok := env[v]
- if !ok {
- replace = os.Getenv(v)
+ if replace, ok := env[v]; ok {
+ return replace
}
- return replace
+ return os.Getenv(v)
}
func checkFormat(s string, env Env) error {
st := strings.TrimSpace(s)
- if (st == "") || strings.HasPrefix(st, "#") {
+ if st == "" || st[0] == '#' {
return nil
}
@@ -291,18 +379,3 @@ 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, override bool) string {
- if strings.Contains(val, "=") && !ignoreNewlines {
- kv := strings.Split(val, "\r")
-
- if len(kv) > 1 {
- val = kv[0]
- for _, l := range kv[1:] {
- _ = parseLine(l, env, override)
- }
- }
- }
-
- return val
-}