Fixed merging arrays with merge anchors #899

This commit is contained in:
Mike Farah 2021-07-22 20:57:47 +10:00
parent 9ec20f8ba2
commit eeac03a437
2 changed files with 26 additions and 4 deletions

View File

@ -31,7 +31,7 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex
(lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) { (lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) {
var newBlank = lhs.CreateChild(nil, &yaml.Node{}) var newBlank = lhs.CreateChild(nil, &yaml.Node{})
log.Debugf("merge - merge lhs into blank")
var newThing, err = mergeObjects(d, context.WritableClone(), newBlank, lhs, multiplyPreferences{}) var newThing, err = mergeObjects(d, context.WritableClone(), newBlank, lhs, multiplyPreferences{})
if err != nil { if err != nil {
return nil, err return nil, err
@ -83,12 +83,13 @@ func multiplyIntegers(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, e
} }
func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) (*CandidateNode, error) { func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) (*CandidateNode, error) {
shouldAppendArrays := preferences.AppendArrays
var results = list.New() var results = list.New()
// shouldn't recurse arrays if appending // only need to recurse the array if we are doing a deep merge
prefs := recursiveDescentPreferences{RecurseArray: !shouldAppendArrays, prefs := recursiveDescentPreferences{RecurseArray: preferences.DeepMergeArrays,
TraversePreferences: traversePreferences{DontFollowAlias: true, IncludeMapKeys: true}} TraversePreferences: traversePreferences{DontFollowAlias: true, IncludeMapKeys: true}}
log.Debugf("merge - preferences.DeepMergeArrays %v", preferences.DeepMergeArrays)
log.Debugf("merge - preferences.AppendArrays %v", preferences.AppendArrays)
err := recursiveDecent(d, results, context.SingleChildContext(rhs), prefs) err := recursiveDecent(d, results, context.SingleChildContext(rhs), prefs)
if err != nil { if err != nil {
return nil, err return nil, err
@ -118,14 +119,22 @@ func applyAssignment(d *dataTreeNavigator, context Context, pathIndexToStartFrom
log.Debugf("merge - applyAssignment lhs %v, rhs: %v", lhs.GetKey(), rhs.GetKey()) log.Debugf("merge - applyAssignment lhs %v, rhs: %v", lhs.GetKey(), rhs.GetKey())
lhsPath := rhs.Path[pathIndexToStartFrom:] lhsPath := rhs.Path[pathIndexToStartFrom:]
log.Debugf("merge - lhsPath %v", lhsPath)
assignmentOp := &Operation{OperationType: assignAttributesOpType} assignmentOp := &Operation{OperationType: assignAttributesOpType}
if shouldAppendArrays && rhs.Node.Kind == yaml.SequenceNode { if shouldAppendArrays && rhs.Node.Kind == yaml.SequenceNode {
assignmentOp.OperationType = addAssignOpType assignmentOp.OperationType = addAssignOpType
log.Debugf("merge - assignmentOp.OperationType = addAssignOpType")
} else if !preferences.DeepMergeArrays && rhs.Node.Kind == yaml.SequenceNode || } else if !preferences.DeepMergeArrays && rhs.Node.Kind == yaml.SequenceNode ||
(rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode) { (rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode) {
assignmentOp.OperationType = assignOpType assignmentOp.OperationType = assignOpType
assignmentOp.UpdateAssign = false assignmentOp.UpdateAssign = false
log.Debugf("merge - rhs.Node.Kind == yaml.SequenceNode: %v", rhs.Node.Kind == yaml.SequenceNode)
log.Debugf("merge - rhs.Node.Kind == yaml.ScalarNode: %v", rhs.Node.Kind == yaml.ScalarNode)
log.Debugf("merge - rhs.Node.Kind == yaml.AliasNode: %v", rhs.Node.Kind == yaml.AliasNode)
log.Debugf("merge - assignmentOp.OperationType = assignOpType, no updateassign")
} else {
log.Debugf("merge - assignmentOp := &Operation{OperationType: assignAttributesOpType}")
} }
rhsOp := &Operation{OperationType: valueOpType, CandidateNode: rhs} rhsOp := &Operation{OperationType: valueOpType, CandidateNode: rhs}

View File

@ -24,6 +24,11 @@ list2:
- "123" - "123"
` `
var mergeArrayWithAnchors = `sample:
- &a
- <<: *a
`
var mergeArraysObjectKeysText = `It's a complex command, the trickyness comes from needing to have the right context in the expressions. var mergeArraysObjectKeysText = `It's a complex command, the trickyness comes from needing to have the right context in the expressions.
First we save the second array into a variable '$two' which lets us reference it later. First we save the second array into a variable '$two' which lets us reference it later.
We then need to update the first array. We will use the relative update (|=) because we need to update relative to the current element of the array in the LHS in the RHS expression. We then need to update the first array. We will use the relative update (|=) because we need to update relative to the current element of the array in the LHS in the RHS expression.
@ -31,6 +36,14 @@ We set the current element of the first array as $cur. Now we multiply (merge) $
` `
var multiplyOperatorScenarios = []expressionScenario{ var multiplyOperatorScenarios = []expressionScenario{
{
skipDoc: true,
document: mergeArrayWithAnchors,
expression: `. * .`,
expected: []string{
"D0, P[], (!!map)::sample:\n - &a\n - !!merge <<: *a\n",
},
},
{ {
description: "Multiply integers", description: "Multiply integers",
expression: `3 * 4`, expression: `3 * 4`,