Can overwrite arrays when merging

This commit is contained in:
Mike Farah 2020-07-17 13:07:32 +10:00
parent ee07edbd88
commit 2fc39b3865
5 changed files with 83 additions and 7 deletions

View File

@ -27,6 +27,7 @@ var indent = 2
var overwriteFlag = false
var autoCreateFlag = true
var appendFlag = false
var overwriteArrays = false
var verbose = false
var version = false
var docIndex = "0"

View File

@ -34,6 +34,7 @@ If append flag is set then existing arrays will be merged with the arrays from e
cmdMerge.PersistentFlags().BoolVarP(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries")
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().BoolVarP(&overwriteArrays, "overwriteArrays", "", false, "overwrite arrays rather than update recursively")
return cmdMerge
}
@ -43,7 +44,7 @@ If append flag is set then existing arrays will be merged with the arrays from e
*/
func createReadFunctionForMerge() func(*yaml.Node) ([]*yqlib.NodeContext, error) {
return func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) {
return lib.GetForMerge(dataBucket, "**", !appendFlag)
return lib.GetForMerge(dataBucket, "**", !appendFlag, overwriteArrays)
}
}
@ -76,7 +77,7 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
Value: matchingNode.Node,
Overwrite: overwriteFlag,
// dont update the content for nodes midway, only leaf nodes
DontUpdateNodeContent: matchingNode.IsMiddleNode,
DontUpdateNodeContent: matchingNode.IsMiddleNode && (!overwriteArrays || matchingNode.Node.Kind != yaml.SequenceNode),
})
}
}

View File

@ -68,6 +68,33 @@ c:
test.AssertResult(t, expectedOutput, result.Output)
}
func TestMergeOverwriteDeepExampleCmd(t *testing.T) {
content := `c:
test: 1
thing: whatever
`
filename := test.WriteTempYamlFile(content)
defer test.RemoveTempYamlFile(filename)
mergeContent := `c:
test: 5
`
mergeFilename := test.WriteTempYamlFile(mergeContent)
defer test.RemoveTempYamlFile(mergeFilename)
cmd := getRootCommand()
result := test.RunCmd(cmd, fmt.Sprintf("merge --autocreate=false --overwrite %s %s", filename, mergeFilename))
if result.Error != nil {
t.Error(result.Error)
}
expectedOutput := `c:
test: 5
thing: whatever
`
test.AssertResult(t, expectedOutput, result.Output)
}
func TestMergeAppendCmd(t *testing.T) {
cmd := getRootCommand()
result := test.RunCmd(cmd, "merge --autocreate=false --append ../examples/data1.yaml ../examples/data2.yaml")
@ -166,7 +193,35 @@ c:
test.AssertResult(t, expectedOutput, result.Output)
}
func TestMergeArraysCmd(t *testing.T) {
func TestMergeOverwriteArraysTooCmd(t *testing.T) {
content := `a: simple # just the best
b: [1, 2]
c:
test: 1
`
filename := test.WriteTempYamlFile(content)
defer test.RemoveTempYamlFile(filename)
mergeContent := `a: things
b: [6]`
mergeFilename := test.WriteTempYamlFile(mergeContent)
defer test.RemoveTempYamlFile(mergeFilename)
cmd := getRootCommand()
result := test.RunCmd(cmd, fmt.Sprintf("merge --autocreate=false --overwriteArrays --overwrite %s %s", filename, mergeFilename))
if result.Error != nil {
t.Error(result.Error)
}
expectedOutput := `a: things
b: [6]
c:
test: 1
`
test.AssertResult(t, expectedOutput, result.Output)
}
func TestMergeRootArraysCmd(t *testing.T) {
cmd := getRootCommand()
result := test.RunCmd(cmd, "merge --append ../examples/sample_array.yaml ../examples/sample_array_2.yaml")
if result.Error != nil {
@ -181,6 +236,18 @@ func TestMergeArraysCmd(t *testing.T) {
test.AssertResult(t, expectedOutput, result.Output)
}
func TestMergeOverwriteArraysCmd(t *testing.T) {
cmd := getRootCommand()
result := test.RunCmd(cmd, "merge --overwriteArrays ../examples/sample_array.yaml ../examples/sample_array_2.yaml")
if result.Error != nil {
t.Error(result.Error)
}
expectedOutput := `- 4
- 5
`
test.AssertResult(t, expectedOutput, result.Output)
}
func TestMergeCmd_Multi(t *testing.T) {
cmd := getRootCommand()
result := test.RunCmd(cmd, "merge -d1 ../examples/multiple_docs_small.yaml ../examples/data1.yaml")

View File

@ -136,7 +136,7 @@ func guessKind(head interface{}, tail []interface{}, guess yaml.Kind) yaml.Kind
type YqLib interface {
Get(rootNode *yaml.Node, path string) ([]*NodeContext, error)
GetForMerge(rootNode *yaml.Node, path string, deeplyTraverseArrays bool) ([]*NodeContext, error)
GetForMerge(rootNode *yaml.Node, path string, deeplyTraverseArrays bool, overwriteArray bool) ([]*NodeContext, error)
Update(rootNode *yaml.Node, updateCommand UpdateCommand, autoCreate bool) error
New(path string) yaml.Node
@ -162,9 +162,9 @@ func (l *lib) Get(rootNode *yaml.Node, path string) ([]*NodeContext, error) {
return navigationStrategy.GetVisitedNodes(), error
}
func (l *lib) GetForMerge(rootNode *yaml.Node, path string, deeplyTraverseArrays bool) ([]*NodeContext, error) {
func (l *lib) GetForMerge(rootNode *yaml.Node, path string, deeplyTraverseArrays bool, overwriteArray bool) ([]*NodeContext, error) {
var paths = l.parser.ParsePath(path)
navigationStrategy := ReadForMergeNavigationStrategy(deeplyTraverseArrays)
navigationStrategy := ReadForMergeNavigationStrategy(deeplyTraverseArrays, overwriteArray)
navigator := NewDataNavigator(navigationStrategy)
error := navigator.Traverse(rootNode, paths)
return navigationStrategy.GetVisitedNodes(), error

View File

@ -1,6 +1,8 @@
package yqlib
func ReadForMergeNavigationStrategy(deeplyTraverseArrays bool) NavigationStrategy {
import "gopkg.in/yaml.v3"
func ReadForMergeNavigationStrategy(deeplyTraverseArrays bool, overwriteArray bool) NavigationStrategy {
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
pathParser: NewPathParser(),
@ -14,6 +16,11 @@ func ReadForMergeNavigationStrategy(deeplyTraverseArrays bool) NavigationStrateg
return nil
},
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
if nodeContext.Node.Kind == yaml.SequenceNode && overwriteArray {
nodeContext.IsMiddleNode = false
return false
}
var isInArray = false
if len(nodeContext.PathStack) > 0 {
var lastElement = nodeContext.PathStack[len(nodeContext.PathStack)-1]