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