mirror of
https://github.com/taigrr/yq
synced 2025-01-18 04:53:17 -08:00
read command
This commit is contained in:
62
pkg/yqlib/treeops/candidate_node.go
Normal file
62
pkg/yqlib/treeops/candidate_node.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package treeops
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type CandidateNode struct {
|
||||
Node *yaml.Node // the actual node
|
||||
Path []interface{} /// the path we took to get to this node
|
||||
Document uint // the document index of this node
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetKey() string {
|
||||
return fmt.Sprintf("%v - %v", n.Document, n.Path)
|
||||
}
|
||||
|
||||
func (n *CandidateNode) PathStackToString() string {
|
||||
return mergePathStackToString(n.Path)
|
||||
}
|
||||
|
||||
func mergePathStackToString(pathStack []interface{}) string {
|
||||
var sb strings.Builder
|
||||
for index, path := range pathStack {
|
||||
switch path.(type) {
|
||||
case int, int64:
|
||||
// if arrayMergeStrategy == AppendArrayMergeStrategy {
|
||||
// sb.WriteString("[+]")
|
||||
// } else {
|
||||
sb.WriteString(fmt.Sprintf("[%v]", path))
|
||||
// }
|
||||
|
||||
default:
|
||||
s := fmt.Sprintf("%v", path)
|
||||
var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint
|
||||
|
||||
hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"")
|
||||
hasDoubleQuotes := strings.Contains(s, "\"")
|
||||
wrappingCharacterStart := "\""
|
||||
wrappingCharacterEnd := "\""
|
||||
if hasDoubleQuotes {
|
||||
wrappingCharacterStart = "("
|
||||
wrappingCharacterEnd = ")"
|
||||
}
|
||||
if hasSpecial || errParsingInt == nil {
|
||||
sb.WriteString(wrappingCharacterStart)
|
||||
}
|
||||
sb.WriteString(s)
|
||||
if hasSpecial || errParsingInt == nil {
|
||||
sb.WriteString(wrappingCharacterEnd)
|
||||
}
|
||||
}
|
||||
|
||||
if index < len(pathStack)-1 {
|
||||
sb.WriteString(".")
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func (d *dataTreeNavigator) traverse(matchMap *orderedmap.OrderedMap, pathNode *
|
||||
return nil, err
|
||||
}
|
||||
for _, n := range newNodes {
|
||||
matchingNodeMap.Set(n.getKey(), n)
|
||||
matchingNodeMap.Set(n.GetKey(), n)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (d *dataTreeNavigator) GetMatchingNodes(matchingNodes []*CandidateNode, pat
|
||||
var matchingNodeMap = orderedmap.NewOrderedMap()
|
||||
|
||||
for _, n := range matchingNodes {
|
||||
matchingNodeMap.Set(n.getKey(), n)
|
||||
matchingNodeMap.Set(n.GetKey(), n)
|
||||
}
|
||||
|
||||
matchedNodes, err := d.getMatchingNodes(matchingNodeMap, pathNode)
|
||||
@@ -63,6 +63,10 @@ func (d *dataTreeNavigator) GetMatchingNodes(matchingNodes []*CandidateNode, pat
|
||||
}
|
||||
|
||||
func (d *dataTreeNavigator) getMatchingNodes(matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) {
|
||||
if pathNode == nil {
|
||||
log.Debugf("getMatchingNodes - nothing to do")
|
||||
return matchingNodes, nil
|
||||
}
|
||||
log.Debugf("Processing Path: %v", pathNode.PathElement.toString())
|
||||
if pathNode.PathElement.PathElementType == SelfReference {
|
||||
return matchingNodes, nil
|
||||
|
||||
@@ -17,7 +17,7 @@ func DeleteChildOperator(d *dataTreeNavigator, matchingNodes *orderedmap.Ordered
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
elMap := orderedmap.NewOrderedMap()
|
||||
elMap.Set(candidate.getKey(), candidate)
|
||||
elMap.Set(candidate.GetKey(), candidate)
|
||||
nodesToDelete, err := d.getMatchingNodes(elMap, pathNode.Rhs)
|
||||
log.Debug("nodesToDelete:\n%v", NodesToString(nodesToDelete))
|
||||
if err != nil {
|
||||
@@ -50,9 +50,9 @@ func deleteFromMap(candidate *CandidateNode, nodesToDelete *orderedmap.OrderedMa
|
||||
Document: candidate.Document,
|
||||
Path: append(candidate.Path, key.Value),
|
||||
}
|
||||
_, shouldDelete := nodesToDelete.Get(childCandidate.getKey())
|
||||
_, shouldDelete := nodesToDelete.Get(childCandidate.GetKey())
|
||||
|
||||
log.Debugf("shouldDelete %v ? %v", childCandidate.getKey(), shouldDelete)
|
||||
log.Debugf("shouldDelete %v ? %v", childCandidate.GetKey(), shouldDelete)
|
||||
|
||||
if !shouldDelete {
|
||||
newContents = append(newContents, key, value)
|
||||
@@ -76,7 +76,7 @@ func deleteFromArray(candidate *CandidateNode, nodesToDelete *orderedmap.Ordered
|
||||
Path: append(candidate.Path, index),
|
||||
}
|
||||
|
||||
_, shouldDelete := nodesToDelete.Get(childCandidate.getKey())
|
||||
_, shouldDelete := nodesToDelete.Get(childCandidate.GetKey())
|
||||
if !shouldDelete {
|
||||
newContents = append(newContents, value)
|
||||
}
|
||||
|
||||
@@ -11,16 +11,6 @@ import (
|
||||
|
||||
var log = logging.MustGetLogger("yq-treeops")
|
||||
|
||||
type CandidateNode struct {
|
||||
Node *yaml.Node // the actual node
|
||||
Path []interface{} /// the path we took to get to this node
|
||||
Document uint // the document index of this node
|
||||
}
|
||||
|
||||
func (n *CandidateNode) getKey() string {
|
||||
return fmt.Sprintf("%v - %v", n.Document, n.Path)
|
||||
}
|
||||
|
||||
type PathElementType uint32
|
||||
|
||||
const (
|
||||
@@ -76,7 +66,7 @@ func (p *PathElement) toString() string {
|
||||
}
|
||||
|
||||
type YqTreeLib interface {
|
||||
Get(rootNode *yaml.Node, path string) ([]*CandidateNode, error)
|
||||
Get(document int, documentNode *yaml.Node, path string) ([]*CandidateNode, error)
|
||||
// GetForMerge(rootNode *yaml.Node, path string, arrayMergeStrategy ArrayMergeStrategy) ([]*NodeContext, error)
|
||||
// Update(rootNode *yaml.Node, updateCommand UpdateCommand, autoCreate bool) error
|
||||
// New(path string) yaml.Node
|
||||
@@ -85,10 +75,24 @@ type YqTreeLib interface {
|
||||
// MergePathStackToString(pathStack []interface{}, arrayMergeStrategy ArrayMergeStrategy) string
|
||||
}
|
||||
|
||||
func NewYqTreeLib() YqTreeLib {
|
||||
return &lib{treeCreator: NewPathTreeCreator()}
|
||||
}
|
||||
|
||||
type lib struct {
|
||||
treeCreator PathTreeCreator
|
||||
}
|
||||
|
||||
func (l *lib) Get(document int, documentNode *yaml.Node, path string) ([]*CandidateNode, error) {
|
||||
nodes := []*CandidateNode{&CandidateNode{Node: documentNode.Content[0], Document: 0}}
|
||||
navigator := NewDataTreeNavigator(NavigationPrefs{})
|
||||
pathNode, errPath := l.treeCreator.ParsePath(path)
|
||||
if errPath != nil {
|
||||
return nil, errPath
|
||||
}
|
||||
return navigator.GetMatchingNodes(nodes, pathNode)
|
||||
}
|
||||
|
||||
//use for debugging only
|
||||
func NodesToString(collection *orderedmap.OrderedMap) string {
|
||||
if !log.IsEnabledFor(logging.DEBUG) {
|
||||
|
||||
@@ -24,7 +24,7 @@ func AssignOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap,
|
||||
}
|
||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||
node := el.Value.(*CandidateNode)
|
||||
log.Debugf("Assiging %v to %v", node.getKey(), pathNode.Rhs.PathElement.StringValue)
|
||||
log.Debugf("Assiging %v to %v", node.GetKey(), pathNode.Rhs.PathElement.StringValue)
|
||||
node.Node.Value = pathNode.Rhs.PathElement.StringValue
|
||||
}
|
||||
return lhs, nil
|
||||
@@ -41,7 +41,7 @@ func UnionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, p
|
||||
}
|
||||
for el := rhs.Front(); el != nil; el = el.Next() {
|
||||
node := el.Value.(*CandidateNode)
|
||||
lhs.Set(node.getKey(), node)
|
||||
lhs.Set(node.GetKey(), node)
|
||||
}
|
||||
return lhs, nil
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func IntersectionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.Ordere
|
||||
|
||||
func splatNode(d *dataTreeNavigator, candidate *CandidateNode) (*orderedmap.OrderedMap, error) {
|
||||
elMap := orderedmap.NewOrderedMap()
|
||||
elMap.Set(candidate.getKey(), candidate)
|
||||
elMap.Set(candidate.GetKey(), candidate)
|
||||
//need to splat matching nodes, then search through them
|
||||
splatter := &PathTreeNode{PathElement: &PathElement{
|
||||
PathElementType: PathKey,
|
||||
@@ -112,7 +112,7 @@ func CountOperator(d *dataTreeNavigator, matchMap *orderedmap.OrderedMap, pathNo
|
||||
length := childMatches.Len()
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"}
|
||||
lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path}
|
||||
results.Set(candidate.getKey(), lengthCand)
|
||||
results.Set(candidate.GetKey(), lengthCand)
|
||||
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func findMatchingChildren(d *dataTreeNavigator, results *orderedmap.OrderedMap,
|
||||
}
|
||||
} else {
|
||||
children = orderedmap.NewOrderedMap()
|
||||
children.Set(candidate.getKey(), candidate)
|
||||
children.Set(candidate.GetKey(), candidate)
|
||||
}
|
||||
|
||||
for childEl := children.Front(); childEl != nil; childEl = childEl.Next() {
|
||||
|
||||
@@ -39,6 +39,10 @@ func (p *pathTreeCreator) ParsePath(path string) (*PathTreeNode, error) {
|
||||
func (p *pathTreeCreator) CreatePathTree(postFixPath []*PathElement) (*PathTreeNode, error) {
|
||||
var stack = make([]*PathTreeNode, 0)
|
||||
|
||||
if len(postFixPath) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
for _, pathElement := range postFixPath {
|
||||
var newNode = PathTreeNode{PathElement: pathElement}
|
||||
if pathElement.PathElementType == Operation {
|
||||
|
||||
Reference in New Issue
Block a user