mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-13 11:55:38 +00:00
explode!
This commit is contained in:
parent
e515b8c2db
commit
d6ff198d63
@ -50,35 +50,35 @@ func explodeNode(node *yaml.Node) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case yaml.MappingNode:
|
case yaml.MappingNode:
|
||||||
|
var newContent = list.New()
|
||||||
for index := 0; index < len(node.Content); index = index + 2 {
|
for index := 0; index < len(node.Content); index = index + 2 {
|
||||||
keyNode := node.Content[index]
|
keyNode := node.Content[index]
|
||||||
valueNode := node.Content[index+1]
|
valueNode := node.Content[index+1]
|
||||||
log.Debugf("traversing %v", keyNode.Value)
|
log.Debugf("traversing %v", keyNode.Value)
|
||||||
if keyNode.Value != "<<" {
|
if keyNode.Value != "<<" {
|
||||||
errorInContent := explodeNode(valueNode)
|
err := overrideEntry(node, keyNode, valueNode, index, newContent)
|
||||||
if errorInContent != nil {
|
if err != nil {
|
||||||
return errorInContent
|
return err
|
||||||
}
|
|
||||||
errorInContent = explodeNode(keyNode)
|
|
||||||
if errorInContent != nil {
|
|
||||||
return errorInContent
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if valueNode.Kind == yaml.SequenceNode {
|
if valueNode.Kind == yaml.SequenceNode {
|
||||||
log.Debugf("an alias merge list!")
|
log.Debugf("an alias merge list!")
|
||||||
for index := len(valueNode.Content) - 1; index >= 0; index = index - 1 {
|
for index := 0; index < len(valueNode.Content); index = index + 1 {
|
||||||
aliasNode := valueNode.Content[index]
|
aliasNode := valueNode.Content[index]
|
||||||
applyAlias(node, aliasNode.Alias)
|
applyAlias(node, aliasNode.Alias, index, newContent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Debugf("an alias merge!")
|
log.Debugf("an alias merge!")
|
||||||
applyAlias(node, valueNode.Alias)
|
applyAlias(node, valueNode.Alias, index, newContent)
|
||||||
}
|
}
|
||||||
node.Content = append(node.Content[:index], node.Content[index+2:]...)
|
|
||||||
//replay that index, since the array is shorter now.
|
|
||||||
index = index - 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
node.Content = make([]*yaml.Node, newContent.Len())
|
||||||
|
index := 0
|
||||||
|
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
|
||||||
|
node.Content[index] = newEl.Value.(*yaml.Node)
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
@ -86,27 +86,57 @@ func explodeNode(node *yaml.Node) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyAlias(node *yaml.Node, alias *yaml.Node) {
|
func applyAlias(node *yaml.Node, alias *yaml.Node, aliasIndex int, newContent *list.List) error {
|
||||||
if alias == nil {
|
if alias == nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
for index := 0; index < len(alias.Content); index = index + 2 {
|
for index := 0; index < len(alias.Content); index = index + 2 {
|
||||||
keyNode := alias.Content[index]
|
keyNode := alias.Content[index]
|
||||||
log.Debugf("applying alias key %v", keyNode.Value)
|
log.Debugf("applying alias key %v", keyNode.Value)
|
||||||
valueNode := alias.Content[index+1]
|
valueNode := alias.Content[index+1]
|
||||||
setIfNotThere(node, keyNode.Value, valueNode)
|
err := overrideEntry(node, keyNode, valueNode, aliasIndex, newContent)
|
||||||
}
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
|
||||||
func setIfNotThere(node *yaml.Node, key string, value *yaml.Node) {
|
|
||||||
for index := 0; index < len(node.Content); index = index + 2 {
|
|
||||||
keyNode := node.Content[index]
|
|
||||||
if keyNode.Value == key {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// need to add it to the map
|
return nil
|
||||||
mapEntryKey := yaml.Node{Value: key, Kind: yaml.ScalarNode}
|
}
|
||||||
node.Content = append(node.Content, &mapEntryKey)
|
|
||||||
node.Content = append(node.Content, value)
|
func overrideEntry(node *yaml.Node, key *yaml.Node, value *yaml.Node, startIndex int, newContent *list.List) error {
|
||||||
|
|
||||||
|
err := explodeNode(value)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
|
||||||
|
valueEl := newEl.Next() // move forward twice
|
||||||
|
keyNode := newEl.Value.(*yaml.Node)
|
||||||
|
log.Debugf("checking new content %v:%v", keyNode.Value, valueEl.Value.(*yaml.Node).Value)
|
||||||
|
if keyNode.Value == key.Value && keyNode.Alias == nil && key.Alias == nil {
|
||||||
|
log.Debugf("overridign new content")
|
||||||
|
valueEl.Value = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newEl = valueEl // move forward twice
|
||||||
|
}
|
||||||
|
|
||||||
|
for index := startIndex + 2; index < len(node.Content); index = index + 2 {
|
||||||
|
keyNode := node.Content[index]
|
||||||
|
|
||||||
|
if keyNode.Value == key.Value && keyNode.Alias == nil {
|
||||||
|
log.Debugf("content will be overridden at index %v", index)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = explodeNode(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugf("adding %v:%v", key.Value, value.Value)
|
||||||
|
newContent.PushBack(key)
|
||||||
|
newContent.PushBack(value)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nested alias
|
||||||
|
|
||||||
var explodeTest = []expressionScenario{
|
var explodeTest = []expressionScenario{
|
||||||
{
|
{
|
||||||
document: `{a: mike}`,
|
document: `{a: mike}`,
|
||||||
@ -20,10 +22,26 @@ var explodeTest = []expressionScenario{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
document: mergeDocSample,
|
document: `{f : {a: &a cat, *a: b}}`,
|
||||||
expression: `.foo* | explode(.)`,
|
expression: `explode(.f)`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (doc)::{f: {a: cat, b: cat}}\n",
|
"D0, P[], (doc)::{f: {a: cat, cat: b}}\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
document: mergeDocSample,
|
||||||
|
expression: `.foo* | explode(.) | (. style="flow")`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[foo], (!!map)::{a: foo_a, thing: foo_thing, c: foo_c}\n",
|
||||||
|
"D0, P[foobarList], (!!map)::{b: bar_b, a: foo_a, thing: bar_thing, c: foobarList_c}\n",
|
||||||
|
"D0, P[foobar], (!!map)::{c: foo_c, a: foo_a, thing: foobar_thing}\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
document: `{f : {a: &a cat, b: &b {f: *a}, *a: *b}}`,
|
||||||
|
expression: `explode(.f)`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (doc)::{f: {a: cat, b: {f: cat}, cat: {f: cat}}}\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,11 @@ var pathTests = []struct {
|
|||||||
append(make([]interface{}, 0), " (string)"),
|
append(make([]interface{}, 0), " (string)"),
|
||||||
append(make([]interface{}, 0), " (string)"),
|
append(make([]interface{}, 0), " (string)"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`.foo* | (. style="flow")`,
|
||||||
|
append(make([]interface{}, 0), "foo*", "PIPE", "(", "SELF", "ASSIGN_STYLE", "flow (string)", ")"),
|
||||||
|
append(make([]interface{}, 0), "foo*", "SELF", "flow (string)", "ASSIGN_STYLE", "PIPE"),
|
||||||
|
},
|
||||||
|
|
||||||
// {".animals | .==cat", append(make([]interface{}, 0), "animals", "TRAVERSE", "SELF", "EQUALS", "cat")},
|
// {".animals | .==cat", append(make([]interface{}, 0), "animals", "TRAVERSE", "SELF", "EQUALS", "cat")},
|
||||||
// {".animals | (. == cat)", append(make([]interface{}, 0), "animals", "TRAVERSE", "(", "SELF", "EQUALS", "cat", ")")},
|
// {".animals | (. == cat)", append(make([]interface{}, 0), "animals", "TRAVERSE", "(", "SELF", "EQUALS", "cat", ")")},
|
||||||
|
@ -1 +0,0 @@
|
|||||||
package treeops
|
|
Loading…
Reference in New Issue
Block a user