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 expectedOutput := `a: other
b: b:
- 1 - 3
- 2 - 4
c: c:
test: 1 test: 1
` `
assertResult(t, expectedOutput, result.Output) 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) { func TestMergeCmd_Multi(t *testing.T) {
cmd := getRootCommand() cmd := getRootCommand()
result := runCmd(cmd, "merge -d1 examples/multiple_docs_small.yaml examples/data2.yaml") 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 a: other
another: another:
document: here document: here
b:
- 3
- 4
c: c:
test: 1 test: 1
--- ---

View File

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

View File

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

View File

@ -2,9 +2,11 @@ package main
import "gopkg.in/imdario/mergo.v0" 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 { 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) return mergo.Merge(dst, src)
} }

View File

@ -11,7 +11,7 @@ var (
GitDescribe string GitDescribe string
// Version is main version number that is being run at the moment. // 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) // 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 // 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 writeScript = ""
var outputToJSON = false var outputToJSON = false
var overwriteFlag = false var overwriteFlag = false
var appendFlag = false
var verbose = false var verbose = false
var version = false var version = false
var docIndex = "0" var docIndex = "0"
@ -183,23 +184,28 @@ func createMergeCmd() *cobra.Command {
var cmdMerge = &cobra.Command{ var cmdMerge = &cobra.Command{
Use: "merge [initial_yaml_file] [additional_yaml_file]...", Use: "merge [initial_yaml_file] [additional_yaml_file]...",
Aliases: []string{"m"}, 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: ` Example: `
yq merge things.yaml other.yaml yq merge things.yaml other.yaml
yq merge --inplace things.yaml other.yaml yq merge --inplace things.yaml other.yaml
yq m -i things.yaml other.yaml yq m -i things.yaml other.yaml
yq m --overwrite things.yaml other.yaml yq m --overwrite things.yaml other.yaml
yq m -i -x 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). 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. 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 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, RunE: mergeProperties,
} }
cmdMerge.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") 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(&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)") cmdMerge.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdMerge return cmdMerge
} }
@ -420,7 +426,11 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
if updateAll || currentIndex == docIndexInt { if updateAll || currentIndex == docIndexInt {
log.Debugf("Merging doc %v", currentIndex) log.Debugf("Merging doc %v", currentIndex)
var mergedData map[interface{}]interface{} 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 return nil, err
} }
for _, f := range filesToMerge { for _, f := range filesToMerge {
@ -428,11 +438,12 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
if err := readData(f, 0, &fileToMerge); err != nil { if err := readData(f, 0, &fileToMerge); err != nil {
return nil, err 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 nil, err
} }
} }
return mergedData, nil return mergedData["root"], nil
} }
return dataBucket, nil return dataBucket, nil
} }