mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Maintain order
This commit is contained in:
parent
5d2d37a5f8
commit
44ee869e47
@ -2,21 +2,34 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
// "fmt"
|
||||||
|
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func write(context map[interface{}]interface{}, head string, tail []string, value interface{}) {
|
func entryInSlice(context yaml.MapSlice, key interface{}) *yaml.MapItem {
|
||||||
|
for idx := range context {
|
||||||
|
var entry = &context[idx]
|
||||||
|
if entry.Key == key {
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func write(context yaml.MapSlice, head string, tail []string, value interface{}) {
|
||||||
if len(tail) == 0 {
|
if len(tail) == 0 {
|
||||||
context[head] = value
|
var entry = entryInSlice(context, head)
|
||||||
|
entry.Value = value
|
||||||
} else {
|
} else {
|
||||||
// e.g. if updating a.b.c, we need to get the 'b', this could be a map or an array
|
// e.g. if updating a.b.c, we need to get the 'b', this could be a map or an array
|
||||||
var parent = readMap(context, head, tail[0:len(tail)-1])
|
var parent = readMap(context, head, tail[0:len(tail)-1])
|
||||||
switch parent.(type) {
|
switch parent.(type) {
|
||||||
case map[interface{}]interface{}:
|
case yaml.MapSlice:
|
||||||
toUpdate := parent.(map[interface{}]interface{})
|
toUpdate := parent.(yaml.MapSlice)
|
||||||
// b is a map, update the key 'c' to the supplied value
|
// b is a map, update the key 'c' to the supplied value
|
||||||
key := (tail[len(tail)-1])
|
key := (tail[len(tail)-1])
|
||||||
toUpdate[key] = value
|
toUpdateEntry := entryInSlice(toUpdate, key)
|
||||||
|
toUpdateEntry.Value = value
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
toUpdate := parent.([]interface{})
|
toUpdate := parent.([]interface{})
|
||||||
// b is an array, update it at index 'c' to the supplied value
|
// b is an array, update it at index 'c' to the supplied value
|
||||||
@ -31,22 +44,26 @@ func write(context map[interface{}]interface{}, head string, tail []string, valu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readMap(context map[interface{}]interface{}, head string, tail []string) interface{} {
|
func readMap(context yaml.MapSlice, head string, tail []string) interface{} {
|
||||||
if head == "*" {
|
if head == "*" {
|
||||||
return readMapSplat(context, tail)
|
return readMapSplat(context, tail)
|
||||||
}
|
}
|
||||||
value := context[head]
|
entry := entryInSlice(context, head)
|
||||||
|
var value interface{}
|
||||||
|
if entry != nil {
|
||||||
|
value = entry.Value
|
||||||
|
}
|
||||||
return calculateValue(value, tail)
|
return calculateValue(value, tail)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readMapSplat(context map[interface{}]interface{}, tail []string) interface{} {
|
func readMapSplat(context yaml.MapSlice, tail []string) interface{} {
|
||||||
var newArray = make([]interface{}, len(context))
|
var newArray = make([]interface{}, len(context))
|
||||||
var i = 0
|
var i = 0
|
||||||
for _, value := range context {
|
for _, entry := range context {
|
||||||
if len(tail) > 0 {
|
if len(tail) > 0 {
|
||||||
newArray[i] = recurse(value, tail[0], tail[1:len(tail)])
|
newArray[i] = recurse(entry.Value, tail[0], tail[1:len(tail)])
|
||||||
} else {
|
} else {
|
||||||
newArray[i] = value
|
newArray[i] = entry.Value
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
@ -64,8 +81,8 @@ func recurse(value interface{}, head string, tail []string) interface{} {
|
|||||||
die("Error accessing array: %v", err)
|
die("Error accessing array: %v", err)
|
||||||
}
|
}
|
||||||
return readArray(value.([]interface{}), index, tail)
|
return readArray(value.([]interface{}), index, tail)
|
||||||
case map[interface{}]interface{}:
|
case yaml.MapSlice:
|
||||||
return readMap(value.(map[interface{}]interface{}), head, tail)
|
return readMap(value.(yaml.MapSlice), head, tail)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -107,6 +108,16 @@ e:
|
|||||||
assertResult(t, "[Fred Sam]", fmt.Sprintf("%v", readMap(data, "e", []string{"*", "name"})))
|
assertResult(t, "[Fred Sam]", fmt.Sprintf("%v", readMap(data, "e", []string{"*", "name"})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWrite_really_simple(t *testing.T) {
|
||||||
|
var data = parseData(`
|
||||||
|
b: 2
|
||||||
|
`)
|
||||||
|
|
||||||
|
write(data, "b", []string{}, "4")
|
||||||
|
b := entryInSlice(data, "b").Value
|
||||||
|
assertResult(t, "4", b)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWrite_simple(t *testing.T) {
|
func TestWrite_simple(t *testing.T) {
|
||||||
var data = parseData(`
|
var data = parseData(`
|
||||||
b:
|
b:
|
||||||
@ -114,9 +125,9 @@ b:
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
write(data, "b", []string{"c"}, "4")
|
write(data, "b", []string{"c"}, "4")
|
||||||
|
b := entryInSlice(data, "b").Value.(yaml.MapSlice)
|
||||||
b := data["b"].(map[interface{}]interface{})
|
c := entryInSlice(b, "c").Value
|
||||||
assertResult(t, "4", b["c"].(string))
|
assertResult(t, "4", c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWrite_array(t *testing.T) {
|
func TestWrite_array(t *testing.T) {
|
||||||
@ -127,7 +138,7 @@ b:
|
|||||||
|
|
||||||
write(data, "b", []string{"0"}, "bb")
|
write(data, "b", []string{"0"}, "bb")
|
||||||
|
|
||||||
b := data["b"].([]interface{})
|
b := entryInSlice(data, "b").Value.([]interface{})
|
||||||
assertResult(t, "bb", b[0].(string))
|
assertResult(t, "bb", b[0].(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +149,6 @@ b:
|
|||||||
`)
|
`)
|
||||||
write(data, "b", []string{}, "4")
|
write(data, "b", []string{}, "4")
|
||||||
|
|
||||||
b := data["b"]
|
b := entryInSlice(data, "b").Value
|
||||||
assertResult(t, "4", fmt.Sprintf("%v", b))
|
assertResult(t, "4", fmt.Sprintf("%v", b))
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fromJSONBytes(jsonBytes []byte, parsedData *map[interface{}]interface{}) {
|
func fromJSONBytes(jsonBytes []byte, parsedData *map[interface{}]interface{}) {
|
||||||
@ -55,11 +56,11 @@ func toJSON(context interface{}) interface{} {
|
|||||||
newArray[index] = toJSON(value)
|
newArray[index] = toJSON(value)
|
||||||
}
|
}
|
||||||
return newArray
|
return newArray
|
||||||
case map[interface{}]interface{}:
|
case yaml.MapSlice:
|
||||||
oldMap := context.(map[interface{}]interface{})
|
oldMap := context.(yaml.MapSlice)
|
||||||
newMap := make(map[string]interface{})
|
newMap := make(map[string]interface{})
|
||||||
for key, value := range oldMap {
|
for _, entry := range oldMap {
|
||||||
newMap[key.(string)] = toJSON(value)
|
newMap[entry.Key.(string)] = toJSON(entry.Value)
|
||||||
}
|
}
|
||||||
return newMap
|
return newMap
|
||||||
default:
|
default:
|
||||||
|
2
order.yaml
Normal file
2
order.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
version: 3
|
||||||
|
application: MyApp
|
6
order.yml
Normal file
6
order.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
version: '2'
|
||||||
|
services:
|
||||||
|
test:
|
||||||
|
image: ubuntu:14.04
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
@ -7,8 +7,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseData(rawData string) map[interface{}]interface{} {
|
func parseData(rawData string) yaml.MapSlice {
|
||||||
var parsedData map[interface{}]interface{}
|
var parsedData yaml.MapSlice
|
||||||
err := yaml.Unmarshal([]byte(rawData), &parsedData)
|
err := yaml.Unmarshal([]byte(rawData), &parsedData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error parsing yaml: %v", err)
|
fmt.Println("Error parsing yaml: %v", err)
|
||||||
|
5
yaml.go
5
yaml.go
@ -81,7 +81,7 @@ func readProperty(cmd *cobra.Command, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func read(args []string) interface{} {
|
func read(args []string) interface{} {
|
||||||
var parsedData map[interface{}]interface{}
|
var parsedData yaml.MapSlice
|
||||||
|
|
||||||
readData(args[0], &parsedData, inputJSON)
|
readData(args[0], &parsedData, inputJSON)
|
||||||
|
|
||||||
@ -114,13 +114,14 @@ func updateYaml(args []string) interface{} {
|
|||||||
writeCommands[args[1]] = parseValue(args[2])
|
writeCommands[args[1]] = parseValue(args[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsedData map[interface{}]interface{}
|
var parsedData yaml.MapSlice
|
||||||
readData(args[0], &parsedData, inputJSON)
|
readData(args[0], &parsedData, inputJSON)
|
||||||
|
|
||||||
for path, value := range writeCommands {
|
for path, value := range writeCommands {
|
||||||
var paths = parsePath(path)
|
var paths = parsePath(path)
|
||||||
write(parsedData, paths[0], paths[1:len(paths)], value)
|
write(parsedData, paths[0], paths[1:len(paths)], value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedData
|
return parsedData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
yaml_test.go
16
yaml_test.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,8 +27,21 @@ func TestRead(t *testing.T) {
|
|||||||
assertResult(t, 2, result)
|
assertResult(t, 2, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOrder(t *testing.T) {
|
||||||
|
result := read([]string{"order.yaml"})
|
||||||
|
formattedResult := yamlToString(result)
|
||||||
|
assertResult(t,
|
||||||
|
`version: 3
|
||||||
|
application: MyApp`,
|
||||||
|
formattedResult)
|
||||||
|
}
|
||||||
|
|
||||||
func TestUpdateYaml(t *testing.T) {
|
func TestUpdateYaml(t *testing.T) {
|
||||||
updateYaml([]string{"sample.yaml", "b.c", "3"})
|
result := updateYaml([]string{"sample.yaml", "b.c", "3"})
|
||||||
|
formattedResult := fmt.Sprintf("%v", result)
|
||||||
|
assertResult(t,
|
||||||
|
"[{a Easy! as one two three} {b [{c 3} {d [3 4]} {e [[{name fred} {value 3}] [{name sam} {value 4}]]}]}]",
|
||||||
|
formattedResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateYaml_WithScript(t *testing.T) {
|
func TestUpdateYaml_WithScript(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user