From 35fd5b7ae42cad5e35d9cebdc0eb84ff1b1ec802 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Sat, 11 Jan 2020 19:30:27 +1100 Subject: [PATCH] Extracted out is path expression checking logic --- pkg/yqlib/data_navigator.go | 5 ++--- pkg/yqlib/delete_navigation_strategy.go | 1 + .../filter_matching_node_navigation_strategy.go | 1 + pkg/yqlib/lib.go | 3 ++- pkg/yqlib/navigation_strategy.go | 13 ++++++++----- pkg/yqlib/path_parser.go | 5 +++++ pkg/yqlib/read_navigation_strategy.go | 1 + pkg/yqlib/update_navigation_strategy.go | 1 + 8 files changed, 21 insertions(+), 9 deletions(-) diff --git a/pkg/yqlib/data_navigator.go b/pkg/yqlib/data_navigator.go index 8dedf9a8..b3932163 100644 --- a/pkg/yqlib/data_navigator.go +++ b/pkg/yqlib/data_navigator.go @@ -2,7 +2,6 @@ package yqlib import ( "strconv" - "strings" errors "github.com/pkg/errors" yaml "gopkg.in/yaml.v3" @@ -70,7 +69,7 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathSt return n.recurseMap(value, head, tail, pathStack) case yaml.SequenceNode: log.Debug("its a sequence of %v things!", len(value.Content)) - if head == "*" || head == "**" || strings.Contains(head, "==") { + if n.navigationStrategy.GetPathParser().IsPathExpression(head) { return n.splatArray(value, head, tail, pathStack) } else if head == "+" { return n.appendArray(value, head, tail, pathStack) @@ -117,7 +116,7 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pat return errorVisiting } - if traversedEntry || head == "*" || head == "**" || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) { + if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) { return nil } diff --git a/pkg/yqlib/delete_navigation_strategy.go b/pkg/yqlib/delete_navigation_strategy.go index fc83c9e2..becad835 100644 --- a/pkg/yqlib/delete_navigation_strategy.go +++ b/pkg/yqlib/delete_navigation_strategy.go @@ -10,6 +10,7 @@ func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy { parser := NewPathParser() return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: parser, followAlias: func(nodeContext NodeContext) bool { return false }, diff --git a/pkg/yqlib/filter_matching_node_navigation_strategy.go b/pkg/yqlib/filter_matching_node_navigation_strategy.go index dde3b8a3..ad4ede0c 100644 --- a/pkg/yqlib/filter_matching_node_navigation_strategy.go +++ b/pkg/yqlib/filter_matching_node_navigation_strategy.go @@ -3,6 +3,7 @@ package yqlib func FilterMatchingNodesNavigationStrategy(value string) NavigationStrategy { return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: NewPathParser(), followAlias: func(nodeContext NodeContext) bool { return true }, diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 108ef3ac..196e3ddf 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -74,7 +74,8 @@ func guessKind(head string, tail []string, guess yaml.Kind) yaml.Kind { if tail[0] == "+" || errorParsingInt == nil { return yaml.SequenceNode } - if (tail[0] == "*" || tail[0] == "**" || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) { + pathParser := NewPathParser() + if (pathParser.IsPathExpression(tail[0]) || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) { return guess } if guess == yaml.AliasNode { diff --git a/pkg/yqlib/navigation_strategy.go b/pkg/yqlib/navigation_strategy.go index a5ae1f1f..892988a7 100644 --- a/pkg/yqlib/navigation_strategy.go +++ b/pkg/yqlib/navigation_strategy.go @@ -36,6 +36,7 @@ type NavigationStrategy interface { ShouldTraverse(nodeContext NodeContext, nodeKey string) bool GetVisitedNodes() []*NodeContext DebugVisitedNodes() + GetPathParser() PathParser } type NavigationStrategyImpl struct { @@ -44,6 +45,11 @@ type NavigationStrategyImpl struct { visit func(nodeContext NodeContext) error shouldVisitExtraFn func(nodeContext NodeContext) bool visitedNodes []*NodeContext + pathParser PathParser +} + +func (ns *NavigationStrategyImpl) GetPathParser() PathParser { + return ns.pathParser } func (ns *NavigationStrategyImpl) GetVisitedNodes() []*NodeContext { @@ -68,10 +74,8 @@ func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKe return false } - parser := NewPathParser() - return (nodeKey == "<<" && ns.FollowAlias(nodeContext)) || (nodeKey != "<<" && - parser.MatchesNextPathElement(nodeContext, nodeKey)) + ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey)) } func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool { @@ -88,11 +92,10 @@ func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool { nodeKey := fmt.Sprintf("%v", pathStack[len(pathStack)-1]) log.Debug("nodeKey: %v, nodeContext.Head: %v", nodeKey, nodeContext.Head) - parser := NewPathParser() // only visit aliases if its an exact match return ((nodeKey == "<<" && nodeContext.Head == "<<") || (nodeKey != "<<" && - parser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext)) + ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext)) } func (ns *NavigationStrategyImpl) Visit(nodeContext NodeContext) error { diff --git a/pkg/yqlib/path_parser.go b/pkg/yqlib/path_parser.go index 112d7912..38464522 100644 --- a/pkg/yqlib/path_parser.go +++ b/pkg/yqlib/path_parser.go @@ -8,6 +8,7 @@ import ( type PathParser interface { ParsePath(path string) []string MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool + IsPathExpression(pathElement string) bool } type pathParser struct{} @@ -16,6 +17,10 @@ func NewPathParser() PathParser { return &pathParser{} } +func (p *pathParser) IsPathExpression(pathElement string) bool { + return pathElement == "*" || pathElement == "**" || strings.Contains(pathElement, "==") +} + /** * node: node that we may traverse/visit * head: path element expression to match against diff --git a/pkg/yqlib/read_navigation_strategy.go b/pkg/yqlib/read_navigation_strategy.go index 70ecfb7d..4040e506 100644 --- a/pkg/yqlib/read_navigation_strategy.go +++ b/pkg/yqlib/read_navigation_strategy.go @@ -3,6 +3,7 @@ package yqlib func ReadNavigationStrategy() NavigationStrategy { return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: NewPathParser(), followAlias: func(nodeContext NodeContext) bool { return true }, diff --git a/pkg/yqlib/update_navigation_strategy.go b/pkg/yqlib/update_navigation_strategy.go index e6be8b71..9cb4ac92 100644 --- a/pkg/yqlib/update_navigation_strategy.go +++ b/pkg/yqlib/update_navigation_strategy.go @@ -3,6 +3,7 @@ package yqlib func UpdateNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy { return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: NewPathParser(), followAlias: func(nodeContext NodeContext) bool { return false },