provide vendor dir for nix
This commit is contained in:
parent
003e12a3ef
commit
de13066a62
766 changed files with 339881 additions and 0 deletions
1
vendor/github.com/subosito/gotenv/.env
generated
vendored
Normal file
1
vendor/github.com/subosito/gotenv/.env
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
HELLO=world
|
1
vendor/github.com/subosito/gotenv/.env.invalid
generated
vendored
Normal file
1
vendor/github.com/subosito/gotenv/.env.invalid
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
lol$wut
|
4
vendor/github.com/subosito/gotenv/.gitignore
generated
vendored
Normal file
4
vendor/github.com/subosito/gotenv/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.test
|
||||
*.out
|
||||
annotate.json
|
||||
profile.cov
|
7
vendor/github.com/subosito/gotenv/.golangci.yaml
generated
vendored
Normal file
7
vendor/github.com/subosito/gotenv/.golangci.yaml
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Options for analysis running.
|
||||
run:
|
||||
timeout: 1m
|
||||
|
||||
linters-settings:
|
||||
gofmt:
|
||||
simplify: true
|
105
vendor/github.com/subosito/gotenv/CHANGELOG.md
generated
vendored
Normal file
105
vendor/github.com/subosito/gotenv/CHANGELOG.md
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
# Changelog
|
||||
|
||||
## [1.5.0] - 2023-08-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- Use io.Reader instead of custom Reader
|
||||
|
||||
## [1.5.0] - 2023-08-15
|
||||
|
||||
### Added
|
||||
|
||||
- Support for reading UTF16 files
|
||||
|
||||
### Fixed
|
||||
|
||||
- Scanner error handling
|
||||
- Reader error handling
|
||||
|
||||
## [1.4.2] - 2023-01-11
|
||||
|
||||
### Fixed
|
||||
|
||||
- Env var initialization
|
||||
|
||||
### Changed
|
||||
|
||||
- More consitent line splitting
|
||||
|
||||
## [1.4.1] - 2022-08-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- Missing file close
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated dependencies
|
||||
|
||||
## [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
|
||||
|
||||
- Support = within double-quoted strings
|
||||
- Add support for multiline values
|
||||
|
||||
### Changed
|
||||
|
||||
- `OverLoad` prefer environment variables over local variables
|
||||
|
||||
## [1.2.0] - 2019-08-03
|
||||
|
||||
### Added
|
||||
|
||||
- Add `Must` helper to raise an error as panic. It can be used with `Load` and `OverLoad`.
|
||||
- Add more tests to be 100% coverage.
|
||||
- Add CHANGELOG
|
||||
- Add more OS for the test: OSX and Windows
|
||||
|
||||
### Changed
|
||||
|
||||
- Reduce complexity and improve source code for having `A+` score in [goreportcard](https://goreportcard.com/report/github.com/subosito/gotenv).
|
||||
- Updated README with mentions to all available functions
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove `ErrFormat`
|
||||
- Remove `MustLoad` and `MustOverload`, replaced with `Must` helper.
|
||||
|
||||
## [1.1.1] - 2018-06-05
|
||||
|
||||
### Changed
|
||||
|
||||
- Replace `os.Getenv` with `os.LookupEnv` to ensure that the environment variable is not set, by [radding](https://github.com/radding)
|
||||
|
||||
## [1.1.0] - 2017-03-20
|
||||
|
||||
### Added
|
||||
|
||||
- Supports carriage return in env
|
||||
- Handle files with UTF-8 BOM
|
||||
|
||||
### Changed
|
||||
|
||||
- Whitespace handling
|
||||
|
||||
### Fixed
|
||||
|
||||
- Incorrect variable expansion
|
||||
- Handling escaped '$' characters
|
||||
|
||||
## [1.0.0] - 2014-10-05
|
||||
|
||||
First stable release.
|
||||
|
21
vendor/github.com/subosito/gotenv/LICENSE
generated
vendored
Normal file
21
vendor/github.com/subosito/gotenv/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Alif Rachmawadi
|
||||
|
||||
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.
|
129
vendor/github.com/subosito/gotenv/README.md
generated
vendored
Normal file
129
vendor/github.com/subosito/gotenv/README.md
generated
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
# gotenv
|
||||
|
||||
[](https://github.com/subosito/gotenv/actions)
|
||||
[](https://codecov.io/gh/subosito/gotenv)
|
||||
[](https://goreportcard.com/report/github.com/subosito/gotenv)
|
||||
[](https://godoc.org/github.com/subosito/gotenv)
|
||||
|
||||
Load environment variables from `.env` or `io.Reader` in Go.
|
||||
|
||||
## Usage
|
||||
|
||||
Put the gotenv package on your `import` statement:
|
||||
|
||||
```go
|
||||
import "github.com/subosito/gotenv"
|
||||
```
|
||||
|
||||
To modify your app environment variables, `gotenv` expose 2 main functions:
|
||||
|
||||
- `gotenv.Load`
|
||||
- `gotenv.Apply`
|
||||
|
||||
By default, `gotenv.Load` will look for a file called `.env` in the current working directory.
|
||||
|
||||
Behind the scene, it will then load `.env` file and export the valid variables to the environment variables. Make sure you call the method as soon as possible to ensure it loads all variables, say, put it on `init()` function.
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
Here's the example of your app:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/subosito/gotenv"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gotenv.Load()
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.Println(os.Getenv("APP_ID")) // "1234567"
|
||||
log.Println(os.Getenv("APP_SECRET")) // "abcdef"
|
||||
}
|
||||
```
|
||||
|
||||
You can also load other than `.env` file if you wish. Just supply filenames when calling `Load()`. It will load them in order and the first value set for a variable will win.:
|
||||
|
||||
```go
|
||||
gotenv.Load(".env.production", "credentials")
|
||||
```
|
||||
|
||||
While `gotenv.Load` loads entries from `.env` file, `gotenv.Apply` allows you to use any `io.Reader`:
|
||||
|
||||
```go
|
||||
gotenv.Apply(strings.NewReader("APP_ID=1234567"))
|
||||
|
||||
log.Println(os.Getenv("APP_ID"))
|
||||
// Output: "1234567"
|
||||
```
|
||||
|
||||
Both `gotenv.Load` and `gotenv.Apply` **DO NOT** overrides existing environment variables. If you want to override existing ones, you can see section below.
|
||||
|
||||
### Environment Overrides
|
||||
|
||||
Besides above functions, `gotenv` also provides another functions that overrides existing:
|
||||
|
||||
- `gotenv.OverLoad`
|
||||
- `gotenv.OverApply`
|
||||
|
||||
Here's the example of this overrides behavior:
|
||||
|
||||
```go
|
||||
os.Setenv("HELLO", "world")
|
||||
|
||||
// NOTE: using Apply existing value will be reserved
|
||||
gotenv.Apply(strings.NewReader("HELLO=universe"))
|
||||
fmt.Println(os.Getenv("HELLO"))
|
||||
// Output: "world"
|
||||
|
||||
// NOTE: using OverApply existing value will be overridden
|
||||
gotenv.OverApply(strings.NewReader("HELLO=universe"))
|
||||
fmt.Println(os.Getenv("HELLO"))
|
||||
// Output: "universe"
|
||||
```
|
||||
|
||||
### Throw a Panic
|
||||
|
||||
Both `gotenv.Load` and `gotenv.OverLoad` returns an error on something wrong occurred, like your env file is not exist, and so on. To make it easier to use, `gotenv` also provides `gotenv.Must` helper, to let it panic when an error returned.
|
||||
|
||||
```go
|
||||
err := gotenv.Load(".env-is-not-exist")
|
||||
fmt.Println("error", err)
|
||||
// error: open .env-is-not-exist: no such file or directory
|
||||
|
||||
gotenv.Must(gotenv.Load, ".env-is-not-exist")
|
||||
// it will throw a panic
|
||||
// panic: open .env-is-not-exist: no such file or directory
|
||||
```
|
||||
|
||||
### Another Scenario
|
||||
|
||||
Just in case you want to parse environment variables from any `io.Reader`, gotenv keeps its `Parse` and `StrictParse` function as public API so you can use that.
|
||||
|
||||
```go
|
||||
// import "strings"
|
||||
|
||||
pairs := gotenv.Parse(strings.NewReader("FOO=test\nBAR=$FOO"))
|
||||
// gotenv.Env{"FOO": "test", "BAR": "test"}
|
||||
|
||||
pairs, err := gotenv.StrictParse(strings.NewReader(`FOO="bar"`))
|
||||
// gotenv.Env{"FOO": "bar"}
|
||||
```
|
||||
|
||||
`Parse` ignores invalid lines and returns `Env` of valid environment variables, while `StrictParse` returns an error for invalid lines.
|
||||
|
||||
## Notes
|
||||
|
||||
The gotenv package is a Go port of [`dotenv`](https://github.com/bkeepers/dotenv) project with some additions made for Go. For general features, it aims to be compatible as close as possible.
|
409
vendor/github.com/subosito/gotenv/gotenv.go
generated
vendored
Normal file
409
vendor/github.com/subosito/gotenv/gotenv.go
generated
vendored
Normal file
|
@ -0,0 +1,409 @@
|
|||
// Package gotenv provides functionality to dynamically load the environment variables
|
||||
package gotenv
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
const (
|
||||
// Pattern for detecting valid line format
|
||||
linePattern = `\A\s*(?:export\s+)?([\w\.]+)(?:\s*=\s*|:\s+?)('(?:\'|[^'])*'|"(?:\"|[^"])*"|[^#\n]+)?\s*(?:\s*\#.*)?\z`
|
||||
|
||||
// Pattern for detecting valid variable within a value
|
||||
variablePattern = `(\\)?(\$)(\{?([A-Z0-9_]+)?\}?)`
|
||||
)
|
||||
|
||||
// Byte order mark character
|
||||
var (
|
||||
bomUTF8 = []byte("\xEF\xBB\xBF")
|
||||
bomUTF16LE = []byte("\xFF\xFE")
|
||||
bomUTF16BE = []byte("\xFE\xFF")
|
||||
)
|
||||
|
||||
// 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.
|
||||
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.
|
||||
func OverLoad(filenames ...string) error {
|
||||
return loadenv(true, filenames...)
|
||||
}
|
||||
|
||||
// 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.
|
||||
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.
|
||||
func OverApply(r io.Reader) error {
|
||||
return parset(r, true)
|
||||
}
|
||||
|
||||
func loadenv(override bool, filenames ...string) error {
|
||||
if len(filenames) == 0 {
|
||||
filenames = []string{".env"}
|
||||
}
|
||||
|
||||
for _, filename := range filenames {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = parset(f, override)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// parse and set :)
|
||||
func parset(r io.Reader, override bool) error {
|
||||
env, err := strictParse(r, override)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for key, val := range env {
|
||||
setenv(key, val, override)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setenv(key, val string, override bool) {
|
||||
if override {
|
||||
os.Setenv(key, val)
|
||||
} else {
|
||||
if _, present := os.LookupEnv(key); !present {
|
||||
os.Setenv(key, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse 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 skipping any invalid lines and only processing the valid one.
|
||||
func Parse(r io.Reader) Env {
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
tee := io.TeeReader(r, buf)
|
||||
|
||||
// There can be a maximum of 3 BOM bytes.
|
||||
bomByteBuffer := make([]byte, 3)
|
||||
_, err := tee.Read(bomByteBuffer)
|
||||
if err != nil && err != io.EOF {
|
||||
return env, err
|
||||
}
|
||||
|
||||
z := io.MultiReader(buf, r)
|
||||
|
||||
// We chooes a different scanner depending on file encoding.
|
||||
var scanner *bufio.Scanner
|
||||
|
||||
if bytes.HasPrefix(bomByteBuffer, bomUTF8) {
|
||||
scanner = bufio.NewScanner(transform.NewReader(z, unicode.UTF8BOM.NewDecoder()))
|
||||
} else if bytes.HasPrefix(bomByteBuffer, bomUTF16LE) {
|
||||
scanner = bufio.NewScanner(transform.NewReader(z, unicode.UTF16(unicode.LittleEndian, unicode.ExpectBOM).NewDecoder()))
|
||||
} else if bytes.HasPrefix(bomByteBuffer, bomUTF16BE) {
|
||||
scanner = bufio.NewScanner(transform.NewReader(z, unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM).NewDecoder()))
|
||||
} else {
|
||||
scanner = bufio.NewScanner(z)
|
||||
}
|
||||
|
||||
scanner.Split(splitLines)
|
||||
|
||||
for scanner.Scan() {
|
||||
if err := scanner.Err(); err != nil {
|
||||
return env, err
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
|
||||
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 = ""
|
||||
}
|
||||
}
|
||||
|
||||
if quote != "" {
|
||||
return env, fmt.Errorf("missing quotes")
|
||||
}
|
||||
|
||||
err := parseLine(line, env, override)
|
||||
if err != nil {
|
||||
return env, err
|
||||
}
|
||||
}
|
||||
|
||||
return env, scanner.Err()
|
||||
}
|
||||
|
||||
var (
|
||||
lineRgx = regexp.MustCompile(linePattern)
|
||||
unescapeRgx = regexp.MustCompile(`\\([^$])`)
|
||||
varRgx = regexp.MustCompile(variablePattern)
|
||||
)
|
||||
|
||||
func parseLine(s string, env Env, override bool) error {
|
||||
rm := lineRgx.FindStringSubmatch(s)
|
||||
|
||||
if len(rm) == 0 {
|
||||
return checkFormat(s, env)
|
||||
}
|
||||
|
||||
key := strings.TrimSpace(rm[1])
|
||||
val := strings.TrimSpace(rm[2])
|
||||
|
||||
var hsq, hdq bool
|
||||
|
||||
// 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 hsq || hdq {
|
||||
val = val[1:l]
|
||||
}
|
||||
}
|
||||
|
||||
if hdq {
|
||||
val = strings.ReplaceAll(val, `\n`, "\n")
|
||||
val = strings.ReplaceAll(val, `\r`, "\r")
|
||||
|
||||
// Unescape all characters except $ so variables can be escaped properly
|
||||
val = unescapeRgx.ReplaceAllString(val, "$1")
|
||||
}
|
||||
|
||||
if !hsq {
|
||||
fv := func(s string) string {
|
||||
return varReplacement(s, hsq, env, override)
|
||||
}
|
||||
val = varRgx.ReplaceAllStringFunc(val, fv)
|
||||
}
|
||||
|
||||
env[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseExport(st string, env Env) error {
|
||||
if strings.HasPrefix(st, "export") {
|
||||
vs := strings.SplitN(st, " ", 2)
|
||||
|
||||
if len(vs) > 1 {
|
||||
if _, ok := env[vs[1]]; !ok {
|
||||
return fmt.Errorf("line `%s` has an unset variable", st)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var varNameRgx = regexp.MustCompile(`(\$)(\{?([A-Z0-9_]+)\}?)`)
|
||||
|
||||
func varReplacement(s string, hsq bool, env Env, override bool) string {
|
||||
if s == "" {
|
||||
return s
|
||||
}
|
||||
|
||||
if s[0] == '\\' {
|
||||
// the dollar sign is escaped
|
||||
return s[1:]
|
||||
}
|
||||
|
||||
if hsq {
|
||||
return s
|
||||
}
|
||||
|
||||
mn := varNameRgx.FindStringSubmatch(s)
|
||||
|
||||
if len(mn) == 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
v := mn[3]
|
||||
|
||||
if replace, ok := os.LookupEnv(v); ok && !override {
|
||||
return replace
|
||||
}
|
||||
|
||||
if replace, ok := env[v]; ok {
|
||||
return replace
|
||||
}
|
||||
|
||||
return os.Getenv(v)
|
||||
}
|
||||
|
||||
func checkFormat(s string, env Env) error {
|
||||
st := strings.TrimSpace(s)
|
||||
|
||||
if st == "" || st[0] == '#' {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := parseExport(st, env); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("line `%s` doesn't match format", s)
|
||||
}
|
Reference in a new issue