mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
wip
This commit is contained in:
parent
4696d11bbc
commit
4c6c653d25
@ -191,10 +191,11 @@ func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) *
|
||||
}
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, value string) *CandidateNode {
|
||||
replacement := n.CreateReplacement(kind, tag, value)
|
||||
func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, style Style) *CandidateNode {
|
||||
replacement := n.CreateReplacement(kind, tag, "")
|
||||
replacement.LeadingContent = n.LeadingContent
|
||||
replacement.TrailingContent = n.TrailingContent
|
||||
replacement.Style = style
|
||||
return replacement
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func createAddOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode {
|
||||
@ -19,23 +17,20 @@ func addAssignOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
return compoundAssignFunction(d, context, expressionNode, createAddOp)
|
||||
}
|
||||
|
||||
func toNodes(candidate *CandidateNode, lhs *CandidateNode) ([]*yaml.Node, error) {
|
||||
if candidate.Node.Tag == "!!null" {
|
||||
return []*yaml.Node{}, nil
|
||||
}
|
||||
clone, err := candidate.Copy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func toNodes(candidate *CandidateNode, lhs *CandidateNode) ([]*CandidateNode, error) {
|
||||
if candidate.Tag == "!!null" {
|
||||
return []*CandidateNode{}, nil
|
||||
}
|
||||
clone := candidate.Copy()
|
||||
|
||||
switch candidate.Node.Kind {
|
||||
case yaml.SequenceNode:
|
||||
return clone.Node.Content, nil
|
||||
switch candidate.Kind {
|
||||
case SequenceNode:
|
||||
return clone.Content, nil
|
||||
default:
|
||||
if len(lhs.Node.Content) > 0 {
|
||||
clone.Node.Style = lhs.Node.Content[0].Style
|
||||
if len(lhs.Content) > 0 {
|
||||
clone.Style = lhs.Content[0].Style
|
||||
}
|
||||
return []*yaml.Node{clone.Node}, nil
|
||||
return []*CandidateNode{clone}, nil
|
||||
}
|
||||
|
||||
}
|
||||
@ -47,50 +42,50 @@ func addOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
||||
}
|
||||
|
||||
func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
lhs = lhs.unwrapDocument()
|
||||
rhs = rhs.unwrapDocument()
|
||||
|
||||
lhsNode := lhs.Node
|
||||
lhsNode := lhs
|
||||
|
||||
if lhsNode.Tag == "!!null" {
|
||||
return lhs.CreateReplacement(rhs.Node), nil
|
||||
return lhs.CreateReplacement(rhs), nil
|
||||
}
|
||||
|
||||
target := lhs.CreateReplacement(&yaml.Node{
|
||||
Anchor: lhs.Node.Anchor,
|
||||
target := lhs.CreateReplacement(&yaml{
|
||||
Anchor: lhs.Anchor,
|
||||
})
|
||||
|
||||
switch lhsNode.Kind {
|
||||
case yaml.MappingNode:
|
||||
if rhs.Node.Kind != yaml.MappingNode {
|
||||
return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Node.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
|
||||
case MappingNode:
|
||||
if rhs.Kind != MappingNode {
|
||||
return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
|
||||
}
|
||||
addMaps(target, lhs, rhs)
|
||||
case yaml.SequenceNode:
|
||||
case SequenceNode:
|
||||
if err := addSequences(target, lhs, rhs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case yaml.ScalarNode:
|
||||
if rhs.Node.Kind != yaml.ScalarNode {
|
||||
return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Node.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
|
||||
case ScalarNode:
|
||||
if rhs.Kind != ScalarNode {
|
||||
return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
|
||||
}
|
||||
target.Node.Kind = yaml.ScalarNode
|
||||
target.Node.Style = lhsNode.Style
|
||||
if err := addScalars(context, target, lhsNode, rhs.Node); err != nil {
|
||||
target.Kind = ScalarNode
|
||||
target.Style = lhsNode.Style
|
||||
if err := addScalars(context, target, lhsNode, rhs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error {
|
||||
func addScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
||||
lhsTag := lhs.Tag
|
||||
rhsTag := guessTagFromCustomType(rhs)
|
||||
rhsTag := rhs.guessTagFromCustomType()
|
||||
lhsIsCustom := false
|
||||
if !strings.HasPrefix(lhsTag, "!!") {
|
||||
// custom tag - we have to have a guess
|
||||
lhsTag = guessTagFromCustomType(lhs)
|
||||
lhsTag = lhs.guessTagFromCustomType()
|
||||
lhsIsCustom = true
|
||||
}
|
||||
|
||||
@ -106,11 +101,11 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam
|
||||
return addDateTimes(context.GetDateTimeLayout(), target, lhs, rhs)
|
||||
|
||||
} else if lhsTag == "!!str" {
|
||||
target.Node.Tag = lhs.Tag
|
||||
target.Node.Value = lhs.Value + rhs.Value
|
||||
target.Tag = lhs.Tag
|
||||
target.Value = lhs.Value + rhs.Value
|
||||
} else if rhsTag == "!!str" {
|
||||
target.Node.Tag = rhs.Tag
|
||||
target.Node.Value = lhs.Value + rhs.Value
|
||||
target.Tag = rhs.Tag
|
||||
target.Value = lhs.Value + rhs.Value
|
||||
} else if lhsTag == "!!int" && rhsTag == "!!int" {
|
||||
format, lhsNum, err := parseInt64(lhs.Value)
|
||||
if err != nil {
|
||||
@ -121,8 +116,8 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam
|
||||
return err
|
||||
}
|
||||
sum := lhsNum + rhsNum
|
||||
target.Node.Tag = lhs.Tag
|
||||
target.Node.Value = fmt.Sprintf(format, sum)
|
||||
target.Tag = lhs.Tag
|
||||
target.Value = fmt.Sprintf(format, sum)
|
||||
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
|
||||
lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
|
||||
if err != nil {
|
||||
@ -134,18 +129,18 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam
|
||||
}
|
||||
sum := lhsNum + rhsNum
|
||||
if lhsIsCustom {
|
||||
target.Node.Tag = lhs.Tag
|
||||
target.Tag = lhs.Tag
|
||||
} else {
|
||||
target.Node.Tag = "!!float"
|
||||
target.Tag = "!!float"
|
||||
}
|
||||
target.Node.Value = fmt.Sprintf("%v", sum)
|
||||
target.Value = fmt.Sprintf("%v", sum)
|
||||
} else {
|
||||
return fmt.Errorf("%v cannot be added to %v", lhsTag, rhsTag)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addDateTimes(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error {
|
||||
func addDateTimes(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
||||
|
||||
duration, err := time.ParseDuration(rhs.Value)
|
||||
if err != nil {
|
||||
@ -158,52 +153,52 @@ func addDateTimes(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yam
|
||||
}
|
||||
|
||||
newTime := currentTime.Add(duration)
|
||||
target.Node.Value = newTime.Format(layout)
|
||||
target.Value = newTime.Format(layout)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
||||
target.Node.Kind = yaml.SequenceNode
|
||||
if len(lhs.Node.Content) > 0 {
|
||||
target.Node.Style = lhs.Node.Style
|
||||
target.Kind = SequenceNode
|
||||
if len(lhs.Content) > 0 {
|
||||
target.Style = lhs.Style
|
||||
}
|
||||
target.Node.Tag = lhs.Node.Tag
|
||||
target.Tag = lhs.Tag
|
||||
|
||||
extraNodes, err := toNodes(rhs, lhs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target.Node.Content = append(deepCloneContent(lhs.Node.Content), extraNodes...)
|
||||
target.Content = append(lhs.CopyChildren(), extraNodes...)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func addMaps(target *CandidateNode, lhsC *CandidateNode, rhsC *CandidateNode) {
|
||||
lhs := lhsC.Node
|
||||
rhs := rhsC.Node
|
||||
lhs := lhsC
|
||||
rhs := rhsC
|
||||
|
||||
target.Node.Content = make([]*yaml.Node, len(lhs.Content))
|
||||
copy(target.Node.Content, lhs.Content)
|
||||
target.Content = make([]*CandidateNode, len(lhs.Content))
|
||||
copy(target.Content, lhs.Content)
|
||||
|
||||
for index := 0; index < len(rhs.Content); index = index + 2 {
|
||||
key := rhs.Content[index]
|
||||
value := rhs.Content[index+1]
|
||||
log.Debug("finding %v", key.Value)
|
||||
indexInLHS := findKeyInMap(target.Node, key)
|
||||
indexInLHS := findKeyInMap(target, key)
|
||||
log.Debug("indexInLhs %v", indexInLHS)
|
||||
if indexInLHS < 0 {
|
||||
// not in there, append it
|
||||
target.Node.Content = append(target.Node.Content, key, value)
|
||||
target.Content = append(target.Content, key, value)
|
||||
} else {
|
||||
// it's there, replace it
|
||||
target.Node.Content[indexInLHS+1] = value
|
||||
target.Content[indexInLHS+1] = value
|
||||
}
|
||||
}
|
||||
target.Node.Kind = yaml.MappingNode
|
||||
target.Kind = MappingNode
|
||||
if len(lhs.Content) > 0 {
|
||||
target.Node.Style = lhs.Style
|
||||
target.Style = lhs.Style
|
||||
}
|
||||
target.Node.Tag = lhs.Tag
|
||||
target.Tag = lhs.Tag
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ func alternativeOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
if lhs == nil {
|
||||
return nil, nil
|
||||
}
|
||||
truthy, err := isTruthy(lhs)
|
||||
truthy, err := isTruthyNode(lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -29,12 +29,8 @@ func alternativeFunc(d *dataTreeNavigator, context Context, lhs *CandidateNode,
|
||||
if rhs == nil {
|
||||
return lhs, nil
|
||||
}
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
log.Debugf("Alternative LHS: %v", lhs.Node.Tag)
|
||||
log.Debugf("- RHS: %v", rhs.Node.Tag)
|
||||
|
||||
isTrue, err := isTruthy(lhs)
|
||||
isTrue, err := isTruthyNode(lhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if isTrue {
|
||||
|
@ -8,9 +8,8 @@ type assignPreferences struct {
|
||||
|
||||
func assignUpdateFunc(prefs assignPreferences) crossFunctionCalculation {
|
||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
if !prefs.OnlyWriteNull || lhs.Node.Tag == "!!null" {
|
||||
lhs.UpdateFrom(rhs, prefs)
|
||||
if !prefs.OnlyWriteNull || lhs.Tag == "!!null" {
|
||||
lhs.UpdateFrom(rhs.unwrapDocument(), prefs)
|
||||
}
|
||||
return lhs, nil
|
||||
}
|
||||
@ -60,8 +59,7 @@ func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
|
||||
if first != nil {
|
||||
rhsCandidate := first.Value.(*CandidateNode)
|
||||
rhsCandidate.Node = unwrapDoc(rhsCandidate.Node)
|
||||
candidate.UpdateFrom(rhsCandidate, prefs)
|
||||
candidate.UpdateFrom(rhsCandidate.unwrapDocument(), prefs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,7 +90,7 @@ func assignAttributesOperator(d *dataTreeNavigator, context Context, expressionN
|
||||
if expressionNode.Operation.Preferences != nil {
|
||||
prefs = expressionNode.Operation.Preferences.(assignPreferences)
|
||||
}
|
||||
if !prefs.OnlyWriteNull || candidate.Node.Tag == "!!null" {
|
||||
if !prefs.OnlyWriteNull || candidate.Tag == "!!null" {
|
||||
candidate.UpdateAttributesFrom(first.Value.(*CandidateNode), prefs)
|
||||
}
|
||||
}
|
||||
|
@ -3,36 +3,26 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func isTruthyNode(node *yaml.Node) (bool, error) {
|
||||
value := true
|
||||
func isTruthyNode(candidate *CandidateNode) (bool, error) {
|
||||
if candidate == nil {
|
||||
return false, nil
|
||||
}
|
||||
node := candidate.unwrapDocument()
|
||||
if node.Tag == "!!null" {
|
||||
return false, nil
|
||||
}
|
||||
if node.Kind == yaml.ScalarNode && node.Tag == "!!bool" {
|
||||
errDecoding := node.Decode(&value)
|
||||
if errDecoding != nil {
|
||||
return false, errDecoding
|
||||
}
|
||||
if node.Kind == ScalarNode && node.Tag == "!!bool" {
|
||||
// yes/y/true/on
|
||||
return (strings.EqualFold(node.Value, "y") ||
|
||||
strings.EqualFold(node.Value, "yes") ||
|
||||
strings.EqualFold(node.Value, "on") ||
|
||||
strings.EqualFold(node.Value, "true")), nil
|
||||
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func isTruthy(c *CandidateNode) (bool, error) {
|
||||
node := unwrapDoc(c.Node)
|
||||
return isTruthyNode(node)
|
||||
}
|
||||
|
||||
func getBoolean(candidate *CandidateNode) (bool, error) {
|
||||
if candidate != nil {
|
||||
candidate.Node = unwrapDoc(candidate.Node)
|
||||
return isTruthy(candidate)
|
||||
}
|
||||
return false, nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode {
|
||||
@ -48,7 +38,7 @@ func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode {
|
||||
|
||||
func returnRhsTruthy(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
owner := getOwner(lhs, rhs)
|
||||
rhsBool, err := getBoolean(rhs)
|
||||
rhsBool, err := isTruthyNode(rhs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -61,7 +51,7 @@ func returnLHSWhen(targetBool bool) func(lhs *CandidateNode) (*CandidateNode, er
|
||||
var err error
|
||||
var lhsBool bool
|
||||
|
||||
if lhsBool, err = getBoolean(lhs); err != nil || lhsBool != targetBool {
|
||||
if lhsBool, err = isTruthyNode(lhs); err != nil || lhsBool != targetBool {
|
||||
return nil, err
|
||||
}
|
||||
owner := &CandidateNode{}
|
||||
@ -72,18 +62,17 @@ func returnLHSWhen(targetBool bool) func(lhs *CandidateNode) (*CandidateNode, er
|
||||
}
|
||||
}
|
||||
|
||||
func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *yaml.Node) (bool, error) {
|
||||
func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *CandidateNode) (bool, error) {
|
||||
for _, node := range sequenceNode.Content {
|
||||
|
||||
if expressionNode != nil {
|
||||
//need to evaluate the expression against the node
|
||||
candidate := &CandidateNode{Node: node}
|
||||
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode)
|
||||
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(node), expressionNode)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if rhs.MatchingNodes.Len() > 0 {
|
||||
node = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node
|
||||
node = rhs.MatchingNodes.Front().Value.(*CandidateNode)
|
||||
} else {
|
||||
// no results found, ignore this entry
|
||||
continue
|
||||
@ -106,8 +95,8 @@ func allOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
if candidateNode.Kind != yaml.SequenceNode {
|
||||
candidateNode := candidate.unwrapDocument()
|
||||
if candidateNode.Kind != SequenceNode {
|
||||
return Context{}, fmt.Errorf("any only supports arrays, was %v", candidateNode.Tag)
|
||||
}
|
||||
booleanResult, err := findBoolean(false, d, context, expressionNode.RHS, candidateNode)
|
||||
@ -125,8 +114,8 @@ func anyOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
if candidateNode.Kind != yaml.SequenceNode {
|
||||
candidateNode := candidate.unwrapDocument()
|
||||
if candidateNode.Kind != SequenceNode {
|
||||
return Context{}, fmt.Errorf("any only supports arrays, was %v", candidateNode.Tag)
|
||||
}
|
||||
booleanResult, err := findBoolean(true, d, context, expressionNode.RHS, candidateNode)
|
||||
@ -164,7 +153,7 @@ func notOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
log.Debug("notOperation checking %v", candidate)
|
||||
truthy, errDecoding := isTruthy(candidate)
|
||||
truthy, errDecoding := isTruthyNode(candidate)
|
||||
if errDecoding != nil {
|
||||
return Context{}, errDecoding
|
||||
}
|
||||
|
@ -2,12 +2,10 @@ package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func collectTogether(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (*CandidateNode, error) {
|
||||
collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
collectedNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
collectExpResults, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode)
|
||||
@ -17,10 +15,10 @@ func collectTogether(d *dataTreeNavigator, context Context, expressionNode *Expr
|
||||
for result := collectExpResults.MatchingNodes.Front(); result != nil; result = result.Next() {
|
||||
resultC := result.Value.(*CandidateNode)
|
||||
log.Debugf("found this: %v", NodeToString(resultC))
|
||||
collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node))
|
||||
collectedNode.Content = append(collectedNode.Content, resultC.unwrapDocument())
|
||||
}
|
||||
}
|
||||
return &CandidateNode{Node: collectedNode}, nil
|
||||
return collectedNode, nil
|
||||
}
|
||||
|
||||
func collectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -28,9 +26,8 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
||||
|
||||
if context.MatchingNodes.Len() == 0 {
|
||||
log.Debugf("nothing to collect")
|
||||
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Value: "[]"}
|
||||
candidate := &CandidateNode{Node: node}
|
||||
return context.SingleChildContext(candidate), nil
|
||||
node := &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Value: "[]"}
|
||||
return context.SingleChildContext(node), nil
|
||||
}
|
||||
|
||||
var evaluateAllTogether = true
|
||||
|
@ -2,8 +2,6 @@ package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -23,26 +21,26 @@ func collectObjectOperator(d *dataTreeNavigator, originalContext Context, expres
|
||||
context := originalContext.WritableClone()
|
||||
|
||||
if context.MatchingNodes.Len() == 0 {
|
||||
node := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map", Value: "{}"}
|
||||
candidate := &CandidateNode{Node: node}
|
||||
candidate := &CandidateNode{Kind: MappingNode, Tag: "!!map", Value: "{}"}
|
||||
return context.SingleChildContext(candidate), nil
|
||||
}
|
||||
first := context.MatchingNodes.Front().Value.(*CandidateNode)
|
||||
var rotated = make([]*list.List, len(first.Node.Content))
|
||||
var rotated = make([]*list.List, len(first.Content))
|
||||
|
||||
for i := 0; i < len(first.Node.Content); i++ {
|
||||
for i := 0; i < len(first.Content); i++ {
|
||||
rotated[i] = list.New()
|
||||
}
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidateNode := el.Value.(*CandidateNode)
|
||||
for i := 0; i < len(first.Node.Content); i++ {
|
||||
rotated[i].PushBack(candidateNode.CreateChildInArray(i, candidateNode.Node.Content[i]))
|
||||
for i := 0; i < len(first.Content); i++ {
|
||||
|
||||
rotated[i].PushBack(candidateNode.CreateChildInArray(i, candidateNode.Content[i]))
|
||||
}
|
||||
}
|
||||
|
||||
newObject := list.New()
|
||||
for i := 0; i < len(first.Node.Content); i++ {
|
||||
for i := 0; i < len(first.Content); i++ {
|
||||
additions, err := collect(d, context.ChildContext(list.New()), rotated[i])
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
@ -82,10 +80,7 @@ func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List)
|
||||
aggCandidate := el.Value.(*CandidateNode)
|
||||
for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
||||
splatCandidate := splatEl.Value.(*CandidateNode)
|
||||
newCandidate, err := aggCandidate.Copy()
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
newCandidate := aggCandidate.Copy()
|
||||
|
||||
newCandidate.Path = nil
|
||||
|
||||
|
@ -3,8 +3,6 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -17,12 +15,12 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
for el := nodesToDelete.MatchingNodes.Back(); el != nil; el = el.Prev() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
if candidate.Node.Kind == yaml.DocumentNode {
|
||||
if candidate.Kind == DocumentNode {
|
||||
//need to delete this node from context.
|
||||
newResults := list.New()
|
||||
for item := context.MatchingNodes.Front(); item != nil; item = item.Next() {
|
||||
nodeInContext := item.Value.(*CandidateNode)
|
||||
if nodeInContext.Node != candidate.Node {
|
||||
if nodeInContext != candidate {
|
||||
newResults.PushBack(nodeInContext)
|
||||
} else {
|
||||
log.Info("Need to delete this %v", NodeToString(nodeInContext))
|
||||
@ -36,12 +34,12 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
return context, nil
|
||||
}
|
||||
|
||||
parentNode := candidate.Parent.Node
|
||||
parentNode := candidate.Parent
|
||||
childPath := candidate.Path[len(candidate.Path)-1]
|
||||
|
||||
if parentNode.Kind == yaml.MappingNode {
|
||||
if parentNode.Kind == MappingNode {
|
||||
deleteFromMap(candidate.Parent, childPath)
|
||||
} else if parentNode.Kind == yaml.SequenceNode {
|
||||
} else if parentNode.Kind == SequenceNode {
|
||||
deleteFromArray(candidate.Parent, childPath)
|
||||
} else {
|
||||
return Context{}, fmt.Errorf("Cannot delete nodes from parent of tag %v", parentNode.Tag)
|
||||
@ -52,19 +50,17 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
|
||||
func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
|
||||
log.Debug("deleteFromMap")
|
||||
node := unwrapDoc(candidate.Node)
|
||||
node := candidate.unwrapDocument()
|
||||
contents := node.Content
|
||||
newContents := make([]*yaml.Node, 0)
|
||||
newContents := make([]*CandidateNode, 0)
|
||||
|
||||
for index := 0; index < len(contents); index = index + 2 {
|
||||
key := contents[index]
|
||||
value := contents[index+1]
|
||||
|
||||
childCandidate := candidate.CreateChildInMap(key, value)
|
||||
|
||||
shouldDelete := key.Value == childPath
|
||||
|
||||
log.Debugf("shouldDelete %v ? %v", childCandidate.GetKey(), shouldDelete)
|
||||
log.Debugf("shouldDelete %v ? %v", value.GetKey(), shouldDelete)
|
||||
|
||||
if !shouldDelete {
|
||||
newContents = append(newContents, key, value)
|
||||
@ -75,9 +71,9 @@ func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
|
||||
|
||||
func deleteFromArray(candidate *CandidateNode, childPath interface{}) {
|
||||
log.Debug("deleteFromArray")
|
||||
node := unwrapDoc(candidate.Node)
|
||||
node := candidate.unwrapDocument()
|
||||
contents := node.Content
|
||||
newContents := make([]*yaml.Node, 0)
|
||||
newContents := make([]*CandidateNode, 0)
|
||||
|
||||
for index := 0; index < len(contents); index = index + 1 {
|
||||
value := contents[index]
|
||||
|
@ -3,8 +3,6 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -12,8 +10,7 @@ func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionN
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Document), Tag: "!!int"}
|
||||
scalar := candidate.CreateReplacement(node)
|
||||
scalar := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.Document))
|
||||
results.PushBack(scalar)
|
||||
}
|
||||
return context.ChildContext(results), nil
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func configureEncoder(format PrinterOutputFormat, indent int) Encoder {
|
||||
@ -78,7 +76,7 @@ func encodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
if originalList != nil && originalList.Len() > 0 && hasOnlyOneNewLine.MatchString(stringValue) {
|
||||
|
||||
original := originalList.Front().Value.(*CandidateNode)
|
||||
originalNode := unwrapDoc(original.Node)
|
||||
originalNode := original.unwrapDocument()
|
||||
// original block did not have a newline at the end, get rid of this one too
|
||||
if !endWithNewLine.MatchString(originalNode.Value) {
|
||||
stringValue = chomper.ReplaceAllString(stringValue, "")
|
||||
@ -92,8 +90,7 @@ func encodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
stringValue = chomper.ReplaceAllString(stringValue, "")
|
||||
}
|
||||
|
||||
stringContentNode := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: stringValue}
|
||||
results.PushBack(candidate.CreateReplacement(stringContentNode))
|
||||
results.PushBack(candidate.CreateReplacement(ScalarNode, "!!str", stringValue))
|
||||
}
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
@ -141,9 +138,9 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
|
||||
context.SetVariable("decoded: "+candidate.GetKey(), candidate.AsList())
|
||||
|
||||
log.Debugf("got: [%v]", candidate.Node.Value)
|
||||
log.Debugf("got: [%v]", candidate.Value)
|
||||
|
||||
err := decoder.Init(strings.NewReader(unwrapDoc(candidate.Node).Value))
|
||||
err := decoder.Init(strings.NewReader(candidate.unwrapDocument().Value))
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
@ -153,9 +150,15 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
return Context{}, errorReading
|
||||
}
|
||||
//first node is a doc
|
||||
node := unwrapDoc(decodedNode.Node)
|
||||
node := decodedNode.unwrapDocument()
|
||||
node.Path = candidate.Path
|
||||
node.Key = candidate.Key
|
||||
node.Parent = candidate.Parent
|
||||
node.Document = candidate.Document
|
||||
node.FileIndex = candidate.FileIndex
|
||||
node.Filename = candidate.Filename
|
||||
|
||||
results.PushBack(candidate.CreateReplacement(node))
|
||||
results.PushBack(node)
|
||||
}
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
@ -3,64 +3,60 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func entrySeqFor(key *yaml.Node, value *yaml.Node) *yaml.Node {
|
||||
var keyKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "key"}
|
||||
var valueKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "value"}
|
||||
func entrySeqFor(key *CandidateNode, value *CandidateNode) *CandidateNode {
|
||||
var keyKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "key"}
|
||||
var valueKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "value"}
|
||||
|
||||
return &yaml.Node{
|
||||
Kind: yaml.MappingNode,
|
||||
return &CandidateNode{
|
||||
Kind: MappingNode,
|
||||
Tag: "!!map",
|
||||
Content: []*yaml.Node{keyKey, key, valueKey, value},
|
||||
Content: []*CandidateNode{keyKey, key, valueKey, value},
|
||||
}
|
||||
}
|
||||
|
||||
func toEntriesFromMap(candidateNode *CandidateNode) *CandidateNode {
|
||||
var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
|
||||
var sequence = candidateNode.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", 0)
|
||||
|
||||
var contents = unwrapDoc(candidateNode.Node).Content
|
||||
var contents = candidateNode.unwrapDocument().Content
|
||||
for index := 0; index < len(contents); index = index + 2 {
|
||||
key := contents[index]
|
||||
value := contents[index+1]
|
||||
|
||||
sequence.Content = append(sequence.Content, entrySeqFor(key, value))
|
||||
}
|
||||
return entriesNode
|
||||
return sequence
|
||||
}
|
||||
|
||||
func toEntriesfromSeq(candidateNode *CandidateNode) *CandidateNode {
|
||||
var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
|
||||
var sequence = candidateNode.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", 0)
|
||||
|
||||
var contents = unwrapDoc(candidateNode.Node).Content
|
||||
var contents = candidateNode.unwrapDocument().Content
|
||||
for index := 0; index < len(contents); index = index + 1 {
|
||||
key := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)}
|
||||
key := &CandidateNode{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)}
|
||||
value := contents[index]
|
||||
|
||||
sequence.Content = append(sequence.Content, entrySeqFor(key, value))
|
||||
}
|
||||
return entriesNode
|
||||
return sequence
|
||||
}
|
||||
|
||||
func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
var results = list.New()
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
candidateNode := candidate.unwrapDocument()
|
||||
|
||||
switch candidateNode.Kind {
|
||||
case yaml.MappingNode:
|
||||
case MappingNode:
|
||||
results.PushBack(toEntriesFromMap(candidate))
|
||||
|
||||
case yaml.SequenceNode:
|
||||
case SequenceNode:
|
||||
results.PushBack(toEntriesfromSeq(candidate))
|
||||
default:
|
||||
if candidateNode.Tag != "!!null" {
|
||||
return Context{}, fmt.Errorf("%v has no keys", candidate.Node.Tag)
|
||||
return Context{}, fmt.Errorf("%v has no keys", candidate.Tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,9 +64,8 @@ func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error) {
|
||||
func parseEntry(candidateNode *CandidateNode, position int) (*CandidateNode, *CandidateNode, error) {
|
||||
prefs := traversePreferences{DontAutoCreate: true}
|
||||
candidateNode := &CandidateNode{Node: entry}
|
||||
|
||||
keyResults, err := traverseMap(Context{}, candidateNode, createStringScalarNode("key"), prefs, false)
|
||||
|
||||
@ -88,15 +83,14 @@ func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error)
|
||||
return nil, nil, fmt.Errorf("expected to find one 'value' entry but found %v in position %v", valueResults.Len(), position)
|
||||
}
|
||||
|
||||
return keyResults.Front().Value.(*CandidateNode).Node, valueResults.Front().Value.(*CandidateNode).Node, nil
|
||||
return keyResults.Front().Value.(*CandidateNode), valueResults.Front().Value.(*CandidateNode), nil
|
||||
|
||||
}
|
||||
|
||||
func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
|
||||
var node = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
|
||||
var mapCandidateNode = candidateNode.CreateReplacementWithDocWrappers(node)
|
||||
var node = candidateNode.CopyWithoutContent()
|
||||
|
||||
var contents = unwrapDoc(candidateNode.Node).Content
|
||||
var contents = candidateNode.unwrapDocument().Content
|
||||
|
||||
for index := 0; index < len(contents); index = index + 1 {
|
||||
key, value, err := parseEntry(contents[index], index)
|
||||
@ -106,17 +100,17 @@ func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
|
||||
|
||||
node.Content = append(node.Content, key, value)
|
||||
}
|
||||
return mapCandidateNode, nil
|
||||
return node, nil
|
||||
}
|
||||
|
||||
func fromEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
var results = list.New()
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
candidateNode := candidate.unwrapDocument()
|
||||
|
||||
switch candidateNode.Kind {
|
||||
case yaml.SequenceNode:
|
||||
case SequenceNode:
|
||||
mapResult, err := fromEntries(candidate)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
|
@ -4,10 +4,8 @@ import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
parse "github.com/a8m/envsubst/parse"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type envOpPreferences struct {
|
||||
@ -18,39 +16,37 @@ type envOpPreferences struct {
|
||||
}
|
||||
|
||||
func envOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
envName := expressionNode.Operation.CandidateNode.Node.Value
|
||||
envName := expressionNode.Operation.CandidateNode.Value
|
||||
log.Debug("EnvOperator, env name:", envName)
|
||||
|
||||
rawValue := os.Getenv(envName)
|
||||
|
||||
preferences := expressionNode.Operation.Preferences.(envOpPreferences)
|
||||
|
||||
var node *yaml.Node
|
||||
var node *CandidateNode
|
||||
if preferences.StringValue {
|
||||
node = &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
node = &CandidateNode{
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: rawValue,
|
||||
}
|
||||
} else if rawValue == "" {
|
||||
return Context{}, fmt.Errorf("Value for env variable '%v' not provided in env()", envName)
|
||||
} else {
|
||||
var dataBucket yaml.Node
|
||||
decoder := yaml.NewDecoder(strings.NewReader(rawValue))
|
||||
errorReading := decoder.Decode(&dataBucket)
|
||||
if errorReading != nil {
|
||||
return Context{}, errorReading
|
||||
decoder := NewYamlDecoder(ConfiguredYamlPreferences)
|
||||
result, err := decoder.Decode()
|
||||
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
//first node is a doc
|
||||
node = unwrapDoc(&dataBucket)
|
||||
node = result.unwrapDocument()
|
||||
|
||||
}
|
||||
log.Debug("ENV tag", node.Tag)
|
||||
log.Debug("ENV value", node.Value)
|
||||
log.Debug("ENV Kind", node.Kind)
|
||||
|
||||
target := &CandidateNode{Node: node}
|
||||
|
||||
return context.SingleChildContext(target), nil
|
||||
return context.SingleChildContext(node), nil
|
||||
}
|
||||
|
||||
func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -71,7 +67,7 @@ func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := unwrapDoc(candidate.Node)
|
||||
node := candidate.unwrapDocument()
|
||||
if node.Tag != "!!str" {
|
||||
log.Warning("EnvSubstOperator, env name:", node.Tag, node.Value)
|
||||
return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
|
||||
@ -81,8 +77,7 @@ func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
targetNode := &yaml.Node{Kind: yaml.ScalarNode, Value: value, Tag: "!!str"}
|
||||
result := candidate.CreateReplacement(targetNode)
|
||||
result := candidate.CreateReplacement(ScalarNode, "!!str", value)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,6 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -14,8 +12,7 @@ func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Filename, Tag: "!!str"}
|
||||
result := candidate.CreateReplacement(node)
|
||||
result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.Filename)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
@ -29,8 +26,7 @@ func getFileIndexOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.FileIndex), Tag: "!!int"}
|
||||
result := candidate.CreateReplacement(node)
|
||||
result := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.FileIndex))
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@ import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var LoadYamlPreferences = YamlPreferences{
|
||||
@ -30,7 +28,7 @@ func loadString(filename string) (*CandidateNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &CandidateNode{Node: &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: string(filebytes)}}, nil
|
||||
return &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: string(filebytes)}, nil
|
||||
}
|
||||
|
||||
func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) {
|
||||
@ -51,15 +49,15 @@ func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) {
|
||||
|
||||
if documents.Len() == 0 {
|
||||
// return null candidate
|
||||
return &CandidateNode{Node: &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!null"}}, nil
|
||||
return &CandidateNode{Kind: ScalarNode, Tag: "!!null"}, nil
|
||||
} else if documents.Len() == 1 {
|
||||
candidate := documents.Front().Value.(*CandidateNode)
|
||||
return candidate, nil
|
||||
|
||||
} else {
|
||||
sequenceNode := &CandidateNode{Node: &yaml.Node{Kind: yaml.SequenceNode}}
|
||||
sequenceNode := &CandidateNode{Kind: SequenceNode}
|
||||
for doc := documents.Front(); doc != nil; doc = doc.Next() {
|
||||
sequenceNode.Node.Content = append(sequenceNode.Node.Content, unwrapDoc(doc.Value.(*CandidateNode).Node))
|
||||
sequenceNode.Content = append(sequenceNode.Content, doc.Value.(*CandidateNode).unwrapDocument())
|
||||
}
|
||||
return sequenceNode, nil
|
||||
}
|
||||
@ -87,7 +85,7 @@ func loadYamlOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
|
||||
}
|
||||
nameCandidateNode := rhs.MatchingNodes.Front().Value.(*CandidateNode)
|
||||
|
||||
filename := nameCandidateNode.Node.Value
|
||||
filename := nameCandidateNode.Value
|
||||
|
||||
var contentsCandidate *CandidateNode
|
||||
|
||||
|
@ -3,21 +3,19 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func createPathNodeFor(pathElement interface{}) *yaml.Node {
|
||||
func createPathNodeFor(pathElement interface{}) *CandidateNode {
|
||||
switch pathElement := pathElement.(type) {
|
||||
case string:
|
||||
return &yaml.Node{Kind: yaml.ScalarNode, Value: pathElement, Tag: "!!str"}
|
||||
return &CandidateNode{Kind: ScalarNode, Value: pathElement, Tag: "!!str"}
|
||||
default:
|
||||
return &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", pathElement), Tag: "!!int"}
|
||||
return &CandidateNode{Kind: ScalarNode, Value: fmt.Sprintf("%v", pathElement), Tag: "!!int"}
|
||||
}
|
||||
}
|
||||
|
||||
func getPathArrayFromNode(funcName string, node *yaml.Node) ([]interface{}, error) {
|
||||
if node.Kind != yaml.SequenceNode {
|
||||
func getPathArrayFromNode(funcName string, node *CandidateNode) ([]interface{}, error) {
|
||||
if node.Kind != SequenceNode {
|
||||
return nil, fmt.Errorf("%v: expected path array, but got %v instead", funcName, node.Tag)
|
||||
}
|
||||
|
||||
@ -59,7 +57,7 @@ func setPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
||||
}
|
||||
lhsValue := lhsPathContext.MatchingNodes.Front().Value.(*CandidateNode)
|
||||
|
||||
lhsPath, err := getPathArrayFromNode("SETPATH", lhsValue.Node)
|
||||
lhsPath, err := getPathArrayFromNode("SETPATH", lhsValue)
|
||||
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
@ -110,7 +108,7 @@ func delPathsOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
|
||||
if pathArraysContext.MatchingNodes.Len() != 1 {
|
||||
return Context{}, fmt.Errorf("DELPATHS: expected single value but found %v", pathArraysContext.MatchingNodes.Len())
|
||||
}
|
||||
pathArraysNode := pathArraysContext.MatchingNodes.Front().Value.(*CandidateNode).Node
|
||||
pathArraysNode := pathArraysContext.MatchingNodes.Front().Value.(*CandidateNode)
|
||||
|
||||
if pathArraysNode.Tag != "!!seq" {
|
||||
return Context{}, fmt.Errorf("DELPATHS: expected a sequence of sequences, but found %v", pathArraysNode.Tag)
|
||||
@ -156,16 +154,15 @@ func getPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||
node := candidate.CreateReplacement(SequenceNode, "!!seq", "")
|
||||
|
||||
content := make([]*yaml.Node, len(candidate.Path))
|
||||
content := make([]*CandidateNode, len(candidate.Path))
|
||||
for pathIndex := 0; pathIndex < len(candidate.Path); pathIndex++ {
|
||||
path := candidate.Path[pathIndex]
|
||||
content[pathIndex] = createPathNodeFor(path)
|
||||
}
|
||||
node.Content = content
|
||||
result := candidate.CreateReplacement(node)
|
||||
results.PushBack(result)
|
||||
results.PushBack(node)
|
||||
}
|
||||
|
||||
return context.ChildContext(results), nil
|
||||
|
@ -3,8 +3,6 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func reverseOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -13,19 +11,19 @@ func reverseOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
candidateNode := candidate.unwrapDocument()
|
||||
|
||||
if candidateNode.Kind != yaml.SequenceNode {
|
||||
if candidateNode.Kind != SequenceNode {
|
||||
return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag())
|
||||
}
|
||||
|
||||
reverseList := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Style: candidateNode.Style}
|
||||
reverseList.Content = make([]*yaml.Node, len(candidateNode.Content))
|
||||
reverseList := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!tag", candidateNode.Style)
|
||||
reverseList.Content = make([]*CandidateNode, len(candidateNode.Content))
|
||||
|
||||
for i, originalNode := range candidateNode.Content {
|
||||
reverseList.Content[len(candidateNode.Content)-i-1] = originalNode
|
||||
}
|
||||
results.PushBack(candidate.CreateReplacementWithDocWrappers(reverseList))
|
||||
results.PushBack(reverseList)
|
||||
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ func selectOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
|
||||
for resultEl := rhs.MatchingNodes.Front(); resultEl != nil; resultEl = resultEl.Next() {
|
||||
result := resultEl.Value.(*CandidateNode)
|
||||
includeResult, errDecoding = isTruthy(result)
|
||||
includeResult, errDecoding = isTruthyNode(result)
|
||||
log.Debugf("isTruthy %v", includeResult)
|
||||
if errDecoding != nil {
|
||||
return Context{}, errDecoding
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func sortOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -26,9 +24,9 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
|
||||
candidateNode := unwrapDoc(candidate.Node)
|
||||
candidateNode := candidate.unwrapDocument()
|
||||
|
||||
if candidateNode.Kind != yaml.SequenceNode {
|
||||
if candidateNode.Kind != SequenceNode {
|
||||
return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag())
|
||||
}
|
||||
|
||||
@ -36,8 +34,7 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
|
||||
for i, originalNode := range candidateNode.Content {
|
||||
|
||||
childCandidate := candidate.CreateChildInArray(i, originalNode)
|
||||
compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(childCandidate), expressionNode.RHS)
|
||||
compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(originalNode), expressionNode.RHS)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
@ -48,19 +45,20 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
|
||||
sort.Stable(sortableArray)
|
||||
|
||||
sortedList := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Style: candidateNode.Style}
|
||||
sortedList.Content = make([]*yaml.Node, len(candidateNode.Content))
|
||||
sortedList := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", candidateNode.Style)
|
||||
|
||||
sortedList.Content = make([]*CandidateNode, len(candidateNode.Content))
|
||||
|
||||
for i, sortedNode := range sortableArray {
|
||||
sortedList.Content[i] = sortedNode.Node
|
||||
}
|
||||
results.PushBack(candidate.CreateReplacementWithDocWrappers(sortedList))
|
||||
results.PushBack(sortedList)
|
||||
}
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
type sortableNode struct {
|
||||
Node *yaml.Node
|
||||
Node *CandidateNode
|
||||
CompareContext Context
|
||||
dateTimeLayout string
|
||||
}
|
||||
@ -79,7 +77,7 @@ func (a sortableNodeArray) Less(i, j int) bool {
|
||||
lhs := lhsEl.Value.(*CandidateNode)
|
||||
rhs := rhsEl.Value.(*CandidateNode)
|
||||
|
||||
result := a.compare(lhs.Node, rhs.Node, a[i].dateTimeLayout)
|
||||
result := a.compare(lhs, rhs, a[i].dateTimeLayout)
|
||||
|
||||
if result < 0 {
|
||||
return true
|
||||
@ -92,18 +90,18 @@ func (a sortableNodeArray) Less(i, j int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (a sortableNodeArray) compare(lhs *yaml.Node, rhs *yaml.Node, dateTimeLayout string) int {
|
||||
func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateTimeLayout string) int {
|
||||
lhsTag := lhs.Tag
|
||||
rhsTag := rhs.Tag
|
||||
|
||||
if !strings.HasPrefix(lhsTag, "!!") {
|
||||
// custom tag - we have to have a guess
|
||||
lhsTag = guessTagFromCustomType(lhs)
|
||||
lhsTag = lhs.guessTagFromCustomType()
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(rhsTag, "!!") {
|
||||
// custom tag - we have to have a guess
|
||||
rhsTag = guessTagFromCustomType(rhs)
|
||||
rhsTag = rhs.guessTagFromCustomType()
|
||||
}
|
||||
|
||||
isDateTime := lhsTag == "!!timestamp" && rhsTag == "!!timestamp"
|
||||
|
@ -3,23 +3,21 @@ package yqlib
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func parseStyle(customStyle string) (yaml.Style, error) {
|
||||
func parseStyle(customStyle string) (Style, error) {
|
||||
if customStyle == "tagged" {
|
||||
return yaml.TaggedStyle, nil
|
||||
return TaggedStyle, nil
|
||||
} else if customStyle == "double" {
|
||||
return yaml.DoubleQuotedStyle, nil
|
||||
return DoubleQuotedStyle, nil
|
||||
} else if customStyle == "single" {
|
||||
return yaml.SingleQuotedStyle, nil
|
||||
return SingleQuotedStyle, nil
|
||||
} else if customStyle == "literal" {
|
||||
return yaml.LiteralStyle, nil
|
||||
return LiteralStyle, nil
|
||||
} else if customStyle == "folded" {
|
||||
return yaml.FoldedStyle, nil
|
||||
return FoldedStyle, nil
|
||||
} else if customStyle == "flow" {
|
||||
return yaml.FlowStyle, nil
|
||||
return FlowStyle, nil
|
||||
} else if customStyle != "" {
|
||||
return 0, fmt.Errorf("Unknown style %v", customStyle)
|
||||
}
|
||||
@ -29,7 +27,7 @@ func parseStyle(customStyle string) (yaml.Style, error) {
|
||||
func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
||||
log.Debugf("AssignStyleOperator: %v")
|
||||
var style yaml.Style
|
||||
var style Style
|
||||
if !expressionNode.Operation.UpdateAssign {
|
||||
rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS)
|
||||
if err != nil {
|
||||
@ -37,7 +35,7 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
}
|
||||
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
|
||||
style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Value)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
@ -60,14 +58,14 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *
|
||||
}
|
||||
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
|
||||
style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Value)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
candidate.Node.Style = style
|
||||
candidate.Style = style
|
||||
}
|
||||
|
||||
return context, nil
|
||||
@ -81,26 +79,25 @@ func getStyleOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
var style string
|
||||
switch candidate.Node.Style {
|
||||
case yaml.TaggedStyle:
|
||||
switch candidate.Style {
|
||||
case TaggedStyle:
|
||||
style = "tagged"
|
||||
case yaml.DoubleQuotedStyle:
|
||||
case DoubleQuotedStyle:
|
||||
style = "double"
|
||||
case yaml.SingleQuotedStyle:
|
||||
case SingleQuotedStyle:
|
||||
style = "single"
|
||||
case yaml.LiteralStyle:
|
||||
case LiteralStyle:
|
||||
style = "literal"
|
||||
case yaml.FoldedStyle:
|
||||
case FoldedStyle:
|
||||
style = "folded"
|
||||
case yaml.FlowStyle:
|
||||
case FlowStyle:
|
||||
style = "flow"
|
||||
case 0:
|
||||
style = ""
|
||||
default:
|
||||
style = "<unknown>"
|
||||
}
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: style, Tag: "!!str"}
|
||||
result := candidate.CreateReplacement(node)
|
||||
result := candidate.CreateReplacement(ScalarNode, "!!str", style)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,6 @@ package yqlib
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -18,7 +16,7 @@ func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
}
|
||||
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,10 +36,10 @@ func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
}
|
||||
|
||||
if rhs.MatchingNodes.Front() != nil {
|
||||
tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
|
||||
}
|
||||
}
|
||||
unwrapDoc(candidate.Node).Tag = tag
|
||||
candidate.unwrapDocument().Tag = tag
|
||||
}
|
||||
|
||||
return context, nil
|
||||
@ -54,8 +52,7 @@ func getTagOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*CandidateNode)
|
||||
node := &yaml.Node{Kind: yaml.ScalarNode, Value: unwrapDoc(candidate.Node).Tag, Tag: "!!str"}
|
||||
result := candidate.CreateReplacement(node)
|
||||
result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.unwrapDocument().Tag)
|
||||
results.PushBack(result)
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ func uniqueBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionN
|
||||
newMatches.Set(keyValue, child)
|
||||
}
|
||||
}
|
||||
resultNode := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", "")
|
||||
resultNode := candidate.CreateReplacementWithDocWrappers(SequenceNode, "!!seq", candidateNode.Style)
|
||||
for el := newMatches.Front(); el != nil; el = el.Next() {
|
||||
resultNode.Content = append(resultNode.Content, el.Value.(*CandidateNode))
|
||||
}
|
||||
|
@ -7,22 +7,16 @@ func referenceOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
|
||||
}
|
||||
|
||||
func valueOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debug("value = %v", expressionNode.Operation.CandidateNode.Node.Value)
|
||||
log.Debug("value = %v", expressionNode.Operation.CandidateNode.Value)
|
||||
if context.MatchingNodes.Len() == 0 {
|
||||
clone, err := expressionNode.Operation.CandidateNode.Copy()
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
clone := expressionNode.Operation.CandidateNode.Copy()
|
||||
return context.SingleChildContext(clone), nil
|
||||
}
|
||||
|
||||
var results = list.New()
|
||||
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
clone, err := expressionNode.Operation.CandidateNode.Copy()
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
clone := expressionNode.Operation.CandidateNode.Copy()
|
||||
results.PushBack(clone)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user