diff --git a/opts/file.go b/opts/file.go index d1089ea41d14..654288cbbd98 100644 --- a/opts/file.go +++ b/opts/file.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "io" "os" "strings" "unicode" @@ -12,15 +13,22 @@ import ( const whiteSpaces = " \t" -func parseKeyValueFile(filename string, emptyFn func(string) (string, bool)) ([]string, error) { +func parseKeyValueFile(filename string, lookupFn func(string) (string, bool)) ([]string, error) { fh, err := os.Open(filename) if err != nil { return []string{}, err } defer fh.Close() + return ParseKeyValueFile(fh, filename, lookupFn) +} +// ParseKeyValueFile parse a file containing key,value pairs separated by equal sign +// Lines starting with `#` are ignored +// If a key is declared without a value (no equal sign), lookupFn is requested to provide value for the given key +// value is returned as-is, without any kind of parsing but removal of leading whitespace +func ParseKeyValueFile(r io.Reader, filename string, lookupFn func(string) (string, bool)) ([]string, error) { lines := []string{} - scanner := bufio.NewScanner(fh) + scanner := bufio.NewScanner(r) currentLine := 0 utf8bom := []byte{0xEF, 0xBB, 0xBF} for scanner.Scan() { @@ -53,8 +61,8 @@ func parseKeyValueFile(filename string, emptyFn func(string) (string, bool)) ([] lines = append(lines, variable+"="+value) } else { var present bool - if emptyFn != nil { - value, present = emptyFn(line) + if lookupFn != nil { + value, present = lookupFn(line) } if present { // if only a pass-through variable is given, clean it up. diff --git a/opts/file_test.go b/opts/file_test.go new file mode 100644 index 000000000000..d0e6835c00f0 --- /dev/null +++ b/opts/file_test.go @@ -0,0 +1,26 @@ +package opts + +import ( + "bytes" + "testing" + + "gotest.tools/v3/assert" +) + +func TestParseKeyValueFile(t *testing.T) { + b := []byte(` +FOO=BAR +ZOT`) + + vars := map[string]string{ + "ZOT": "QIX", + } + lookupFn := func(s string) (string, bool) { + v, ok := vars[s] + return v, ok + } + + got, err := ParseKeyValueFile(bytes.NewReader(b), "(inlined)", lookupFn) + assert.NilError(t, err) + assert.DeepEqual(t, got, []string{"FOO=BAR", "ZOT=QIX"}) +}