mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-13 22:38:04 +00:00
Maintain order
This commit is contained in:
parent
5d2d37a5f8
commit
44ee869e47
@ -2,21 +2,34 @@ package main
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
"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 {
|
||||
context[head] = value
|
||||
var entry = entryInSlice(context, head)
|
||||
entry.Value = value
|
||||
} else {
|
||||
// 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])
|
||||
switch parent.(type) {
|
||||
case map[interface{}]interface{}:
|
||||
toUpdate := parent.(map[interface{}]interface{})
|
||||
case yaml.MapSlice:
|
||||
toUpdate := parent.(yaml.MapSlice)
|
||||
// b is a map, update the key 'c' to the supplied value
|
||||
key := (tail[len(tail)-1])
|
||||
toUpdate[key] = value
|
||||
toUpdateEntry := entryInSlice(toUpdate, key)
|
||||
toUpdateEntry.Value = value
|
||||
case []interface{}:
|
||||
toUpdate := parent.([]interface{})
|
||||
// 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 == "*" {
|
||||
return readMapSplat(context, tail)
|
||||
}
|
||||
value := context[head]
|
||||
entry := entryInSlice(context, head)
|
||||
var value interface{}
|
||||
if entry != nil {
|
||||
value = entry.Value
|
||||
}
|
||||
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 i = 0
|
||||
for _, value := range context {
|
||||
for _, entry := range context {
|
||||
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 {
|
||||
newArray[i] = value
|
||||
newArray[i] = entry.Value
|
||||
}
|
||||
i++
|
||||
}
|
||||
@ -64,8 +81,8 @@ func recurse(value interface{}, head string, tail []string) interface{} {
|
||||
die("Error accessing array: %v", err)
|
||||
}
|
||||
return readArray(value.([]interface{}), index, tail)
|
||||
case map[interface{}]interface{}:
|
||||
return readMap(value.(map[interface{}]interface{}), head, tail)
|
||||
case yaml.MapSlice:
|
||||
return readMap(value.(yaml.MapSlice), head, tail)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
@ -107,6 +108,16 @@ e:
|
||||
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) {
|
||||
var data = parseData(`
|
||||
b:
|
||||
@ -114,9 +125,9 @@ b:
|
||||
`)
|
||||
|
||||
write(data, "b", []string{"c"}, "4")
|
||||
|
||||
b := data["b"].(map[interface{}]interface{})
|
||||
assertResult(t, "4", b["c"].(string))
|
||||
b := entryInSlice(data, "b").Value.(yaml.MapSlice)
|
||||
c := entryInSlice(b, "c").Value
|
||||
assertResult(t, "4", c)
|
||||
}
|
||||
|
||||
func TestWrite_array(t *testing.T) {
|
||||
@ -127,7 +138,7 @@ b:
|
||||
|
||||
write(data, "b", []string{"0"}, "bb")
|
||||
|
||||
b := data["b"].([]interface{})
|
||||
b := entryInSlice(data, "b").Value.([]interface{})
|
||||
assertResult(t, "bb", b[0].(string))
|
||||
}
|
||||
|
||||
@ -138,6 +149,6 @@ b:
|
||||
`)
|
||||
write(data, "b", []string{}, "4")
|
||||
|
||||
b := data["b"]
|
||||
b := entryInSlice(data, "b").Value
|
||||
assertResult(t, "4", fmt.Sprintf("%v", b))
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func fromJSONBytes(jsonBytes []byte, parsedData *map[interface{}]interface{}) {
|
||||
@ -55,11 +56,11 @@ func toJSON(context interface{}) interface{} {
|
||||
newArray[index] = toJSON(value)
|
||||
}
|
||||
return newArray
|
||||
case map[interface{}]interface{}:
|
||||
oldMap := context.(map[interface{}]interface{})
|
||||
case yaml.MapSlice:
|
||||
oldMap := context.(yaml.MapSlice)
|
||||
newMap := make(map[string]interface{})
|
||||
for key, value := range oldMap {
|
||||
newMap[key.(string)] = toJSON(value)
|
||||
for _, entry := range oldMap {
|
||||
newMap[entry.Key.(string)] = toJSON(entry.Value)
|
||||
}
|
||||
return newMap
|
||||
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"
|
||||
)
|
||||
|
||||
func parseData(rawData string) map[interface{}]interface{} {
|
||||
var parsedData map[interface{}]interface{}
|
||||
func parseData(rawData string) yaml.MapSlice {
|
||||
var parsedData yaml.MapSlice
|
||||
err := yaml.Unmarshal([]byte(rawData), &parsedData)
|
||||
if err != nil {
|
||||
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{} {
|
||||
var parsedData map[interface{}]interface{}
|
||||
var parsedData yaml.MapSlice
|
||||
|
||||
readData(args[0], &parsedData, inputJSON)
|
||||
|
||||
@ -114,13 +114,14 @@ func updateYaml(args []string) interface{} {
|
||||
writeCommands[args[1]] = parseValue(args[2])
|
||||
}
|
||||
|
||||
var parsedData map[interface{}]interface{}
|
||||
var parsedData yaml.MapSlice
|
||||
readData(args[0], &parsedData, inputJSON)
|
||||
|
||||
for path, value := range writeCommands {
|
||||
var paths = parsePath(path)
|
||||
write(parsedData, paths[0], paths[1:len(paths)], value)
|
||||
}
|
||||
|
||||
return parsedData
|
||||
}
|
||||
|
||||
|
16
yaml_test.go
16
yaml_test.go
@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -26,8 +27,21 @@ func TestRead(t *testing.T) {
|
||||
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) {
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user