fix: correct visitMappingNodeFields

This commit adjusts visitMappingNodeFields so that it no longer assumes
the mapping node has unique keys.
This commit is contained in:
Ed Overton
2022-12-22 11:51:15 -05:00
parent 20b0d3c7ce
commit a0e94c1642
2 changed files with 25 additions and 13 deletions

View File

@@ -647,16 +647,16 @@ func (s MapEntrySetter) Filter(rn *RNode) (*RNode, error) {
} }
content := rn.Content() content := rn.Content()
stillMissing := true fieldStillNotFound := true
visitFieldsWhileTrue(content, func(key, value *yaml.Node, keyIndex int) bool { visitFieldsWhileTrue(content, func(key, value *yaml.Node, keyIndex int) bool {
if key.Value == s.Name { if key.Value == s.Name {
content[keyIndex] = s.Key.YNode() content[keyIndex] = s.Key.YNode()
content[keyIndex+1] = s.Value.YNode() content[keyIndex+1] = s.Value.YNode()
stillMissing = false fieldStillNotFound = false
} }
return stillMissing return fieldStillNotFound
}) })
if !stillMissing { if !fieldStillNotFound {
return rn, nil return rn, nil
} }

View File

@@ -539,7 +539,7 @@ func (rn *RNode) getMapFromMeta(fName string, fields ...string) map[string]strin
// fName is found in metadata; create the map from its content // fName is found in metadata; create the map from its content
expectedSize := len(fields) expectedSize := len(fields)
if expectedSize == 0 { if expectedSize == 0 {
expectedSize = len(fNameValue.Content) / 2 expectedSize = len(fNameValue.Content) / 2 //nolint: gomnd
} }
result = make(map[string]string, expectedSize) result = make(map[string]string, expectedSize)
@@ -772,7 +772,7 @@ func (rn *RNode) VisitFields(fn func(node *MapNode) error) error {
// visitMappingNodeFields calls fn for fields in the content, in content order. // visitMappingNodeFields calls fn for fields in the content, in content order.
// The caller is responsible to ensure the node is a mapping node. If fieldNames // The caller is responsible to ensure the node is a mapping node. If fieldNames
// are specified, then fn is called only for the fields that match the given // are specified, then fn is called only for the fields that match the given
// fieldNames. fieldNames must contain unique values. // fieldNames.
func visitMappingNodeFields(content []*yaml.Node, fn func(key, value *yaml.Node), fieldNames ...string) { func visitMappingNodeFields(content []*yaml.Node, fn func(key, value *yaml.Node), fieldNames ...string) {
switch len(fieldNames) { switch len(fieldNames) {
case 0: // visit all fields case 0: // visit all fields
@@ -780,19 +780,31 @@ func visitMappingNodeFields(content []*yaml.Node, fn func(key, value *yaml.Node)
fn(key, value) fn(key, value)
return true return true
}) })
default: // visit specified fields case 1: // visit single field
// assumption: fields in content have unique names
found := 0
visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool { visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
if key == nil { if key == nil {
return true return true
} }
if !sliceutil.Contains(fieldNames, key.Value) { if fieldNames[0] == key.Value {
fn(key, value)
return false
}
return true
})
default: // visit specified fields
fieldsStillToVisit := make(map[string]bool, len(fieldNames))
for _, fieldName := range fieldNames {
fieldsStillToVisit[fieldName] = true
}
visitFieldsWhileTrue(content, func(key, value *yaml.Node, _ int) bool {
if key == nil {
return true return true
} }
fn(key, value) if fieldsStillToVisit[key.Value] {
found++ fn(key, value)
return found < len(fieldNames) delete(fieldsStillToVisit, key.Value)
}
return len(fieldsStillToVisit) > 0
}) })
} }
} }