diff --git a/pkg/yqlib/data_tree_navigator.go b/pkg/yqlib/data_tree_navigator.go index a305b602..70078425 100644 --- a/pkg/yqlib/data_tree_navigator.go +++ b/pkg/yqlib/data_tree_navigator.go @@ -26,6 +26,17 @@ func (d *dataTreeNavigator) DeeplyAssign(context Context, path []interface{}, rh assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}} + if rhsCandidateNode.Kind == MappingNode { + log.Debug("[DataTreeNavigator] DeeplyAssign: deeply merging object") + // if the rhs is a map, we need to deeply merge it in. + // otherwise we'll clobber any existing fields + assignmentOp = &Operation{OperationType: multiplyAssignOpType, Preferences: multiplyPreferences{ + AppendArrays: true, + TraversePrefs: traversePreferences{DontFollowAlias: true}, + AssignPrefs: assignPreferences{}, + }} + } + rhsOp := &Operation{OperationType: valueOpType, CandidateNode: rhsCandidateNode} assignmentOpNode := &ExpressionNode{ diff --git a/pkg/yqlib/decoder_toml.go b/pkg/yqlib/decoder_toml.go index 68181596..1066a89c 100644 --- a/pkg/yqlib/decoder_toml.go +++ b/pkg/yqlib/decoder_toml.go @@ -56,7 +56,7 @@ func (dec *tomlDecoder) getFullPath(tomlNode *toml.Node) []interface{} { func (dec *tomlDecoder) processKeyValueIntoMap(rootMap *CandidateNode, tomlNode *toml.Node) error { value := tomlNode.Value() path := dec.getFullPath(value.Next()) - log.Debug("!!!processKeyValueIntoMap: %v", path) + log.Debug("[DecoderTOML] processKeyValueIntoMap: %v", path) valueNode, err := dec.decodeNode(value) if err != nil { @@ -70,14 +70,14 @@ func (dec *tomlDecoder) processKeyValueIntoMap(rootMap *CandidateNode, tomlNode } func (dec *tomlDecoder) decodeKeyValuesIntoMap(rootMap *CandidateNode, tomlNode *toml.Node) (bool, error) { - log.Debug("!! DECODE_KV_INTO_MAP -- processing first (current) entry") + log.Debug("[DecoderTOML] decodeKeyValuesIntoMap -- processing first (current) entry") if err := dec.processKeyValueIntoMap(rootMap, tomlNode); err != nil { return false, err } for dec.parser.NextExpression() { nextItem := dec.parser.Expression() - log.Debug("!! DECODE_KV_INTO_MAP -- next exp, its a %v", nextItem.Kind) + log.Debug("[DecoderTOML] decodeKeyValuesIntoMap -- next exp, its a %v", nextItem.Kind) if nextItem.Kind == toml.KeyValue { if err := dec.processKeyValueIntoMap(rootMap, nextItem); err != nil { @@ -249,7 +249,7 @@ func (dec *tomlDecoder) Decode() (*CandidateNode, error) { func (dec *tomlDecoder) processTopLevelNode(currentNode *toml.Node) (bool, error) { var runAgainstCurrentExp bool var err error - log.Debug("!!!!!!!!!!!!Going to process %v state is current %v", currentNode.Kind, NodeToString(dec.rootMap)) + log.Debug("[DecoderTOML] processTopLevelNode: Going to process %v state is current %v", currentNode.Kind, NodeToString(dec.rootMap)) if currentNode.Kind == toml.Table { runAgainstCurrentExp, err = dec.processTable(currentNode) } else if currentNode.Kind == toml.ArrayTable { @@ -258,14 +258,14 @@ func (dec *tomlDecoder) processTopLevelNode(currentNode *toml.Node) (bool, error runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(dec.rootMap, currentNode) } - log.Debug("!!!!!!!!!!!!DONE Processing state is now %v", NodeToString(dec.rootMap)) + log.Debug("[DecoderTOML] processTopLevelNode: DONE Processing state is now %v", NodeToString(dec.rootMap)) return runAgainstCurrentExp, err } func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) { - log.Debug("!!! processing table") + log.Debug("[DecoderTOML] Enter processTable") fullPath := dec.getFullPath(currentNode.Child()) - log.Debug("!!!fullpath: %v", fullPath) + log.Debug("[DecoderTOML] fullpath: %v", fullPath) tableNodeValue := &CandidateNode{ Kind: MappingNode, @@ -302,6 +302,7 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) { } func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *CandidateNode) error { + log.Debug("[DecoderTOML] arrayAppend to path: %v,%v", path, NodeToString(rhsNode)) rhsCandidateNode := &CandidateNode{ Kind: SequenceNode, Tag: "!!seq", @@ -323,9 +324,9 @@ func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode } func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error) { - log.Debug("!!! processing table") + log.Debug("[DecoderTOML] Entering processArrayTable") fullPath := dec.getFullPath(currentNode.Child()) - log.Debug("!!!fullpath: %v", fullPath) + log.Debug("[DecoderTOML] Fullpath: %v", fullPath) // need to use the array append exp to add another entry to // this array: fullpath += [ thing ] diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index 01562fd8..b6f37aa1 100644 --- a/pkg/yqlib/operators_test.go +++ b/pkg/yqlib/operators_test.go @@ -32,7 +32,7 @@ type expressionScenario struct { } func TestMain(m *testing.M) { - logging.SetLevel(logging.ERROR, "") + logging.SetLevel(logging.DEBUG, "") Now = func() time.Time { return time.Date(2021, time.May, 19, 1, 2, 3, 4, time.UTC) } diff --git a/pkg/yqlib/toml_test.go b/pkg/yqlib/toml_test.go index fcbea8a1..0dda9773 100644 --- a/pkg/yqlib/toml_test.go +++ b/pkg/yqlib/toml_test.go @@ -16,6 +16,19 @@ name = "Tom Preston-Werner" age = 36 ` +var tableArrayBeforeOwners = ` +[[owner.addresses]] +street = "first street" + +[owner] +name = "Tom Preston-Werner" +` +var expectedTableArrayBeforeOwners = `owner: + addresses: + - street: first street + name: Tom Preston-Werner +` + var sampleTableExpected = `var: x owner: contact: @@ -74,6 +87,13 @@ var tomlScenarios = []formatScenario{ expected: "", scenarioType: "decode", }, + { + skipDoc: true, + description: "table array before owners", + input: tableArrayBeforeOwners, + expected: expectedTableArrayBeforeOwners, + scenarioType: "decode", + }, { skipDoc: true, description: "datetime",