mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 13:48:06 +00:00
Delete works! needs refactor
This commit is contained in:
parent
707ad09ba5
commit
df52383ffb
@ -1077,7 +1077,7 @@ func TestWriteCmd_SplatMapEmpty(t *testing.T) {
|
|||||||
test.AssertResult(t, expectedOutput, result.Output)
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteYaml(t *testing.T) {
|
func TestDeleteYamlCmd(t *testing.T) {
|
||||||
content := `a: 2
|
content := `a: 2
|
||||||
b:
|
b:
|
||||||
c: things
|
c: things
|
||||||
|
@ -82,13 +82,12 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pat
|
|||||||
|
|
||||||
log.Debug("should I traverse? %v", head)
|
log.Debug("should I traverse? %v", head)
|
||||||
DebugNode(value)
|
DebugNode(value)
|
||||||
newPath := append(pathStack, contents[indexInMap].Value)
|
newPathStack := append(pathStack, contents[indexInMap].Value)
|
||||||
|
if n.navigationSettings.ShouldTraverse(contents[indexInMap+1], head, tail, newPathStack, contents[indexInMap].Value) == true {
|
||||||
if n.navigationSettings.ShouldTraverse(contents[indexInMap+1], head, tail, newPath) == true {
|
|
||||||
log.Debug("yep!")
|
log.Debug("yep!")
|
||||||
traversedEntry = true
|
traversedEntry = true
|
||||||
contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(tail, contents[indexInMap+1].Kind))
|
contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(tail, contents[indexInMap+1].Kind))
|
||||||
return n.doTraverse(contents[indexInMap+1], head, tail, newPath)
|
return n.doTraverse(contents[indexInMap+1], head, tail, newPathStack)
|
||||||
} else {
|
} else {
|
||||||
log.Debug("nope not traversing")
|
log.Debug("nope not traversing")
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func DeleteNavigationSettings(lastBit string) NavigationSettings {
|
func DeleteNavigationSettings(lastBit string) NavigationSettings {
|
||||||
|
parser := NewPathParser()
|
||||||
return &NavigationSettingsImpl{
|
return &NavigationSettingsImpl{
|
||||||
visitedNodes: []*VisitedNode{},
|
visitedNodes: []*VisitedNode{},
|
||||||
followAlias: func(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool {
|
followAlias: func(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool {
|
||||||
@ -16,7 +17,7 @@ func DeleteNavigationSettings(lastBit string) NavigationSettings {
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
visit: func(node *yaml.Node, head string, tail []string, pathStack []interface{}) error {
|
visit: func(node *yaml.Node, head string, tail []string, pathStack []interface{}) error {
|
||||||
log.Debug("need to find %v in here", lastBit)
|
log.Debug("need to find and delete %v in here", lastBit)
|
||||||
DebugNode(node)
|
DebugNode(node)
|
||||||
if node.Kind == yaml.SequenceNode {
|
if node.Kind == yaml.SequenceNode {
|
||||||
newContent, errorDeleting := deleteFromArray(node.Content, lastBit)
|
newContent, errorDeleting := deleteFromArray(node.Content, lastBit)
|
||||||
@ -25,31 +26,33 @@ func DeleteNavigationSettings(lastBit string) NavigationSettings {
|
|||||||
}
|
}
|
||||||
node.Content = newContent
|
node.Content = newContent
|
||||||
} else if node.Kind == yaml.MappingNode {
|
} else if node.Kind == yaml.MappingNode {
|
||||||
// need to delete in reverse - otherwise the matching indexes
|
node.Content = deleteFromMap(parser, node.Content, pathStack, lastBit)
|
||||||
// become incorrect.
|
|
||||||
// matchingIndices := make([]int, 0)
|
|
||||||
// _, errorVisiting := n.visitMatchingEntries(node, lastBit, []string{}, pathStack, func(matchingNode []*yaml.Node, indexInMap int) error {
|
|
||||||
// matchingIndices = append(matchingIndices, indexInMap)
|
|
||||||
// log.Debug("matchingIndices %v", indexInMap)
|
|
||||||
// return nil
|
|
||||||
// })
|
|
||||||
// log.Debug("delete matching indices now")
|
|
||||||
// log.Debug("%v", matchingIndices)
|
|
||||||
// if errorVisiting != nil {
|
|
||||||
// return errorVisiting
|
|
||||||
// }
|
|
||||||
// for i := len(matchingIndices) - 1; i >= 0; i-- {
|
|
||||||
// indexToDelete := matchingIndices[i]
|
|
||||||
// log.Debug("deleting index %v, %v", indexToDelete, node.Content[indexToDelete].Value)
|
|
||||||
// node.Content = append(node.Content[:indexToDelete], node.Content[indexToDelete+2:]...)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func deleteFromMap(pathParser PathParser, contents []*yaml.Node, pathStack []interface{}, lastBit string) []*yaml.Node {
|
||||||
|
newContents := make([]*yaml.Node, 0)
|
||||||
|
for index := 0; index < len(contents); index = index + 2 {
|
||||||
|
keyNode := contents[index]
|
||||||
|
valueNode := contents[index+1]
|
||||||
|
if pathParser.MatchesNextPathElement(keyNode, lastBit, []string{}, pathStack, keyNode.Value) == false {
|
||||||
|
log.Debug("adding node %v", keyNode.Value)
|
||||||
|
newContents = append(newContents, keyNode, valueNode)
|
||||||
|
} else {
|
||||||
|
log.Debug("skipping node %v", keyNode.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newContents
|
||||||
|
}
|
||||||
|
|
||||||
func deleteFromArray(content []*yaml.Node, lastBit string) ([]*yaml.Node, error) {
|
func deleteFromArray(content []*yaml.Node, lastBit string) ([]*yaml.Node, error) {
|
||||||
|
|
||||||
|
if lastBit == "*" {
|
||||||
|
return make([]*yaml.Node, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
var index, err = strconv.ParseInt(lastBit, 10, 64) // nolint
|
var index, err = strconv.ParseInt(lastBit, 10, 64) // nolint
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return content, err
|
return content, err
|
||||||
|
@ -2,7 +2,6 @@ package yqlib
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@ -18,7 +17,7 @@ type NavigationSettings interface {
|
|||||||
FollowAlias(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool
|
FollowAlias(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool
|
||||||
AutoCreateMap(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool
|
AutoCreateMap(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool
|
||||||
Visit(node *yaml.Node, head string, tail []string, pathStack []interface{}) error
|
Visit(node *yaml.Node, head string, tail []string, pathStack []interface{}) error
|
||||||
ShouldTraverse(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool
|
ShouldTraverse(node *yaml.Node, head string, tail []string, pathStack []interface{}, lastBit string) bool
|
||||||
GetVisitedNodes() []*VisitedNode
|
GetVisitedNodes() []*VisitedNode
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,16 +28,6 @@ type NavigationSettingsImpl struct {
|
|||||||
visitedNodes []*VisitedNode
|
visitedNodes []*VisitedNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func matches(node *yaml.Node, head string) bool {
|
|
||||||
var prefixMatch = strings.TrimSuffix(head, "*")
|
|
||||||
if prefixMatch != head {
|
|
||||||
log.Debug("prefix match, %v", strings.HasPrefix(node.Value, prefixMatch))
|
|
||||||
return strings.HasPrefix(node.Value, prefixMatch)
|
|
||||||
}
|
|
||||||
log.Debug("equals match, %v", node.Value == head)
|
|
||||||
return node.Value == head
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ns *NavigationSettingsImpl) GetVisitedNodes() []*VisitedNode {
|
func (ns *NavigationSettingsImpl) GetVisitedNodes() []*VisitedNode {
|
||||||
return ns.visitedNodes
|
return ns.visitedNodes
|
||||||
}
|
}
|
||||||
@ -51,16 +40,7 @@ func (ns *NavigationSettingsImpl) AutoCreateMap(node *yaml.Node, head string, ta
|
|||||||
return ns.autoCreateMap(node, head, tail, pathStack)
|
return ns.autoCreateMap(node, head, tail, pathStack)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *NavigationSettingsImpl) matchesNextPath(path string, candidate string) bool {
|
func (ns *NavigationSettingsImpl) ShouldTraverse(node *yaml.Node, head string, tail []string, pathStack []interface{}, lastBit string) bool {
|
||||||
var prefixMatch = strings.TrimSuffix(path, "*")
|
|
||||||
if prefixMatch != path {
|
|
||||||
log.Debug("prefix match, %v", strings.HasPrefix(candidate, prefixMatch))
|
|
||||||
return strings.HasPrefix(candidate, prefixMatch)
|
|
||||||
}
|
|
||||||
return candidate == path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ns *NavigationSettingsImpl) ShouldTraverse(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool {
|
|
||||||
// we should traverse aliases (if enabled), but not visit them :/
|
// we should traverse aliases (if enabled), but not visit them :/
|
||||||
if len(pathStack) == 0 {
|
if len(pathStack) == 0 {
|
||||||
return true
|
return true
|
||||||
@ -70,9 +50,10 @@ func (ns *NavigationSettingsImpl) ShouldTraverse(node *yaml.Node, head string, t
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
lastBit := fmt.Sprintf("%v", pathStack[len(pathStack)-1])
|
parser := NewPathParser()
|
||||||
|
|
||||||
return (lastBit == "<<" && ns.FollowAlias(node, head, tail, pathStack)) || (lastBit != "<<" && ns.matchesNextPath(head, lastBit))
|
return (lastBit == "<<" && ns.FollowAlias(node, head, tail, pathStack)) || (lastBit != "<<" &&
|
||||||
|
parser.MatchesNextPathElement(node, head, tail, pathStack, lastBit))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *NavigationSettingsImpl) shouldVisit(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool {
|
func (ns *NavigationSettingsImpl) shouldVisit(node *yaml.Node, head string, tail []string, pathStack []interface{}) bool {
|
||||||
@ -86,8 +67,11 @@ func (ns *NavigationSettingsImpl) shouldVisit(node *yaml.Node, head string, tail
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastBit := fmt.Sprintf("%v", pathStack[len(pathStack)-1])
|
lastBit := fmt.Sprintf("%v", pathStack[len(pathStack)-1])
|
||||||
|
parser := NewPathParser()
|
||||||
|
|
||||||
// only visit aliases if its an exact match
|
// only visit aliases if its an exact match
|
||||||
return (lastBit == "<<" && head == "<<") || (lastBit != "<<" && ns.matchesNextPath(head, lastBit))
|
return (lastBit == "<<" && head == "<<") || (lastBit != "<<" &&
|
||||||
|
parser.MatchesNextPathElement(node, head, tail, pathStack, lastBit))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
package yqlib
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
yaml "gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
type PathParser interface {
|
type PathParser interface {
|
||||||
ParsePath(path string) []string
|
ParsePath(path string) []string
|
||||||
|
MatchesNextPathElement(node *yaml.Node, head string, tail []string, pathStack []interface{}, lastBit string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type pathParser struct{}
|
type pathParser struct{}
|
||||||
@ -10,6 +17,22 @@ func NewPathParser() PathParser {
|
|||||||
return &pathParser{}
|
return &pathParser{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* node: node that we may traverse/visit
|
||||||
|
* head: path element expression to match against
|
||||||
|
* tail: remaining path element expressions
|
||||||
|
* pathStack: stack of actual paths we've matched to get to node
|
||||||
|
* lastBit: actual value of this nodes 'key' or index.
|
||||||
|
*/
|
||||||
|
func (p *pathParser) MatchesNextPathElement(node *yaml.Node, head string, tail []string, pathStack []interface{}, lastBit string) bool {
|
||||||
|
var prefixMatch = strings.TrimSuffix(head, "*")
|
||||||
|
if prefixMatch != head {
|
||||||
|
log.Debug("prefix match, %v", strings.HasPrefix(lastBit, prefixMatch))
|
||||||
|
return strings.HasPrefix(lastBit, prefixMatch)
|
||||||
|
}
|
||||||
|
return lastBit == head
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pathParser) ParsePath(path string) []string {
|
func (p *pathParser) ParsePath(path string) []string {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return []string{}
|
return []string{}
|
||||||
|
Loading…
Reference in New Issue
Block a user