Fix merge anchor traversing

- Allow inline maps instead of just aliases
- Disallow nested sequences
- Disallow other types

Closes #2386
This commit is contained in:
Steven WdV 2025-06-13 19:08:36 +02:00
parent 40808838ba
commit 162ea5437c
No known key found for this signature in database
2 changed files with 39 additions and 7 deletions

View File

@ -295,17 +295,26 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, node *CandidateNode, wante
func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, value *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
switch value.Kind {
case AliasNode:
if value.Alias.Kind != MappingNode {
return fmt.Errorf("can only use merge anchors with maps (!!map), but got %v", value.Alias.Tag)
}
return doTraverseMap(newMatches, value.Alias, wantedKey, prefs, splat)
return traverseMergeAnchor(newMatches, value.Alias, wantedKey, prefs, splat)
case MappingNode:
return doTraverseMap(newMatches, value, wantedKey, prefs, splat)
case SequenceNode:
for _, childValue := range value.Content {
err := traverseMergeAnchor(newMatches, childValue, wantedKey, prefs, splat)
if childValue.Kind == AliasNode {
childValue = childValue.Alias
}
if childValue.Kind != MappingNode {
return fmt.Errorf(
"can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got sequence containing %v",
childValue.Tag)
}
err := doTraverseMap(newMatches, childValue, wantedKey, prefs, splat)
if err != nil {
return err
}
}
default:
return fmt.Errorf("can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got %v", value.Tag)
}
return nil
}

View File

@ -25,7 +25,7 @@ foobar:
thing: foobar_thing
`
// cannot use merge anchors with arrays
// cannot use merge anchors with arrays of non-maps
var badAliasSample = `
_common: &common-docker-file
- FROM ubuntu:18.04
@ -365,6 +365,22 @@ var traversePathOperatorScenarios = []expressionScenario{
"D0, P[0], (!!null)::null\n",
},
},
{
skipDoc: true,
document: `{<<: {a: 42}}`,
expression: `.a`,
expected: []string{
"D0, P[<< a], (!!int)::42\n",
},
},
{
skipDoc: true,
document: `{<<: [{a: 42}]}`,
expression: `.a`,
expected: []string{
"D0, P[<< 0 a], (!!int)::42\n",
},
},
{
skipDoc: true,
document: mergeDocSample,
@ -553,9 +569,16 @@ var traversePathOperatorScenarios = []expressionScenario{
skipDoc: true,
document: badAliasSample,
expression: ".steps[]",
expectedError: "can only use merge anchors with maps (!!map), but got !!seq",
expectedError: "can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got sequence containing !!str",
skipForGoccy: true, // throws an error on parsing, that's fine
},
{
skipDoc: true,
document: `{<<: 42}`,
expression: ".[]",
expectedError: "can only use merge anchors with maps (!!map) or sequences (!!seq) of maps, but got !!int",
skipForGoccy: true,
},
}
func TestTraversePathOperatorScenarios(t *testing.T) {