Added merge with append

This commit is contained in:
Mike Farah 2018-07-07 15:26:56 +10:00
parent ce2ee42f71
commit 2c15048ddb
6 changed files with 59 additions and 9 deletions

View File

@ -612,14 +612,46 @@ func TestMergeOverwriteCmd(t *testing.T) {
}
expectedOutput := `a: other
b:
- 1
- 2
- 3
- 4
c:
test: 1
`
assertResult(t, expectedOutput, result.Output)
}
func TestMergeAppendCmd(t *testing.T) {
cmd := getRootCommand()
result := runCmd(cmd, "merge --append examples/data1.yaml examples/data2.yaml")
if result.Error != nil {
t.Error(result.Error)
}
expectedOutput := `a: simple
b:
- 1
- 2
- 3
- 4
c:
test: 1
`
assertResult(t, expectedOutput, result.Output)
}
func TestMergeArraysCmd(t *testing.T) {
cmd := getRootCommand()
result := runCmd(cmd, "merge --append examples/sample_array.yaml examples/sample_array_2.yaml")
if result.Error != nil {
t.Error(result.Error)
}
expectedOutput := `- 1
- 2
- 3
- 4
- 5
`
assertResult(t, expectedOutput, result.Output)
}
func TestMergeCmd_Multi(t *testing.T) {
cmd := getRootCommand()
result := runCmd(cmd, "merge -d1 examples/multiple_docs_small.yaml examples/data2.yaml")
@ -631,6 +663,9 @@ func TestMergeCmd_Multi(t *testing.T) {
a: other
another:
document: here
b:
- 3
- 4
c:
test: 1
---

View File

@ -1,3 +1,4 @@
a: other
b: [3, 4]
c:
test: 1

View File

@ -0,0 +1 @@
[4,5]

View File

@ -2,9 +2,11 @@ package main
import "gopkg.in/imdario/mergo.v0"
func merge(dst, src interface{}, overwrite bool) error {
func merge(dst interface{}, src interface{}, overwrite bool, append bool) error {
if overwrite {
return mergo.MergeWithOverwrite(dst, src)
return mergo.Merge(dst, src, mergo.WithOverride)
} else if append {
return mergo.Merge(dst, src, mergo.WithAppendSlice)
}
return mergo.Merge(dst, src)
}

View File

@ -11,7 +11,7 @@ var (
GitDescribe string
// Version is main version number that is being run at the moment.
Version = "2.0.1"
Version = "2.1.0"
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release

19
yq.go
View File

@ -22,6 +22,7 @@ var writeInplace = false
var writeScript = ""
var outputToJSON = false
var overwriteFlag = false
var appendFlag = false
var verbose = false
var version = false
var docIndex = "0"
@ -183,23 +184,28 @@ func createMergeCmd() *cobra.Command {
var cmdMerge = &cobra.Command{
Use: "merge [initial_yaml_file] [additional_yaml_file]...",
Aliases: []string{"m"},
Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] sample.yaml sample2.yaml",
Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--append/-a] sample.yaml sample2.yaml",
Example: `
yq merge things.yaml other.yaml
yq merge --inplace things.yaml other.yaml
yq m -i things.yaml other.yaml
yq m --overwrite things.yaml other.yaml
yq m -i -x things.yaml other.yaml
yq m -i -a things.yaml other.yaml
`,
Long: `Updates the yaml file by adding/updating the path(s) and value(s) from additional yaml file(s).
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
If overwrite flag is set then existing values will be overwritten using the values from each additional yaml file.
If append flag is set then existing arrays will be merged with the arrays from each additional yaml file.
Note that if you set both flags only overwrite will take effect.
`,
RunE: mergeProperties,
}
cmdMerge.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
cmdMerge.PersistentFlags().BoolVarP(&overwriteFlag, "overwrite", "x", false, "update the yaml file by overwriting existing values")
cmdMerge.PersistentFlags().BoolVarP(&appendFlag, "append", "a", false, "update the yaml file by appending array values")
cmdMerge.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdMerge
}
@ -420,7 +426,11 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
if updateAll || currentIndex == docIndexInt {
log.Debugf("Merging doc %v", currentIndex)
var mergedData map[interface{}]interface{}
if err := merge(&mergedData, dataBucket, overwriteFlag); err != nil {
// merge only works for maps, so put everything in a temporary
// map
var mapDataBucket = make(map[interface{}]interface{})
mapDataBucket["root"] = dataBucket
if err := merge(&mergedData, mapDataBucket, overwriteFlag, appendFlag); err != nil {
return nil, err
}
for _, f := range filesToMerge {
@ -428,11 +438,12 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
if err := readData(f, 0, &fileToMerge); err != nil {
return nil, err
}
if err := merge(&mergedData, fileToMerge, overwriteFlag); err != nil {
mapDataBucket["root"] = fileToMerge
if err := merge(&mergedData, mapDataBucket, overwriteFlag, appendFlag); err != nil {
return nil, err
}
}
return mergedData, nil
return mergedData["root"], nil
}
return dataBucket, nil
}