Skip to content

Commit 76196db

Browse files
committed
opts: parseKeyValueFile: cleanup and remove redundant trimming
- the function already trimmed leading whitespace from each line before parsing. keys with trailing whitespace would be invalidated, and values have whitespace preserved, so there's no need to trim whitespace for the key. - if a line is validated (key is valid), we don't need to reconstruct the key=value by concatenating, and we can add the line as-is. - check if the key is empty before checking if it contains whitespace - touch-up comments - rename some variables for readability - slight cleanup to use early returns / early continues to reduce nesting Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
1 parent dac7319 commit 76196db

1 file changed

Lines changed: 33 additions & 30 deletions

File tree

opts/file.go

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
const whiteSpaces = " \t"
1414

15-
func parseKeyValueFile(filename string, emptyFn func(string) (string, bool)) ([]string, error) {
15+
func parseKeyValueFile(filename string, lookupFn func(string) (string, bool)) ([]string, error) {
1616
fh, err := os.Open(filename)
1717
if err != nil {
1818
return []string{}, err
@@ -21,45 +21,48 @@ func parseKeyValueFile(filename string, emptyFn func(string) (string, bool)) ([]
2121

2222
lines := []string{}
2323
scanner := bufio.NewScanner(fh)
24-
currentLine := 0
2524
utf8bom := []byte{0xEF, 0xBB, 0xBF}
26-
for scanner.Scan() {
25+
for currentLine := 1; scanner.Scan(); currentLine++ {
2726
scannedBytes := scanner.Bytes()
2827
if !utf8.Valid(scannedBytes) {
29-
return []string{}, fmt.Errorf("env file %s contains invalid utf8 bytes at line %d: %v", filename, currentLine+1, scannedBytes)
28+
return []string{}, fmt.Errorf("env file %s contains invalid utf8 bytes at line %d: %v", filename, currentLine, scannedBytes)
3029
}
3130
// We trim UTF8 BOM
32-
if currentLine == 0 {
31+
if currentLine == 1 {
3332
scannedBytes = bytes.TrimPrefix(scannedBytes, utf8bom)
3433
}
35-
// trim the line from all leading whitespace first
34+
// trim the line from all leading whitespace first. trailing whitespace
35+
// is part of the value, and is kept unmodified.
3636
line := strings.TrimLeftFunc(string(scannedBytes), unicode.IsSpace)
37-
currentLine++
38-
// line is not empty, and not starting with '#'
39-
if len(line) > 0 && !strings.HasPrefix(line, "#") {
40-
variable, value, hasValue := strings.Cut(line, "=")
4137

42-
// trim the front of a variable, but nothing else
43-
variable = strings.TrimLeft(variable, whiteSpaces)
44-
if strings.ContainsAny(variable, whiteSpaces) {
45-
return []string{}, fmt.Errorf("variable '%s' contains whitespaces", variable)
46-
}
47-
if len(variable) == 0 {
48-
return []string{}, fmt.Errorf("no variable name on line '%s'", line)
49-
}
38+
if len(line) == 0 || line[0] == '#' {
39+
// skip empty lines and comments (lines starting with '#')
40+
continue
41+
}
42+
43+
key, _, hasValue := strings.Cut(line, "=")
44+
if len(key) == 0 {
45+
return []string{}, fmt.Errorf("no variable name on line '%s'", line)
46+
}
47+
48+
// leading whitespace was already removed from the line, but
49+
// variables are not allowed to contain whitespace or have
50+
// trailing whitespace.
51+
if strings.ContainsAny(key, whiteSpaces) {
52+
return []string{}, fmt.Errorf("variable '%s' contains whitespaces", key)
53+
}
54+
55+
if hasValue {
56+
// key/value pair is valid and has a value; add the line as-is.
57+
lines = append(lines, line)
58+
continue
59+
}
5060

51-
if hasValue {
52-
// pass the value through, no trimming
53-
lines = append(lines, variable+"="+value)
54-
} else {
55-
var present bool
56-
if emptyFn != nil {
57-
value, present = emptyFn(line)
58-
}
59-
if present {
60-
// if only a pass-through variable is given, clean it up.
61-
lines = append(lines, strings.TrimSpace(variable)+"="+value)
62-
}
61+
if lookupFn != nil {
62+
// No value given; try to look up the value. The value may be
63+
// empty but if no value is found, the key is omitted.
64+
if value, found := lookupFn(line); found {
65+
lines = append(lines, key+"="+value)
6366
}
6467
}
6568
}

0 commit comments

Comments
 (0)