1
0
mirror of https://github.com/taigrr/yq synced 2025-01-18 04:53:17 -08:00

Compare commits

...

4 Commits
1.5 ... 1.6

Author SHA1 Message Date
Mike Farah
44ee869e47 Maintain order 2017-02-27 09:09:29 +11:00
Mike Farah
5d2d37a5f8 Fixed travis script, added Travis banner to readme 2017-02-13 07:55:06 +11:00
Mike Farah
e3fc944709 Added travis config 2017-02-13 07:28:48 +11:00
Mike Farah
6ee9db9a70 Added License (MIT) 2017-02-10 16:00:25 +11:00
13 changed files with 121 additions and 39 deletions

4
.travis.yml Normal file
View File

@@ -0,0 +1,4 @@
language: go
go:
- 1.7.x
script: ./ci.sh

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2017 Mike Farah
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,4 +1,4 @@
# yaml
# yaml [![Build Status](https://travis-ci.org/mikefarah/yaml.svg?branch=master)](https://travis-ci.org/mikefarah/yaml)
yaml is a lightweight and flexible command-line YAML processor
The aim of the project is to be the [jq](https://github.com/stedolan/jq) or sed of yaml files.

15
ci.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
set -e
go test
go build
# acceptance test
X=$(./yaml w sample.yaml b.c 3 | ./yaml r - b.c)
if [ $X != 3 ]
then
echo "Failed acceptance test: expected 2 but was $X"
exit 1
fi

View File

@@ -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
}

View File

@@ -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))
}

View File

@@ -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
View File

@@ -0,0 +1,2 @@
version: 3
application: MyApp

6
order.yml Normal file
View File

@@ -0,0 +1,6 @@
version: '2'
services:
test:
image: ubuntu:14.04
stdin_open: true
tty: true

View File

@@ -1,17 +1,9 @@
#!/bin/bash
set -e
gofmt -w .
golint
go test
go build
# acceptance test
X=$(./yaml w sample.yaml b.c 3 | ./yaml r - b.c)
if [ $X != 3 ]
then
echo "Failed acceptance test: expected 2 but was $X"
exit 1
fi
./ci.sh
go install

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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) {