mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Added comments merge strategy
This commit is contained in:
parent
b380ea2892
commit
fea8510061
@ -27,6 +27,7 @@ var indent = 2
|
|||||||
var overwriteFlag = false
|
var overwriteFlag = false
|
||||||
var autoCreateFlag = true
|
var autoCreateFlag = true
|
||||||
var arrayMergeStrategyFlag = "update"
|
var arrayMergeStrategyFlag = "update"
|
||||||
|
var commentsMergeStrategyFlag = "setWhenBlank"
|
||||||
var verbose = false
|
var verbose = false
|
||||||
var version = false
|
var version = false
|
||||||
var docIndex = "0"
|
var docIndex = "0"
|
||||||
|
34
cmd/merge.go
34
cmd/merge.go
@ -32,7 +32,15 @@ If append flag is set then existing arrays will be merged with the arrays from e
|
|||||||
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(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries")
|
cmdMerge.PersistentFlags().BoolVarP(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries")
|
||||||
cmdMerge.PersistentFlags().StringVarP(&arrayMergeStrategyFlag, "arrays", "a", "update", "array merge strategy (update/append/overwrite)")
|
cmdMerge.PersistentFlags().StringVarP(&arrayMergeStrategyFlag, "arrays", "a", "update", `array merge strategy (update/append/overwrite)
|
||||||
|
update: recursively update arrays by their index
|
||||||
|
append: concatenate arrays together
|
||||||
|
overwrite: replace arrays`)
|
||||||
|
cmdMerge.PersistentFlags().StringVarP(&commentsMergeStrategyFlag, "comments", "", "setWhenBlank", `comments merge strategy (setWhenBlank/ignore/append/overwrite)
|
||||||
|
setWhenBlank: set comment if the original document has no comment at that node
|
||||||
|
ignore: leave comments as-is in the original
|
||||||
|
append: append comments together
|
||||||
|
overwrite: overwrite comments completely`)
|
||||||
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
|
||||||
}
|
}
|
||||||
@ -66,6 +74,21 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
|
|||||||
return errors.New("Array merge strategy must be one of: update/append/overwrite")
|
return errors.New("Array merge strategy must be one of: update/append/overwrite")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commentsMergeStrategy yqlib.CommentsMergeStrategy
|
||||||
|
|
||||||
|
switch commentsMergeStrategyFlag {
|
||||||
|
case "setWhenBlank":
|
||||||
|
commentsMergeStrategy = yqlib.SetWhenBlankCommentsMergeStrategy
|
||||||
|
case "ignore":
|
||||||
|
commentsMergeStrategy = yqlib.IgnoreCommentsMergeStrategy
|
||||||
|
case "append":
|
||||||
|
commentsMergeStrategy = yqlib.AppendCommentsMergeStrategy
|
||||||
|
case "overwrite":
|
||||||
|
commentsMergeStrategy = yqlib.OverwriteCommentsMergeStrategy
|
||||||
|
default:
|
||||||
|
return errors.New("Comments merge strategy must be one of: setWhenBlank/ignore/append/overwrite")
|
||||||
|
}
|
||||||
|
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
// first generate update commands from the file
|
// first generate update commands from the file
|
||||||
var filesToMerge = args[1:]
|
var filesToMerge = args[1:]
|
||||||
@ -83,10 +106,11 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
|
|||||||
for _, matchingNode := range matchingNodes {
|
for _, matchingNode := range matchingNodes {
|
||||||
mergePath := lib.MergePathStackToString(matchingNode.PathStack, arrayMergeStrategy)
|
mergePath := lib.MergePathStackToString(matchingNode.PathStack, arrayMergeStrategy)
|
||||||
updateCommands = append(updateCommands, yqlib.UpdateCommand{
|
updateCommands = append(updateCommands, yqlib.UpdateCommand{
|
||||||
Command: "merge",
|
Command: "merge",
|
||||||
Path: mergePath,
|
Path: mergePath,
|
||||||
Value: matchingNode.Node,
|
Value: matchingNode.Node,
|
||||||
Overwrite: overwriteFlag,
|
Overwrite: overwriteFlag,
|
||||||
|
CommentsMergeStrategy: commentsMergeStrategy,
|
||||||
// dont update the content for nodes midway, only leaf nodes
|
// dont update the content for nodes midway, only leaf nodes
|
||||||
DontUpdateNodeContent: matchingNode.IsMiddleNode && (arrayMergeStrategy != yqlib.OverwriteArrayMergeStrategy || matchingNode.Node.Kind != yaml.SequenceNode),
|
DontUpdateNodeContent: matchingNode.IsMiddleNode && (arrayMergeStrategy != yqlib.OverwriteArrayMergeStrategy || matchingNode.Node.Kind != yaml.SequenceNode),
|
||||||
})
|
})
|
||||||
|
@ -60,7 +60,7 @@ func TestMergeOverwriteCmd(t *testing.T) {
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `a: other # better than the original
|
expectedOutput := `a: other # just the best
|
||||||
b: [3, 4]
|
b: [3, 4]
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
@ -185,7 +185,7 @@ func TestMergeOverwriteAndAppendCmd(t *testing.T) {
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `a: other # better than the original
|
expectedOutput := `a: other # just the best
|
||||||
b: [1, 2, 3, 4]
|
b: [1, 2, 3, 4]
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
@ -193,6 +193,97 @@ c:
|
|||||||
test.AssertResult(t, expectedOutput, result.Output)
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commentContentA = `
|
||||||
|
a: valueA1 # commentA1
|
||||||
|
b: valueB1
|
||||||
|
`
|
||||||
|
|
||||||
|
var commentContentB = `
|
||||||
|
a: valueA2 # commentA2
|
||||||
|
b: valueB2 # commentB2
|
||||||
|
c: valueC2 # commentC2
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestMergeCommentsSetWhenBlankCmd(t *testing.T) {
|
||||||
|
filename := test.WriteTempYamlFile(commentContentA)
|
||||||
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
|
mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||||
|
defer test.RemoveTempYamlFile(mergeFilename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=setWhenBlank %s %s", filename, mergeFilename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOutput := `a: valueA1 # commentA1
|
||||||
|
b: valueB1 # commentB2
|
||||||
|
c: valueC2 # commentC2
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeCommentsIgnoreCmd(t *testing.T) {
|
||||||
|
filename := test.WriteTempYamlFile(commentContentA)
|
||||||
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
|
mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||||
|
defer test.RemoveTempYamlFile(mergeFilename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=ignore %s %s", filename, mergeFilename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOutput := `a: valueA1 # commentA1
|
||||||
|
b: valueB1
|
||||||
|
c: valueC2
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeCommentsAppendCmd(t *testing.T) {
|
||||||
|
filename := test.WriteTempYamlFile(commentContentA)
|
||||||
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
|
mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||||
|
defer test.RemoveTempYamlFile(mergeFilename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=append %s %s", filename, mergeFilename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOutput := `a: valueA1 # commentA1 # commentA2
|
||||||
|
b: valueB1 # commentB2
|
||||||
|
c: valueC2 # commentC2
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeCommentsOverwriteCmd(t *testing.T) {
|
||||||
|
filename := test.WriteTempYamlFile(commentContentA)
|
||||||
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
|
mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||||
|
defer test.RemoveTempYamlFile(mergeFilename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=overwrite %s %s", filename, mergeFilename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOutput := `a: valueA1 # commentA2
|
||||||
|
b: valueB1 # commentB2
|
||||||
|
c: valueC2 # commentC2
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeOverwriteArraysTooCmd(t *testing.T) {
|
func TestMergeOverwriteArraysTooCmd(t *testing.T) {
|
||||||
content := `a: simple # just the best
|
content := `a: simple # just the best
|
||||||
b: [1, 2]
|
b: [1, 2]
|
||||||
@ -213,7 +304,7 @@ b: [6]`
|
|||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedOutput := `a: things
|
expectedOutput := `a: things # just the best
|
||||||
b: [6]
|
b: [6]
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
|
@ -19,6 +19,7 @@ type UpdateCommand struct {
|
|||||||
Overwrite bool
|
Overwrite bool
|
||||||
DontUpdateNodeValue bool
|
DontUpdateNodeValue bool
|
||||||
DontUpdateNodeContent bool
|
DontUpdateNodeContent bool
|
||||||
|
CommentsMergeStrategy CommentsMergeStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
func KindString(kind yaml.Kind) string {
|
func KindString(kind yaml.Kind) string {
|
||||||
|
@ -10,6 +10,15 @@ const (
|
|||||||
AppendArrayMergeStrategy
|
AppendArrayMergeStrategy
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CommentsMergeStrategy uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
SetWhenBlankCommentsMergeStrategy CommentsMergeStrategy = 1 << iota
|
||||||
|
IgnoreCommentsMergeStrategy
|
||||||
|
OverwriteCommentsMergeStrategy
|
||||||
|
AppendCommentsMergeStrategy
|
||||||
|
)
|
||||||
|
|
||||||
func MergeNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy {
|
func MergeNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy {
|
||||||
return &NavigationStrategyImpl{
|
return &NavigationStrategyImpl{
|
||||||
visitedNodes: []*NodeContext{},
|
visitedNodes: []*NodeContext{},
|
||||||
@ -31,40 +40,63 @@ func MergeNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) Navig
|
|||||||
node = node.Content[0]
|
node = node.Content[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("going to update")
|
||||||
|
DebugNode(node)
|
||||||
|
log.Debug("with")
|
||||||
|
DebugNode(changesToApply)
|
||||||
|
|
||||||
if updateCommand.Overwrite || node.Value == "" {
|
if updateCommand.Overwrite || node.Value == "" {
|
||||||
log.Debug("going to update")
|
|
||||||
DebugNode(node)
|
|
||||||
log.Debug("with")
|
|
||||||
DebugNode(changesToApply)
|
|
||||||
node.Value = changesToApply.Value
|
node.Value = changesToApply.Value
|
||||||
node.Tag = changesToApply.Tag
|
node.Tag = changesToApply.Tag
|
||||||
node.Kind = changesToApply.Kind
|
node.Kind = changesToApply.Kind
|
||||||
node.Style = changesToApply.Style
|
node.Style = changesToApply.Style
|
||||||
node.Anchor = changesToApply.Anchor
|
node.Anchor = changesToApply.Anchor
|
||||||
node.Alias = changesToApply.Alias
|
node.Alias = changesToApply.Alias
|
||||||
node.HeadComment = changesToApply.HeadComment
|
|
||||||
node.LineComment = changesToApply.LineComment
|
|
||||||
node.FootComment = changesToApply.FootComment
|
|
||||||
|
|
||||||
if !updateCommand.DontUpdateNodeContent {
|
if !updateCommand.DontUpdateNodeContent {
|
||||||
node.Content = changesToApply.Content
|
node.Content = changesToApply.Content
|
||||||
}
|
}
|
||||||
|
|
||||||
// // TODO: mergeComments flag
|
|
||||||
// if node.HeadComment != "" && changesToApply.HeadComment != "" {
|
|
||||||
// node.HeadComment = node.HeadComment + "\n" + changesToApply.HeadComment
|
|
||||||
// log.Debug("merged comments with a space, %v", node.HeadComment)
|
|
||||||
// } else {
|
|
||||||
// node.HeadComment = node.HeadComment + changesToApply.HeadComment
|
|
||||||
// if node.HeadComment != "" {
|
|
||||||
// log.Debug("merged comments with no space, %v", node.HeadComment)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// node.LineComment = node.LineComment + changesToApply.LineComment
|
|
||||||
// node.FootComment = node.FootComment + changesToApply.FootComment
|
|
||||||
} else {
|
} else {
|
||||||
log.Debug("skipping update as node already has value %v and overwriteFlag is ", node.Value, updateCommand.Overwrite)
|
log.Debug("skipping update as node already has value %v and overwriteFlag is ", node.Value, updateCommand.Overwrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch updateCommand.CommentsMergeStrategy {
|
||||||
|
case OverwriteCommentsMergeStrategy:
|
||||||
|
node.HeadComment = changesToApply.HeadComment
|
||||||
|
node.LineComment = changesToApply.LineComment
|
||||||
|
node.FootComment = changesToApply.FootComment
|
||||||
|
case SetWhenBlankCommentsMergeStrategy:
|
||||||
|
if node.HeadComment == "" {
|
||||||
|
node.HeadComment = changesToApply.HeadComment
|
||||||
|
}
|
||||||
|
if node.LineComment == "" {
|
||||||
|
node.LineComment = changesToApply.LineComment
|
||||||
|
}
|
||||||
|
if node.FootComment == "" {
|
||||||
|
node.FootComment = changesToApply.FootComment
|
||||||
|
}
|
||||||
|
case AppendCommentsMergeStrategy:
|
||||||
|
if node.HeadComment == "" {
|
||||||
|
node.HeadComment = changesToApply.HeadComment
|
||||||
|
} else {
|
||||||
|
node.HeadComment = node.HeadComment + "\n" + changesToApply.HeadComment
|
||||||
|
}
|
||||||
|
if node.LineComment == "" {
|
||||||
|
node.LineComment = changesToApply.LineComment
|
||||||
|
} else {
|
||||||
|
node.LineComment = node.LineComment + " " + changesToApply.LineComment
|
||||||
|
}
|
||||||
|
if node.FootComment == "" {
|
||||||
|
node.FootComment = changesToApply.FootComment
|
||||||
|
} else {
|
||||||
|
node.FootComment = node.FootComment + "\n" + changesToApply.FootComment
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("result")
|
||||||
|
DebugNode(node)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user