diff --git a/.gitignore b/.gitignore index c85b1cf..3085803 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ goml-linux-amd64 goml-darwin-amd64 vendor/* +goml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9e1bf56 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +all: + go build -o goml cmd/goml/main.go +test: + go test diff --git a/main.go b/cmd/goml/main.go similarity index 71% rename from main.go rename to cmd/goml/main.go index 870016f..12290c6 100644 --- a/main.go +++ b/cmd/goml/main.go @@ -3,10 +3,9 @@ package main import ( "errors" "fmt" - "io/ioutil" "os" - "github.com/JulzDiverse/goml/goml" + "github.com/JulzDiverse/goml" "github.com/fatih/color" "github.com/urfave/cli" ) @@ -74,10 +73,7 @@ func getParam(c *cli.Context) { os.Exit(1) } - yaml, err := goml.ReadYamlFromFile(c.String("file")) - exitWithError(err) - - res, err := goml.Get(yaml, c.String("prop")) + res, err := goml.GetFromFile(c.String("file"), c.String("prop")) exitWithError(err) fmt.Println(res) @@ -89,21 +85,14 @@ func setParam(c *cli.Context) { exitWithError(errors.New("invalid number of arguments")) } - yaml, err := goml.ReadYamlFromFile(c.String("file")) - exitWithError(err) - - var value string + var err error if c.String("value") != "" { - value = c.String("value") + value := c.String("value") + err = goml.SetInFile(c.String("file"), c.String("prop"), value) } else if c.String("key") != "" { - bytes, err := ioutil.ReadFile(c.String("key")) - exitWithError(err) - value = string(bytes) + err = goml.SetKeyInFile(c.String("file"), c.String("prop"), c.String("key")) } - - err = goml.Set(yaml, c.String("prop"), value) exitWithError(err) - goml.WriteYaml(yaml, c.String("file")) } func deleteParam(c *cli.Context) { @@ -112,15 +101,8 @@ func deleteParam(c *cli.Context) { exitWithError(errors.New("invalid number of arguments")) } - yaml, err := goml.ReadYamlFromFile(c.String("file")) + err := goml.DeleteInFile(c.String("file"), c.String("prop")) exitWithError(err) - - err = goml.Delete(yaml, c.String("prop")) - if err != nil { - exitWithError(errors.New("Couldn't delete property for path: " + c.String("prop"))) - } - - goml.WriteYaml(yaml, c.String("file")) } func transferParam(c *cli.Context) { @@ -129,18 +111,8 @@ func transferParam(c *cli.Context) { exitWithError(errors.New("invalid number of arguments")) } - sourceYaml, err := goml.ReadYamlFromFile(c.String("file")) - exitWithError(err) - - destYaml, err := goml.ReadYamlFromFile(c.String("df")) + err := goml.TransferToFile(c.String("file"), c.String("prop"), c.String("df"), c.String("dp")) exitWithError(err) - - value, _ := goml.Get(sourceYaml, c.String("prop")) - - err = goml.Set(destYaml, c.String("dp"), value) - exitWithError(err) - - goml.WriteYaml(destYaml, c.String("df")) } func exitWithError(err error) { diff --git a/delete.go b/delete.go new file mode 100644 index 0000000..6872270 --- /dev/null +++ b/delete.go @@ -0,0 +1,99 @@ +package goml + +import ( + "errors" + "os" + "strconv" + "strings" + + "github.com/smallfish/simpleyaml" +) + +func DeleteInFile(file string, path string) error { + yaml, err := ReadYamlFromFile(file) + if err != nil { + return err + } + + err = Delete(yaml, path) + if err != nil { + return errors.New("Couldn't delete property for path: " + path) + } + + if yaml.IsMap() { + keys, err := yaml.GetMapKeys() + if err != nil { + return err + } + + if len(keys) == 0 { + err = os.Remove(path) + if err != nil { + return err + } + } + } + + return WriteYaml(yaml, file) +} + +func Delete(yml *simpleyaml.Yaml, path string) error { + propsArr := strings.Split(path, ".") + propName := propsArr[len(propsArr)-1] + props := propsArr[:len(propsArr)-1] + newPath := strings.Join(props, ".") + + if index, err := strconv.Atoi(propName); err == nil { + tmp, props := get(yml, newPath) + prop, err := tmp.Array() + if err != nil { + return err + } + + prop = append(prop[:index], prop[index+1:]...) + + updateYaml(yml, props, prop) + return nil + } + + if strings.Contains(propName, ":") { + tmp, props := get(yml, newPath) + prop, err := tmp.Array() + if err != nil { + return err + } + + index, err := returnIndexForProp(propName, prop) + if err != nil { + return err + } + + prop = append(prop[:index], prop[index+1:]...) + updateYaml(yml, props, prop) + return nil + } + + var res map[interface{}]interface{} + if len(propsArr) == 1 { + tmp, err := yml.Map() + if err != nil { + return err + } + res = tmp + } else { + prop, _ := get(yml, newPath) + tmp, err := prop.Map() + if err != nil { + return err + } + res = tmp + } + _, ok := res[propName] + if ok { + delete(res, propName) + } else { + return errors.New("property not found") + } + + return nil +} diff --git a/delete_test.go b/delete_test.go new file mode 100644 index 0000000..8851fa2 --- /dev/null +++ b/delete_test.go @@ -0,0 +1,80 @@ +package goml_test + +import ( + . "github.com/JulzDiverse/goml" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/smallfish/simpleyaml" +) + +var _ = Describe("Delete", func() { + var yml *simpleyaml.Yaml + var err error + + BeforeEach(func() { + yaml := `map: + name: foo + +array: +- bar +- var +- zar + +mapArray: +- foo: bar + zoo: lion + arr: + - one + - two + - three +- foo: var + boo: laa` + + yml, err = simpleyaml.NewYaml([]byte(yaml)) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should delete a value from a map", func() { + err = Delete(yml, "map.name") + Expect(err).NotTo(HaveOccurred()) + + _, err = Get(yml, "map.name") + Expect(err).To(MatchError("property not found")) + }) + + It("should delete a value from an array ", func() { + err = Delete(yml, "array.0") + Expect(err).NotTo(HaveOccurred()) + + _, err := Get(yml, "array.:bar") + Expect(err).To(MatchError("property not found")) + + err = Delete(yml, "array.:zar") + Expect(err).NotTo(HaveOccurred()) + _, err = Get(yml, "array.:zar") + Expect(err).To(MatchError("property not found")) + }) + + It("should delete a value from an map inside an array ", func() { + err = Delete(yml, "mapArray.foo:bar.zoo") + Expect(err).NotTo(HaveOccurred()) + + _, err := Get(yml, "mapArray.foo:bar.zoo") + Expect(err).To(HaveOccurred()) + }) + + It("should delete a value from an array inside a map which in turn is inside an array ", func() { + err = Delete(yml, "mapArray.foo:bar.arr.0") + Expect(err).NotTo(HaveOccurred()) + + _, err := Get(yml, "mapArray.foo:bar.arr.:one") + Expect(err).To(MatchError("property not found")) + + err = Delete(yml, "mapArray.foo:bar.arr.:two") + Expect(err).NotTo(HaveOccurred()) + + _, err = Get(yml, "mapArray.foo:bar.arr.:two") + Expect(err).To(MatchError("property not found")) + }) +}) diff --git a/get.go b/get.go new file mode 100644 index 0000000..a4f10e0 --- /dev/null +++ b/get.go @@ -0,0 +1,75 @@ +package goml + +import ( + "errors" + "strconv" + "strings" + + "github.com/smallfish/simpleyaml" +) + +func GetFromFile(file string, path string) (interface{}, error) { + yaml, err := ReadYamlFromFile(file) + if err != nil { + return nil, err + } + + return Get(yaml, path) +} + +func GetFromFileAsSimpleYaml(file string, path string) (*simpleyaml.Yaml, error) { + yaml, err := ReadYamlFromFile(file) + if err != nil { + return nil, err + } + + return GetAsSimpleYaml(yaml, path) +} + +func Get(yml *simpleyaml.Yaml, path string) (interface{}, error) { + val, ok := get(yml, path) + if ok == nil { + return nil, errors.New("property not found") + } + + result, err := ExtractType(val) + return result, err +} + +func GetAsSimpleYaml(yml *simpleyaml.Yaml, path string) (*simpleyaml.Yaml, error) { + val, ok := get(yml, path) + if ok == nil { + return nil, errors.New("property not found") + } + + return val, nil +} + +func get(yml *simpleyaml.Yaml, path string) (*simpleyaml.Yaml, []string) { + solvedPath := []string{} + + props := strings.Split(path, ".") + for _, p := range props { + if index, err := strconv.Atoi(p); err == nil { + yml = yml.GetIndex(index) + solvedPath = append(solvedPath, strconv.Itoa(index)) + continue + } + + if strings.Contains(p, ":") { + if prop, err := yml.Array(); err == nil { + index, err := returnIndexForProp(p, prop) + if err != nil { + return yml, nil + } + + yml = yml.GetIndex(index) + solvedPath = append(solvedPath, strconv.Itoa(index)) + continue + } + } + solvedPath = append(solvedPath, p) + yml = yml.Get(p) + } + return yml, solvedPath +} diff --git a/get_test.go b/get_test.go new file mode 100644 index 0000000..2ae0c8e --- /dev/null +++ b/get_test.go @@ -0,0 +1,63 @@ +package goml_test + +import ( + . "github.com/JulzDiverse/goml" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/smallfish/simpleyaml" +) + +var _ = Describe("Get", func() { + var yml *simpleyaml.Yaml + var err error + + BeforeEach(func() { + yaml := `map: + name: foo + +array: +- bar +- var +- zar + +mapArray: +- foo: bar + zoo: lion + arr: + - one + - two + - three +- foo: var + boo: laa` + + yml, err = simpleyaml.NewYaml([]byte(yaml)) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should get a value from a map, array, array with maps", func() { + value, err := Get(yml, "map.name") + Expect(err).NotTo(HaveOccurred()) + Expect(value).To(Equal("foo")) + + value, err = Get(yml, "array.0") + Expect(err).NotTo(HaveOccurred()) + Expect(value).To(Equal("bar")) + + value, err = Get(yml, "mapArray.0.foo") + Expect(err).NotTo(HaveOccurred()) + Expect(value).To(Equal("bar")) + + value, err = Get(yml, "mapArray.foo:var.boo") + Expect(err).NotTo(HaveOccurred()) + Expect(value).To(Equal("laa")) + + value, err = Get(yml, "array.:var") + Expect(err).NotTo(HaveOccurred()) + Expect(value).To(Equal("var")) + + value, err = Get(yml, "mapArray.foo:bar.arr.0") + Expect(err).NotTo(HaveOccurred()) + Expect(value).To(Equal("one")) + }) +}) diff --git a/goml/goml.go b/goml/goml.go deleted file mode 100644 index 164af44..0000000 --- a/goml/goml.go +++ /dev/null @@ -1,347 +0,0 @@ -package goml - -import ( - "errors" - "fmt" - "io/ioutil" - "strconv" - "strings" - - "github.com/smallfish/simpleyaml" - "gopkg.in/yaml.v2" -) - -func Get(yml *simpleyaml.Yaml, path string) (interface{}, error) { - val, ok := get(yml, path) - if ok == nil { - return nil, errors.New("property not found") - } - - result, err := ExtractType(val) - return result, err -} - -func GetAsSimpleYaml(yml *simpleyaml.Yaml, path string) (*simpleyaml.Yaml, error) { - val, ok := get(yml, path) - if ok == nil { - return nil, errors.New("property not found") - } - - return val, nil -} - -func ExtractType(value *simpleyaml.Yaml) (interface{}, error) { - if v, err := value.String(); err == nil { - return v, nil - } - if v, err := value.Bool(); err == nil { - return strconv.FormatBool(v), nil - } - if v, err := value.Int(); err == nil { - return strconv.Itoa(v), nil - } - if v, err := value.Float(); err == nil { - return fmt.Sprint(v), nil - } - if v, err := value.Array(); err == nil { - strSl := []string{} - for _, val := range v { - tmp := extractArrayType(val) - strSl = append(strSl, tmp) - } - str := strings.Join(strSl, ",") - return str, nil - } - if v, err := value.Map(); err == nil { - return v, nil - } - return nil, errors.New("property not found") -} - -func extractArrayType(value interface{}) string { - switch t := value.(type) { - default: - fmt.Printf("unexpected type %T\n", t) - case string: - return value.(string) - case bool: - return strconv.FormatBool(value.(bool)) - case int: - return strconv.Itoa(value.(int)) - case float64: - return fmt.Sprint(value.(float64)) - } - return "" -} - -func Set(yml *simpleyaml.Yaml, path string, val interface{}) error { - propsArr := strings.Split(path, ".") - propName := propsArr[len(propsArr)-1] - props := propsArr[:len(propsArr)-1] - newPath := strings.Join(props, ".") - - if index, err := strconv.Atoi(propName); err == nil { - tmp, props := get(yml, newPath) - if props == nil { - return errors.New("property not found") - } - - prop, err := tmp.Array() - if err != nil { - return err - } - - prop[index] = convertValueType(val) - - updateYaml(yml, props, prop) - return nil - } - - if propName == "+" { - tmp, props := get(yml, newPath) - prop, err := tmp.Array() - if err != nil { - return err - } - resolved := convertValueType(val) - prop = append(prop, resolved) - updateYaml(yml, props, prop) - return nil - } - - if strings.Contains(propName, ":") { - tmp, props := get(yml, newPath) - prop, err := tmp.Array() - if err != nil { - return err - } - - index, err := returnIndexForProp(propName, prop) - if err != nil { - return err - } - - prop[index] = convertValueType(val) - updateYaml(yml, props, prop) - return nil - } - - if len(propsArr) == 1 { - prop, _ := yml.Map() - prop[path] = convertValueType(val) - return nil - } - - tmp, _ := get(yml, newPath) - prop, err := tmp.Map() - if err != nil { - return err - } - - prop[propName] = convertValueType(val) - - return nil -} - -func Delete(yml *simpleyaml.Yaml, path string) error { - propsArr := strings.Split(path, ".") - propName := propsArr[len(propsArr)-1] - props := propsArr[:len(propsArr)-1] - newPath := strings.Join(props, ".") - - if index, err := strconv.Atoi(propName); err == nil { - tmp, props := get(yml, newPath) - prop, err := tmp.Array() - if err != nil { - return err - } - - prop = append(prop[:index], prop[index+1:]...) - - updateYaml(yml, props, prop) - return nil - } - - if strings.Contains(propName, ":") { - tmp, props := get(yml, newPath) - prop, err := tmp.Array() - if err != nil { - return err - } - - index, err := returnIndexForProp(propName, prop) - if err != nil { - return err - } - - prop = append(prop[:index], prop[index+1:]...) - updateYaml(yml, props, prop) - return nil - } - - var res map[interface{}]interface{} - if len(propsArr) == 1 { - tmp, err := yml.Map() - if err != nil { - return err - } - res = tmp - } else { - prop, _ := get(yml, newPath) - tmp, err := prop.Map() - if err != nil { - return err - } - res = tmp - } - _, ok := res[propName] - if ok { - delete(res, propName) - } else { - return errors.New("property not found") - } - - return nil -} - -func convertValueType(val interface{}) interface{} { - switch val.(type) { - default: - return val - case string: - str := val.(string) - if value, err := strconv.Atoi(str); err == nil { - return value - } - if value, err := strconv.ParseBool(str); err == nil { - return value - } - } - return val -} - -func SetValueForType(yaml *simpleyaml.Yaml, path string, value *simpleyaml.Yaml) error { - if v, err := value.String(); err == nil { - err := Set(yaml, path, v) - return err - } - if v, err := value.Bool(); err == nil { - err := Set(yaml, path, v) - return err - } - if v, err := value.Int(); err == nil { - err := Set(yaml, path, v) - return err - } - if v, err := value.Float(); err == nil { - err := Set(yaml, path, v) - return err - } - if v, err := value.Array(); err == nil { - err := Set(yaml, path, v) - return err - } - if v, err := value.Map(); err == nil { - err := Set(yaml, path, v) - return err - } - return nil -} - -func WriteYaml(yml *simpleyaml.Yaml, file string) error { - goml, err := yml.Map() - if err != nil { - return err - } - - gomlSave, err := yaml.Marshal(goml) - if err != nil { - return err - } - - return ioutil.WriteFile(file, gomlSave, 0644) -} - -func ReadYaml(yaml []byte) (*simpleyaml.Yaml, error) { - yml, err := simpleyaml.NewYaml(yaml) - if err != nil { - return nil, err - } - return yml, nil -} - -func ReadYamlFromFile(filename string) (*simpleyaml.Yaml, error) { - file, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - - return simpleyaml.NewYaml(file) -} - -func get(yml *simpleyaml.Yaml, path string) (*simpleyaml.Yaml, []string) { - solvedPath := []string{} - - props := strings.Split(path, ".") - for _, p := range props { - if index, err := strconv.Atoi(p); err == nil { - yml = yml.GetIndex(index) - solvedPath = append(solvedPath, strconv.Itoa(index)) - continue - } - - if strings.Contains(p, ":") { - if prop, err := yml.Array(); err == nil { - index, err := returnIndexForProp(p, prop) - if err != nil { - return yml, nil - } - - yml = yml.GetIndex(index) - solvedPath = append(solvedPath, strconv.Itoa(index)) - continue - } - } - solvedPath = append(solvedPath, p) - yml = yml.Get(p) - } - return yml, solvedPath -} - -func updateYaml(yml *simpleyaml.Yaml, props []string, prop []interface{}) { - var yaml map[interface{}]interface{} - propName := props[len(props)-1] - - if len(props) > 1 { - props = props[:len(props)-1] - tmp, _ := get(yml, strings.Join(props, ".")) - yaml, _ = tmp.Map() - } else { - yaml, _ = yml.Map() - } - - yaml[propName] = prop -} - -func returnIndexForProp(propName string, array []interface{}) (int, error) { - keyVal := strings.Split(propName, ":") - key, val := keyVal[0], keyVal[1] - - for i, _ := range array { - if key == "" { - - check := array[i] - if check == val { - return i, nil - } - - } else { - check := array[i].(map[interface{}]interface{}) - if check[key] == val { - return i, nil - } - } - } - - return 0, errors.New("property not found") -} diff --git a/goml/goml_test.go b/goml/goml_test.go deleted file mode 100644 index 4b75ba9..0000000 --- a/goml/goml_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package goml_test - -import ( - . "github.com/JulzDiverse/goml/goml" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/smallfish/simpleyaml" -) - -var _ = Describe("Goml", func() { - - var yaml string - BeforeEach(func() { - yaml = `map: - name: foo - -array: -- bar -- var -- zar - -mapArray: -- foo: bar - zoo: lion - arr: - - one - - two - - three -- foo: var - boo: laa` - }) - - Context("Get", func() { - It("should get a value from a map, array, array with maps", func() { - yml, _ := simpleyaml.NewYaml([]byte(yaml)) - - Expect(Get(yml, "map.name")).To(Equal("foo")) - Expect(Get(yml, "array.0")).To(Equal("bar")) - Expect(Get(yml, "mapArray.0.foo")).To(Equal("bar")) - Expect(Get(yml, "mapArray.foo:var.boo")).To(Equal("laa")) - Expect(Get(yml, "array.:var")).To(Equal("var")) - Expect(Get(yml, "mapArray.foo:bar.arr.0")).To(Equal("one")) - - }) - }) - - Context("Set", func() { - It("should add an value to an array", func() { - yml, _ := simpleyaml.NewYaml([]byte(yaml)) - - Set(yml, "array.2", "bumblebee") - Set(yml, "array.+", "optimusPrime") - Set(yml, "mapArray.0.foo", "wolverine") - Set(yml, "mapArray.foo:var.boo", "baymax") - - Expect(Get(yml, "array.2")).To(Equal("bumblebee")) - Expect(Get(yml, "array.3")).To(Equal("optimusPrime")) - Expect(Get(yml, "mapArray.0.foo")).To(Equal("wolverine")) - Expect(Get(yml, "mapArray.foo:var.boo")).To(Equal("baymax")) - - Set(yml, "array.:optimusPrime", "pikachu") - Expect(Get(yml, "array.:pikachu")).To(Equal("pikachu")) - Set(yml, "mapArray.foo:wolverine.arr.0", "new") - Expect(Get(yml, "mapArray.foo:wolverine.arr.0")).To(Equal("new")) - }) - }) - - Context("Delete", func() { - It("should delete a value from a map", func() { - yml, _ := simpleyaml.NewYaml([]byte(yaml)) - Delete(yml, "map.name") - _, err := Get(yml, "map.name") - Expect(err).NotTo(BeNil()) - }) - - It("should delete a value from an array ", func() { - yml, _ := simpleyaml.NewYaml([]byte(yaml)) - Delete(yml, "array.0") - _, err := Get(yml, "array.:bar") - Expect(err).NotTo(BeNil()) - - Delete(yml, "array.:zar") - _, err = Get(yml, "array.:zar") - Expect(err).NotTo(BeNil()) - - }) - - It("should delete a value from an map inside an array ", func() { - yml, _ := simpleyaml.NewYaml([]byte(yaml)) - Delete(yml, "array.mapArray.foo:bar.zoo") - _, err := Get(yml, "array.mapArray.foo:bar.zoo") - Expect(err).NotTo(BeNil()) - }) - - It("should delete a value from an array inside a map which in turn is inside an array ", func() { - yml, _ := simpleyaml.NewYaml([]byte(yaml)) - Delete(yml, "array.mapArray.foo:bar.arr.0") - _, err := Get(yml, "array.mapArray.foo:bar.arr.:one") - Expect(err).NotTo(BeNil()) - - Delete(yml, "array.mapArray.foo:bar.arr.:two") - _, err = Get(yml, "array.mapArray.foo:bar.arr.:two") - Expect(err).NotTo(BeNil()) - }) - }) - -}) diff --git a/goml/goml_suite_test.go b/goml_suite_test.go similarity index 100% rename from goml/goml_suite_test.go rename to goml_suite_test.go diff --git a/set.go b/set.go new file mode 100644 index 0000000..319afaa --- /dev/null +++ b/set.go @@ -0,0 +1,158 @@ +package goml + +import ( + "errors" + "io/ioutil" + "strconv" + "strings" + + "github.com/smallfish/simpleyaml" +) + +func SetKeyInFile(file string, path string, key string) error { + yaml, err := ReadYamlFromFile(file) + if err != nil { + return err + } + + err = SetKey(yaml, path, key) + if err != nil { + return err + } + + return WriteYaml(yaml, file) +} + +func SetKey(yaml *simpleyaml.Yaml, path string, key string) error { + bytes, err := ioutil.ReadFile(key) + if err != nil { + return err + } + return Set(yaml, path, string(bytes)) +} + +func SetInFile(file string, path string, val interface{}) error { + yaml, err := ReadYamlFromFile(file) + if err != nil { + return err + } + + err = Set(yaml, path, val) + if err != nil { + return err + } + + return WriteYaml(yaml, file) +} + +func Set(yml *simpleyaml.Yaml, path string, val interface{}) error { + propsArr := strings.Split(path, ".") + propName := propsArr[len(propsArr)-1] + props := propsArr[:len(propsArr)-1] + newPath := strings.Join(props, ".") + + if index, err := strconv.Atoi(propName); err == nil { + tmp, props := get(yml, newPath) + if props == nil { + return errors.New("property not found") + } + + prop, err := tmp.Array() + if err != nil { + return err + } + + prop[index] = convertValueType(val) + + updateYaml(yml, props, prop) + return nil + } + + if propName == "+" { + tmp, props := get(yml, newPath) + prop, err := tmp.Array() + if err != nil { + return err + } + resolved := convertValueType(val) + prop = append(prop, resolved) + updateYaml(yml, props, prop) + return nil + } + + if strings.Contains(propName, ":") { + tmp, props := get(yml, newPath) + prop, err := tmp.Array() + if err != nil { + return err + } + + index, err := returnIndexForProp(propName, prop) + if err != nil { + return err + } + + prop[index] = convertValueType(val) + updateYaml(yml, props, prop) + return nil + } + + if len(propsArr) == 1 { + prop, _ := yml.Map() + prop[path] = convertValueType(val) + return nil + } + + tmp, _ := get(yml, newPath) + prop, err := tmp.Map() + if err != nil { + return err + } + + prop[propName] = convertValueType(val) + + return nil +} + +func SetValueForType(yaml *simpleyaml.Yaml, path string, value *simpleyaml.Yaml) error { + if v, err := value.String(); err == nil { + err := Set(yaml, path, v) + return err + } + if v, err := value.Bool(); err == nil { + err := Set(yaml, path, v) + return err + } + if v, err := value.Int(); err == nil { + err := Set(yaml, path, v) + return err + } + if v, err := value.Float(); err == nil { + err := Set(yaml, path, v) + return err + } + if v, err := value.Array(); err == nil { + err := Set(yaml, path, v) + return err + } + if v, err := value.Map(); err == nil { + err := Set(yaml, path, v) + return err + } + return nil +} + +func updateYaml(yml *simpleyaml.Yaml, props []string, prop []interface{}) { + var yaml map[interface{}]interface{} + propName := props[len(props)-1] + + if len(props) > 1 { + props = props[:len(props)-1] + tmp, _ := get(yml, strings.Join(props, ".")) + yaml, _ = tmp.Map() + } else { + yaml, _ = yml.Map() + } + + yaml[propName] = prop +} diff --git a/set_test.go b/set_test.go new file mode 100644 index 0000000..3650bbb --- /dev/null +++ b/set_test.go @@ -0,0 +1,58 @@ +package goml_test + +import ( + . "github.com/JulzDiverse/goml" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/smallfish/simpleyaml" +) + +var _ = Describe("Set", func() { + var yml *simpleyaml.Yaml + var err error + + BeforeEach(func() { + yaml := `map: + name: foo + +array: +- bar +- var +- zar + +mapArray: +- foo: bar + zoo: lion + arr: + - one + - two + - three +- foo: var + boo: laa` + + yml, err = simpleyaml.NewYaml([]byte(yaml)) + Expect(err).NotTo(HaveOccurred()) + }) + + It("should add an value to an array", func() { + err = Set(yml, "array.2", "bumblebee") + Expect(err).NotTo(HaveOccurred()) + err = Set(yml, "array.+", "optimusPrime") + Expect(err).NotTo(HaveOccurred()) + err = Set(yml, "mapArray.0.foo", "wolverine") + Expect(err).NotTo(HaveOccurred()) + err = Set(yml, "mapArray.foo:var.boo", "baymax") + Expect(err).NotTo(HaveOccurred()) + + Expect(Get(yml, "array.2")).To(Equal("bumblebee")) + Expect(Get(yml, "array.3")).To(Equal("optimusPrime")) + Expect(Get(yml, "mapArray.0.foo")).To(Equal("wolverine")) + Expect(Get(yml, "mapArray.foo:var.boo")).To(Equal("baymax")) + + err = Set(yml, "array.:optimusPrime", "pikachu") + Expect(Get(yml, "array.:pikachu")).To(Equal("pikachu")) + err = Set(yml, "mapArray.foo:wolverine.arr.0", "new") + Expect(Get(yml, "mapArray.foo:wolverine.arr.0")).To(Equal("new")) + }) +}) diff --git a/transfer.go b/transfer.go new file mode 100644 index 0000000..17103b0 --- /dev/null +++ b/transfer.go @@ -0,0 +1,31 @@ +package goml + +import "github.com/smallfish/simpleyaml" + +func TransferToFile(from string, fromPath string, to string, toPath string) error { + fromYaml, err := ReadYamlFromFile(from) + if err != nil { + return err + } + + toYaml, err := ReadYamlFromFile(to) + if err != nil { + return err + } + + err = Transfer(fromYaml, fromPath, toYaml, toPath) + if err != nil { + return err + } + + return WriteYaml(toYaml, to) +} + +func Transfer(fromYaml *simpleyaml.Yaml, fromPath string, toYaml *simpleyaml.Yaml, toPath string) error { + value, err := Get(fromYaml, fromPath) + if err != nil { + return err + } + + return Set(toYaml, toPath, value) +} diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..42c0afa --- /dev/null +++ b/utils.go @@ -0,0 +1,126 @@ +package goml + +import ( + "errors" + "fmt" + "io/ioutil" + "strconv" + "strings" + + "github.com/smallfish/simpleyaml" + "gopkg.in/yaml.v2" +) + +func ExtractType(value *simpleyaml.Yaml) (interface{}, error) { + if v, err := value.String(); err == nil { + return v, nil + } + if v, err := value.Bool(); err == nil { + return strconv.FormatBool(v), nil + } + if v, err := value.Int(); err == nil { + return strconv.Itoa(v), nil + } + if v, err := value.Float(); err == nil { + return fmt.Sprint(v), nil + } + if v, err := value.Array(); err == nil { + strSl := []string{} + for _, val := range v { + tmp := extractArrayType(val) + strSl = append(strSl, tmp) + } + str := strings.Join(strSl, ",") + return str, nil + } + if v, err := value.Map(); err == nil { + return v, nil + } + return nil, errors.New("property not found") +} + +func extractArrayType(value interface{}) string { + switch t := value.(type) { + default: + fmt.Printf("unexpected type %T\n", t) + case string: + return value.(string) + case bool: + return strconv.FormatBool(value.(bool)) + case int: + return strconv.Itoa(value.(int)) + case float64: + return fmt.Sprint(value.(float64)) + } + return "" +} + +func convertValueType(val interface{}) interface{} { + switch val.(type) { + default: + return val + case string: + str := val.(string) + if value, err := strconv.Atoi(str); err == nil { + return value + } + if value, err := strconv.ParseBool(str); err == nil { + return value + } + } + return val +} + +func WriteYaml(yml *simpleyaml.Yaml, file string) error { + goml, err := yml.Map() + if err != nil { + return err + } + + gomlSave, err := yaml.Marshal(goml) + if err != nil { + return err + } + + return ioutil.WriteFile(file, gomlSave, 0644) +} + +func ReadYaml(yaml []byte) (*simpleyaml.Yaml, error) { + yml, err := simpleyaml.NewYaml(yaml) + if err != nil { + return nil, err + } + return yml, nil +} + +func ReadYamlFromFile(filename string) (*simpleyaml.Yaml, error) { + file, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + return simpleyaml.NewYaml(file) +} + +func returnIndexForProp(propName string, array []interface{}) (int, error) { + keyVal := strings.Split(propName, ":") + key, val := keyVal[0], keyVal[1] + + for i, _ := range array { + if key == "" { + + check := array[i] + if check == val { + return i, nil + } + + } else { + check := array[i].(map[interface{}]interface{}) + if check[key] == val { + return i, nil + } + } + } + + return 0, errors.New("property not found") +}