mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Delete now works with deep splat
This commit is contained in:
parent
b9e304e7a4
commit
71f5f76213
@ -100,6 +100,29 @@ b:
|
|||||||
test.AssertResult(t, expectedOutput, result.Output)
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteDeepSplatArrayYaml(t *testing.T) {
|
||||||
|
content := `thing: 123
|
||||||
|
b:
|
||||||
|
hi:
|
||||||
|
- thing: item1
|
||||||
|
name: fred
|
||||||
|
`
|
||||||
|
filename := test.WriteTempYamlFile(content)
|
||||||
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, fmt.Sprintf("delete %s **.thing", filename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOutput := `b:
|
||||||
|
hi:
|
||||||
|
- name: fred
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDeleteSplatPrefixYaml(t *testing.T) {
|
func TestDeleteSplatPrefixYaml(t *testing.T) {
|
||||||
content := `a: 2
|
content := `a: 2
|
||||||
b:
|
b:
|
||||||
|
@ -24,6 +24,7 @@ func NewDataNavigator(NavigationStrategy NavigationStrategy) DataNavigator {
|
|||||||
func (n *navigator) Traverse(value *yaml.Node, path []interface{}) error {
|
func (n *navigator) Traverse(value *yaml.Node, path []interface{}) error {
|
||||||
realValue := value
|
realValue := value
|
||||||
emptyArray := make([]interface{}, 0)
|
emptyArray := make([]interface{}, 0)
|
||||||
|
log.Debugf("Traversing path %v", pathStackToString(path))
|
||||||
if realValue.Kind == yaml.DocumentNode {
|
if realValue.Kind == yaml.DocumentNode {
|
||||||
log.Debugf("its a document! returning the first child")
|
log.Debugf("its a document! returning the first child")
|
||||||
return n.doTraverse(value.Content[0], "", path, emptyArray)
|
return n.doTraverse(value.Content[0], "", path, emptyArray)
|
||||||
@ -68,6 +69,16 @@ func (n *navigator) getOrReplace(original *yaml.Node, expectedKind yaml.Kind) *y
|
|||||||
|
|
||||||
func (n *navigator) recurse(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error {
|
func (n *navigator) recurse(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error {
|
||||||
log.Debug("recursing, processing %v, pathStack %v", head, pathStackToString(pathStack))
|
log.Debug("recursing, processing %v, pathStack %v", head, pathStackToString(pathStack))
|
||||||
|
|
||||||
|
nodeContext := NewNodeContext(value, head, tail, pathStack)
|
||||||
|
|
||||||
|
if head == "**" && !n.navigationStrategy.ShouldOnlyDeeplyVisitLeaves(nodeContext) {
|
||||||
|
errorVisitingDeeply := n.navigationStrategy.Visit(nodeContext)
|
||||||
|
if errorVisitingDeeply != nil {
|
||||||
|
return errorVisitingDeeply
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch value.Kind {
|
switch value.Kind {
|
||||||
case yaml.MappingNode:
|
case yaml.MappingNode:
|
||||||
log.Debug("its a map with %v entries", len(value.Content)/2)
|
log.Debug("its a map with %v entries", len(value.Content)/2)
|
||||||
@ -85,20 +96,20 @@ func (n *navigator) recurse(value *yaml.Node, head interface{}, tail []interface
|
|||||||
if head == "+" {
|
if head == "+" {
|
||||||
return n.appendArray(value, head, tail, pathStack)
|
return n.appendArray(value, head, tail, pathStack)
|
||||||
} else if len(value.Content) == 0 && head == "**" {
|
} else if len(value.Content) == 0 && head == "**" {
|
||||||
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
|
return n.navigationStrategy.Visit(nodeContext)
|
||||||
}
|
}
|
||||||
return n.splatArray(value, head, tail, pathStack)
|
return n.splatArray(value, head, tail, pathStack)
|
||||||
}
|
}
|
||||||
case yaml.AliasNode:
|
case yaml.AliasNode:
|
||||||
log.Debug("its an alias!")
|
log.Debug("its an alias!")
|
||||||
DebugNode(value.Alias)
|
DebugNode(value.Alias)
|
||||||
if n.navigationStrategy.FollowAlias(NewNodeContext(value, head, tail, pathStack)) {
|
if n.navigationStrategy.FollowAlias(nodeContext) {
|
||||||
log.Debug("following the alias")
|
log.Debug("following the alias")
|
||||||
return n.recurse(value.Alias, head, tail, pathStack)
|
return n.recurse(value.Alias, head, tail, pathStack)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
|
return n.navigationStrategy.Visit(nodeContext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,12 @@ func DeleteNavigationStrategy(pathElementToDelete interface{}) NavigationStrateg
|
|||||||
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
|
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
shouldOnlyDeeplyVisitLeaves: func(nodeContext NodeContext) bool {
|
||||||
|
return false
|
||||||
|
},
|
||||||
visit: func(nodeContext NodeContext) error {
|
visit: func(nodeContext NodeContext) error {
|
||||||
node := nodeContext.Node
|
node := nodeContext.Node
|
||||||
log.Debug("need to find and delete %v in here", pathElementToDelete)
|
log.Debug("need to find and delete %v in here (%v)", pathElementToDelete, pathStackToString(nodeContext.PathStack))
|
||||||
DebugNode(node)
|
DebugNode(node)
|
||||||
if node.Kind == yaml.SequenceNode {
|
if node.Kind == yaml.SequenceNode {
|
||||||
newContent := deleteFromArray(parser, node.Content, nodeContext.PathStack, pathElementToDelete)
|
newContent := deleteFromArray(parser, node.Content, nodeContext.PathStack, pathElementToDelete)
|
||||||
|
@ -35,6 +35,8 @@ type NavigationStrategy interface {
|
|||||||
// we use it to match against the pathExpression in head.
|
// we use it to match against the pathExpression in head.
|
||||||
ShouldTraverse(nodeContext NodeContext, nodeKey string) bool
|
ShouldTraverse(nodeContext NodeContext, nodeKey string) bool
|
||||||
ShouldDeeplyTraverse(nodeContext NodeContext) bool
|
ShouldDeeplyTraverse(nodeContext NodeContext) bool
|
||||||
|
// when deeply traversing, should we visit all matching nodes, or just leaves?
|
||||||
|
ShouldOnlyDeeplyVisitLeaves(NodeContext) bool
|
||||||
GetVisitedNodes() []*NodeContext
|
GetVisitedNodes() []*NodeContext
|
||||||
DebugVisitedNodes()
|
DebugVisitedNodes()
|
||||||
GetPathParser() PathParser
|
GetPathParser() PathParser
|
||||||
@ -46,6 +48,7 @@ type NavigationStrategyImpl struct {
|
|||||||
visit func(nodeContext NodeContext) error
|
visit func(nodeContext NodeContext) error
|
||||||
shouldVisitExtraFn func(nodeContext NodeContext) bool
|
shouldVisitExtraFn func(nodeContext NodeContext) bool
|
||||||
shouldDeeplyTraverse func(nodeContext NodeContext) bool
|
shouldDeeplyTraverse func(nodeContext NodeContext) bool
|
||||||
|
shouldOnlyDeeplyVisitLeaves func(nodeContext NodeContext) bool
|
||||||
visitedNodes []*NodeContext
|
visitedNodes []*NodeContext
|
||||||
pathParser PathParser
|
pathParser PathParser
|
||||||
}
|
}
|
||||||
@ -70,6 +73,10 @@ func (ns *NavigationStrategyImpl) ShouldDeeplyTraverse(nodeContext NodeContext)
|
|||||||
return ns.shouldDeeplyTraverse(nodeContext)
|
return ns.shouldDeeplyTraverse(nodeContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ns *NavigationStrategyImpl) ShouldOnlyDeeplyVisitLeaves(nodeContext NodeContext) bool {
|
||||||
|
return ns.shouldOnlyDeeplyVisitLeaves(nodeContext)
|
||||||
|
}
|
||||||
|
|
||||||
func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKey string) bool {
|
func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKey string) bool {
|
||||||
// we should traverse aliases (if enabled), but not visit them :/
|
// we should traverse aliases (if enabled), but not visit them :/
|
||||||
if len(nodeContext.PathStack) == 0 {
|
if len(nodeContext.PathStack) == 0 {
|
||||||
|
@ -26,5 +26,8 @@ func ReadNavigationStrategy(deeplyTraverseArrays bool) NavigationStrategy {
|
|||||||
}
|
}
|
||||||
return deeplyTraverseArrays || !isInArray
|
return deeplyTraverseArrays || !isInArray
|
||||||
},
|
},
|
||||||
|
shouldOnlyDeeplyVisitLeaves: func(nodeContext NodeContext) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@ func UpdateNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) Navi
|
|||||||
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
|
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
shouldOnlyDeeplyVisitLeaves: func(nodeContext NodeContext) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
visit: func(nodeContext NodeContext) error {
|
visit: func(nodeContext NodeContext) error {
|
||||||
node := nodeContext.Node
|
node := nodeContext.Node
|
||||||
changesToApply := updateCommand.Value
|
changesToApply := updateCommand.Value
|
||||||
|
Loading…
Reference in New Issue
Block a user