Merge pull request #5496 from thaJeztah/parseKeyValueFile_refactor

opts: parseKeyValueFile: cleanup and remove redundant trimming
This commit is contained in:
Sebastiaan van Stijn 2024-10-04 12:12:09 +02:00 committed by GitHub
commit 9dee12ff69
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 33 additions and 30 deletions

View File

@ -12,7 +12,7 @@ import (
const whiteSpaces = " \t" 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) fh, err := os.Open(filename)
if err != nil { if err != nil {
return []string{}, err return []string{}, err
@ -21,45 +21,48 @@ func parseKeyValueFile(filename string, emptyFn func(string) (string, bool)) ([]
lines := []string{} lines := []string{}
scanner := bufio.NewScanner(fh) scanner := bufio.NewScanner(fh)
currentLine := 0
utf8bom := []byte{0xEF, 0xBB, 0xBF} utf8bom := []byte{0xEF, 0xBB, 0xBF}
for scanner.Scan() { for currentLine := 1; scanner.Scan(); currentLine++ {
scannedBytes := scanner.Bytes() scannedBytes := scanner.Bytes()
if !utf8.Valid(scannedBytes) { if !utf8.Valid(scannedBytes) {
return []string{}, fmt.Errorf("env file %s contains invalid utf8 bytes at line %d: %v", filename, currentLine+1, scannedBytes) return []string{}, fmt.Errorf("env file %s contains invalid utf8 bytes at line %d: %v", filename, currentLine, scannedBytes)
} }
// We trim UTF8 BOM // We trim UTF8 BOM
if currentLine == 0 { if currentLine == 1 {
scannedBytes = bytes.TrimPrefix(scannedBytes, utf8bom) scannedBytes = bytes.TrimPrefix(scannedBytes, utf8bom)
} }
// trim the line from all leading whitespace first // trim the line from all leading whitespace first. trailing whitespace
// is part of the value, and is kept unmodified.
line := strings.TrimLeftFunc(string(scannedBytes), unicode.IsSpace) line := strings.TrimLeftFunc(string(scannedBytes), unicode.IsSpace)
currentLine++
// line is not empty, and not starting with '#'
if len(line) > 0 && !strings.HasPrefix(line, "#") {
variable, value, hasValue := strings.Cut(line, "=")
// trim the front of a variable, but nothing else if len(line) == 0 || line[0] == '#' {
variable = strings.TrimLeft(variable, whiteSpaces) // skip empty lines and comments (lines starting with '#')
if strings.ContainsAny(variable, whiteSpaces) { continue
return []string{}, fmt.Errorf("variable '%s' contains whitespaces", variable) }
}
if len(variable) == 0 {
return []string{}, fmt.Errorf("no variable name on line '%s'", line)
}
if hasValue { key, _, hasValue := strings.Cut(line, "=")
// pass the value through, no trimming if len(key) == 0 {
lines = append(lines, variable+"="+value) return []string{}, fmt.Errorf("no variable name on line '%s'", line)
} else { }
var present bool
if emptyFn != nil { // leading whitespace was already removed from the line, but
value, present = emptyFn(line) // variables are not allowed to contain whitespace or have
} // trailing whitespace.
if present { if strings.ContainsAny(key, whiteSpaces) {
// if only a pass-through variable is given, clean it up. return []string{}, fmt.Errorf("variable '%s' contains whitespaces", key)
lines = append(lines, strings.TrimSpace(variable)+"="+value) }
}
if hasValue {
// key/value pair is valid and has a value; add the line as-is.
lines = append(lines, line)
continue
}
if lookupFn != nil {
// No value given; try to look up the value. The value may be
// empty but if no value is found, the key is omitted.
if value, found := lookupFn(line); found {
lines = append(lines, key+"="+value)
} }
} }
} }