From 02258fbaae6830eb48d895188f3bd0721eed8bf7 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Tue, 4 Feb 2020 14:10:12 +1100 Subject: [PATCH] Fixed deep splatting merge anchors - dont visit twice --- cmd/commands_test.go | 26 ++++++++++++++++++++++++++ pkg/yqlib/data_navigator.go | 7 ++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd/commands_test.go b/cmd/commands_test.go index d3bb9d5..a9d70fd 100644 --- a/cmd/commands_test.go +++ b/cmd/commands_test.go @@ -247,6 +247,32 @@ func TestReadAnchorsWithKeyAndValueCmd(t *testing.T) { test.AssertResult(t, "foobar.a: 1\n", result.Output) } +func TestReadAllAnchorsWithKeyAndValueCmd(t *testing.T) { + cmd := getRootCommand() + result := test.RunCmd(cmd, "read -p pv ../examples/merge-anchor.yaml **") + if result.Error != nil { + t.Error(result.Error) + } + expectedOutput := `foo.a: original +foo.thing: coolasdf +foo.thirsty: yep +bar.b: 2 +bar.thing: coconut +bar.c: oldbar +foobarList.c: newbar +foobarList.b: 2 +foobarList.thing: coconut +foobarList.a: original +foobarList.thirsty: yep +foobar.thirty: well beyond +foobar.thing: ice +foobar.c: 3 +foobar.a: original +foobar.thirsty: yep +` + test.AssertResult(t, expectedOutput, result.Output) +} + func TestReadMergeAnchorsOriginalCmd(t *testing.T) { cmd := getRootCommand() result := test.RunCmd(cmd, "read ../examples/merge-anchor.yaml foobar.a") diff --git a/pkg/yqlib/data_navigator.go b/pkg/yqlib/data_navigator.go index 0ff63b2..0a053b7 100644 --- a/pkg/yqlib/data_navigator.go +++ b/pkg/yqlib/data_navigator.go @@ -35,7 +35,9 @@ func (n *navigator) doTraverse(value *yaml.Node, head string, tail []string, pat DebugNode(value) var errorDeepSplatting error if head == "**" && value.Kind != yaml.ScalarNode { - errorDeepSplatting = n.recurse(value, head, tail, pathStack) + if len(pathStack) == 0 || pathStack[len(pathStack)-1] != "<<" { + errorDeepSplatting = n.recurse(value, head, tail, pathStack) + } // ignore errors here, we are deep splatting so we may accidently give a string key // to an array sequence if len(tail) > 0 { @@ -93,10 +95,9 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathSt func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pathStack []interface{}) error { traversedEntry := false errorVisiting := n.visitMatchingEntries(value, head, tail, pathStack, func(contents []*yaml.Node, indexInMap int) error { - log.Debug("recurseMap: visitMatchingEntries") + log.Debug("recurseMap: visitMatchingEntries for %v", contents[indexInMap].Value) n.navigationStrategy.DebugVisitedNodes() newPathStack := append(pathStack, contents[indexInMap].Value) - log.Debug("appended %v", contents[indexInMap].Value) n.navigationStrategy.DebugVisitedNodes() log.Debug("should I traverse? head: %v, path: %v", head, pathStackToString(newPathStack)) DebugNode(value)