Skip to content

Commit

Permalink
Maintain order
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Farah committed Feb 26, 2017
1 parent 5d2d37a commit 44ee869
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 27 deletions.
43 changes: 30 additions & 13 deletions data_navigator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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++
}
Expand All @@ -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
}
Expand Down
21 changes: 16 additions & 5 deletions data_navigator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"github.com/mikefarah/yaml/Godeps/_workspace/src/gopkg.in/yaml.v2"
"sort"
"testing"
)
Expand Down Expand Up @@ -107,16 +108,26 @@ 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:
c: 2
`)

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) {
Expand All @@ -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))
}

Expand All @@ -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))
}
9 changes: 5 additions & 4 deletions json_converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}) {
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions order.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
version: 3
application: MyApp
6 changes: 6 additions & 0 deletions order.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: '2'
services:
test:
image: ubuntu:14.04
stdin_open: true
tty: true
4 changes: 2 additions & 2 deletions utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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
}

Expand Down
16 changes: 15 additions & 1 deletion yaml_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"testing"
)

Expand All @@ -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) {
Expand Down

0 comments on commit 44ee869

Please sign in to comment.