forked from coop-cloud-mirrors/godotenv
		
	Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a2be92d182 | |||
| 3a7a190201 | |||
| a7f6c4c583 | |||
| 32e64fa834 | |||
| 7765d9d198 | |||
| 383d64cb7e | |||
| e3b6eee84d | |||
| 193c9aba29 | 
							
								
								
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@ -14,7 +14,7 @@ jobs:
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
      - name: Setup go
 | 
			
		||||
        uses: actions/setup-go@v3
 | 
			
		||||
        uses: actions/setup-go@v4
 | 
			
		||||
        with:
 | 
			
		||||
          go-version: ${{ matrix.go }}
 | 
			
		||||
      - run: go test
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,6 @@ import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/joho/godotenv"
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,7 @@
 | 
			
		||||
# Full line comment
 | 
			
		||||
qux=thud # fred # other
 | 
			
		||||
thud=fred#qux # other
 | 
			
		||||
fred=qux#baz # other # more
 | 
			
		||||
foo=bar # baz
 | 
			
		||||
bar=foo#baz
 | 
			
		||||
baz="foo"#bar
 | 
			
		||||
 | 
			
		||||
@ -3,3 +3,4 @@ OPTION_B=${OPTION_A}
 | 
			
		||||
OPTION_C=$OPTION_B
 | 
			
		||||
OPTION_D=${OPTION_A}${OPTION_B}
 | 
			
		||||
OPTION_E=${OPTION_NOT_DEFINED}
 | 
			
		||||
OPTION_F=${GLOBAL_OPTION}
 | 
			
		||||
 | 
			
		||||
@ -207,15 +207,21 @@ func TestLoadQuotedEnv(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestSubstitutions(t *testing.T) {
 | 
			
		||||
	envFileName := "fixtures/substitutions.env"
 | 
			
		||||
 | 
			
		||||
	presets := map[string]string{
 | 
			
		||||
		"GLOBAL_OPTION": "global",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expectedValues := map[string]string{
 | 
			
		||||
		"OPTION_A": "1",
 | 
			
		||||
		"OPTION_B": "1",
 | 
			
		||||
		"OPTION_C": "1",
 | 
			
		||||
		"OPTION_D": "11",
 | 
			
		||||
		"OPTION_E": "",
 | 
			
		||||
		"OPTION_F": "global",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
 | 
			
		||||
	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, presets)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestExpanding(t *testing.T) {
 | 
			
		||||
@ -471,6 +477,9 @@ func TestErrorParsing(t *testing.T) {
 | 
			
		||||
func TestComments(t *testing.T) {
 | 
			
		||||
	envFileName := "fixtures/comments.env"
 | 
			
		||||
	expectedValues := map[string]string{
 | 
			
		||||
		"qux":  "thud",
 | 
			
		||||
		"thud": "fred#qux",
 | 
			
		||||
		"fred": "qux#baz",
 | 
			
		||||
		"foo":  "bar",
 | 
			
		||||
		"bar":  "foo#baz",
 | 
			
		||||
		"baz":  "foo",
 | 
			
		||||
@ -573,3 +582,64 @@ func TestTrailingNewlines(t *testing.T) {
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestWhitespace(t *testing.T) {
 | 
			
		||||
	cases := map[string]struct {
 | 
			
		||||
		input string
 | 
			
		||||
		key   string
 | 
			
		||||
		value string
 | 
			
		||||
	}{
 | 
			
		||||
		"Leading whitespace": {
 | 
			
		||||
			input: " A=a\n",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"Leading tab": {
 | 
			
		||||
			input: "\tA=a\n",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"Leading mixed whitespace": {
 | 
			
		||||
			input: " \t \t\n\t \t A=a\n",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"Leading whitespace before export": {
 | 
			
		||||
			input: " \t\t export    A=a\n",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"Trailing whitespace": {
 | 
			
		||||
			input: "A=a \t \t\n",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"Trailing whitespace with export": {
 | 
			
		||||
			input: "export A=a\t \t \n",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"No EOL": {
 | 
			
		||||
			input: "A=a",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
		"Trailing whitespace with no EOL": {
 | 
			
		||||
			input: "A=a ",
 | 
			
		||||
			key:   "A",
 | 
			
		||||
			value: "a",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for n, c := range cases {
 | 
			
		||||
		t.Run(n, func(t *testing.T) {
 | 
			
		||||
			result, err := Unmarshal(c.input)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Errorf("Input: %q Unexpected error:\t%q", c.input, err)
 | 
			
		||||
			}
 | 
			
		||||
			if result[c.key] != c.value {
 | 
			
		||||
				t.Errorf("Input %q Expected:\t %q/%q\nGot:\t %q", c.input, c.key, c.value, result)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								parser.go
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								parser.go
									
									
									
									
									
								
							@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode"
 | 
			
		||||
@ -142,9 +143,9 @@ func extractVarValue(src []byte, vars map[string]string) (value string, rest []b
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Work backwards to check if the line ends in whitespace then
 | 
			
		||||
		// a comment (ie asdasd # some comment)
 | 
			
		||||
		for i := endOfVar - 1; i >= 0; i-- {
 | 
			
		||||
			if line[i] == charComment && i > 0 {
 | 
			
		||||
		// a comment, ie: foo=bar # baz # other
 | 
			
		||||
		for i := 0; i < endOfVar; i++ {
 | 
			
		||||
			if line[i] == charComment && i < endOfVar {
 | 
			
		||||
				if isSpace(line[i-1]) {
 | 
			
		||||
					endOfVar = i
 | 
			
		||||
					break
 | 
			
		||||
@ -211,7 +212,7 @@ func indexOfNonSpaceChar(src []byte) int {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// hasQuotePrefix reports whether charset starts with single or double quote and returns quote character
 | 
			
		||||
func hasQuotePrefix(src []byte) (prefix byte, isQuored bool) {
 | 
			
		||||
func hasQuotePrefix(src []byte) (prefix byte, isQuoted bool) {
 | 
			
		||||
	if len(src) == 0 {
 | 
			
		||||
		return 0, false
 | 
			
		||||
	}
 | 
			
		||||
@ -264,6 +265,12 @@ func expandVariables(v string, m map[string]string) string {
 | 
			
		||||
		if submatch[1] == "\\" || submatch[2] == "(" {
 | 
			
		||||
			return submatch[0][1:]
 | 
			
		||||
		} else if submatch[4] != "" {
 | 
			
		||||
			if val, ok := m[submatch[4]]; ok {
 | 
			
		||||
				return val
 | 
			
		||||
			}
 | 
			
		||||
			if val, ok := os.LookupEnv(submatch[4]); ok {
 | 
			
		||||
				return val
 | 
			
		||||
			}
 | 
			
		||||
			return m[submatch[4]]
 | 
			
		||||
		}
 | 
			
		||||
		return s
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user