mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 13:48:06 +00:00
Merge can allow empty merges!
This commit is contained in:
parent
e3f4eedd51
commit
d8c29b26c1
119
commands_test.go
119
commands_test.go
@ -243,7 +243,7 @@ func TestReadBadDocumentIndexCmd(t *testing.T) {
|
|||||||
if result.Error == nil {
|
if result.Error == nil {
|
||||||
t.Error("Expected command to fail due to invalid path")
|
t.Error("Expected command to fail due to invalid path")
|
||||||
}
|
}
|
||||||
expectedOutput := `asked to process document index 1 but there are only 1 document(s)`
|
expectedOutput := `Could not process document index 1 as there are only 1 document(s)`
|
||||||
test.AssertResult(t, expectedOutput, result.Error.Error())
|
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,18 +829,6 @@ func TestNewCmd_Error(t *testing.T) {
|
|||||||
test.AssertResult(t, expectedOutput, result.Error.Error())
|
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewCmd_Verbose(t *testing.T) {
|
|
||||||
cmd := getRootCommand()
|
|
||||||
result := test.RunCmd(cmd, "-v new b.c 3")
|
|
||||||
if result.Error != nil {
|
|
||||||
t.Error(result.Error)
|
|
||||||
}
|
|
||||||
expectedOutput := `b:
|
|
||||||
c: 3
|
|
||||||
`
|
|
||||||
test.AssertResult(t, expectedOutput, result.Output)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteCmd(t *testing.T) {
|
func TestWriteCmd(t *testing.T) {
|
||||||
content := `b:
|
content := `b:
|
||||||
c: 3
|
c: 3
|
||||||
@ -998,24 +986,6 @@ func TestWriteCmd_ErrorUnreadableFile(t *testing.T) {
|
|||||||
test.AssertResult(t, expectedOutput, result.Error.Error())
|
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriteCmd_Verbose(t *testing.T) {
|
|
||||||
content := `b:
|
|
||||||
c: 3
|
|
||||||
`
|
|
||||||
filename := test.WriteTempYamlFile(content)
|
|
||||||
defer test.RemoveTempYamlFile(filename)
|
|
||||||
|
|
||||||
cmd := getRootCommand()
|
|
||||||
result := test.RunCmd(cmd, fmt.Sprintf("-v write %s b.c 7", filename))
|
|
||||||
if result.Error != nil {
|
|
||||||
t.Error(result.Error)
|
|
||||||
}
|
|
||||||
expectedOutput := `b:
|
|
||||||
c: 7
|
|
||||||
`
|
|
||||||
test.AssertResult(t, expectedOutput, result.Output)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteCmd_Inplace(t *testing.T) {
|
func TestWriteCmd_Inplace(t *testing.T) {
|
||||||
content := `b:
|
content := `b:
|
||||||
c: 3
|
c: 3
|
||||||
@ -1193,7 +1163,7 @@ b:
|
|||||||
defer test.RemoveTempYamlFile(filename)
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := test.RunCmd(cmd, fmt.Sprintf("delete -v %s b.hi[*].thing", filename))
|
result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.hi[*].thing", filename))
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
@ -1224,7 +1194,7 @@ b:
|
|||||||
defer test.RemoveTempYamlFile(filename)
|
defer test.RemoveTempYamlFile(filename)
|
||||||
|
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := test.RunCmd(cmd, fmt.Sprintf("delete -v %s b.there*.c", filename))
|
result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.there*.c", filename))
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
@ -1315,7 +1285,7 @@ func TestMergeCmd(t *testing.T) {
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `a: simple
|
expectedOutput := `a: simple # just the best
|
||||||
b: [1, 2]
|
b: [1, 2]
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
@ -1332,7 +1302,7 @@ func TestMergeNoAutoCreateCmd(t *testing.T) {
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `a: simple
|
expectedOutput := `a: simple # just the best
|
||||||
b: [1, 2]
|
b: [1, 2]
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
@ -1401,7 +1371,7 @@ c:
|
|||||||
test.AssertResult(t, expectedOutput, result.Output)
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func xTestMergeYamlMultiAllCmd(t *testing.T) {
|
func TestMergeYamlMultiAllCmd(t *testing.T) {
|
||||||
content := `b:
|
content := `b:
|
||||||
c: 3
|
c: 3
|
||||||
apples: green
|
apples: green
|
||||||
@ -1420,17 +1390,18 @@ something: good`
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `apples: green
|
expectedOutput := `b:
|
||||||
b:
|
|
||||||
c: 3
|
c: 3
|
||||||
|
apples: green
|
||||||
something: good
|
something: good
|
||||||
---
|
---
|
||||||
|
something: else
|
||||||
apples: red
|
apples: red
|
||||||
something: else`
|
`
|
||||||
test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func xTestMergeYamlMultiAllOverwriteCmd(t *testing.T) {
|
func TestMergeYamlMultiAllOverwriteCmd(t *testing.T) {
|
||||||
content := `b:
|
content := `b:
|
||||||
c: 3
|
c: 3
|
||||||
apples: green
|
apples: green
|
||||||
@ -1449,17 +1420,18 @@ something: good`
|
|||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `apples: red
|
expectedOutput := `b:
|
||||||
b:
|
|
||||||
c: 3
|
c: 3
|
||||||
|
apples: red
|
||||||
something: good
|
something: good
|
||||||
---
|
---
|
||||||
|
something: good
|
||||||
apples: red
|
apples: red
|
||||||
something: good`
|
`
|
||||||
test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func xTestMergeCmd_Error(t *testing.T) {
|
func TestMergeCmd_Error(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := test.RunCmd(cmd, "merge examples/data1.yaml")
|
result := test.RunCmd(cmd, "merge examples/data1.yaml")
|
||||||
if result.Error == nil {
|
if result.Error == nil {
|
||||||
@ -1469,7 +1441,7 @@ func xTestMergeCmd_Error(t *testing.T) {
|
|||||||
test.AssertResult(t, expectedOutput, result.Error.Error())
|
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func xTestMergeCmd_ErrorUnreadableFile(t *testing.T) {
|
func TestMergeCmd_ErrorUnreadableFile(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := test.RunCmd(cmd, "merge examples/data1.yaml fake-unknown")
|
result := test.RunCmd(cmd, "merge examples/data1.yaml fake-unknown")
|
||||||
if result.Error == nil {
|
if result.Error == nil {
|
||||||
@ -1477,30 +1449,14 @@ func xTestMergeCmd_ErrorUnreadableFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
var expectedOutput string
|
var expectedOutput string
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
expectedOutput = `Error updating document at index 0: open fake-unknown: The system cannot find the file specified.`
|
expectedOutput = `open fake-unknown: The system cannot find the file specified.`
|
||||||
} else {
|
} else {
|
||||||
expectedOutput = `Error updating document at index 0: open fake-unknown: no such file or directory`
|
expectedOutput = `open fake-unknown: no such file or directory`
|
||||||
}
|
}
|
||||||
test.AssertResult(t, expectedOutput, result.Error.Error())
|
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func xTestMergeCmd_Verbose(t *testing.T) {
|
func TestMergeCmd_Inplace(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
|
||||||
result := test.RunCmd(cmd, "-v merge examples/data1.yaml examples/data2.yaml")
|
|
||||||
if result.Error != nil {
|
|
||||||
t.Error(result.Error)
|
|
||||||
}
|
|
||||||
expectedOutput := `a: simple
|
|
||||||
b:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
c:
|
|
||||||
test: 1
|
|
||||||
`
|
|
||||||
test.AssertResult(t, expectedOutput, result.Output)
|
|
||||||
}
|
|
||||||
|
|
||||||
func xTestMergeCmd_Inplace(t *testing.T) {
|
|
||||||
filename := test.WriteTempYamlFile(test.ReadTempYamlFile("examples/data1.yaml"))
|
filename := test.WriteTempYamlFile(test.ReadTempYamlFile("examples/data1.yaml"))
|
||||||
err := os.Chmod(filename, os.FileMode(int(0666)))
|
err := os.Chmod(filename, os.FileMode(int(0666)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1515,26 +1471,35 @@ func xTestMergeCmd_Inplace(t *testing.T) {
|
|||||||
}
|
}
|
||||||
info, _ := os.Stat(filename)
|
info, _ := os.Stat(filename)
|
||||||
gotOutput := test.ReadTempYamlFile(filename)
|
gotOutput := test.ReadTempYamlFile(filename)
|
||||||
expectedOutput := `a: simple
|
expectedOutput := `a: simple # just the best
|
||||||
b:
|
b: [1, 2]
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
c:
|
c:
|
||||||
test: 1`
|
test: 1
|
||||||
test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n "))
|
toast: leave
|
||||||
|
tell: 1
|
||||||
|
taco: cool
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, gotOutput)
|
||||||
test.AssertResult(t, os.FileMode(int(0666)), info.Mode())
|
test.AssertResult(t, os.FileMode(int(0666)), info.Mode())
|
||||||
}
|
}
|
||||||
|
|
||||||
func xTestMergeAllowEmptyCmd(t *testing.T) {
|
func TestMergeAllowEmptyCmd(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := test.RunCmd(cmd, "merge --allow-empty examples/data1.yaml examples/empty.yaml")
|
result := test.RunCmd(cmd, "merge --allow-empty examples/data1.yaml examples/empty.yaml")
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
expectedOutput := `a: simple
|
expectedOutput := `a: simple # just the best
|
||||||
b:
|
b: [1, 2]
|
||||||
- 1
|
c:
|
||||||
- 2
|
test: 1
|
||||||
`
|
`
|
||||||
test.AssertResult(t, expectedOutput, result.Output)
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergeDontAllowEmptyCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, "merge examples/data1.yaml examples/empty.yaml")
|
||||||
|
expectedOutput := `Could not process document index 0 as there are only 0 document(s)`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||||
|
}
|
||||||
|
52
yq.go
52
yq.go
@ -7,6 +7,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/mikefarah/yq/v3/pkg/yqlib"
|
"github.com/mikefarah/yq/v3/pkg/yqlib"
|
||||||
|
|
||||||
@ -239,7 +240,7 @@ Note that if you set both flags only overwrite will take effect.
|
|||||||
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().BoolVarP(&appendFlag, "append", "a", false, "update the yaml file by appending array values")
|
cmdMerge.PersistentFlags().BoolVarP(&appendFlag, "append", "a", false, "update the yaml file by appending array values")
|
||||||
// cmdMerge.PersistentFlags().BoolVarP(&allowEmptyFlag, "allow-empty", "e", false, "allow empty yaml files")
|
cmdMerge.PersistentFlags().BoolVarP(&allowEmptyFlag, "allow-empty", "e", false, "allow empty yaml files")
|
||||||
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
|
||||||
}
|
}
|
||||||
@ -293,7 +294,7 @@ func readYamlFile(filename string, path string, updateAll bool, docIndexInt int)
|
|||||||
func handleEOF(updateAll bool, docIndexInt int, currentIndex int) error {
|
func handleEOF(updateAll bool, docIndexInt int, currentIndex int) error {
|
||||||
log.Debugf("done %v / %v", currentIndex, docIndexInt)
|
log.Debugf("done %v / %v", currentIndex, docIndexInt)
|
||||||
if !updateAll && currentIndex <= docIndexInt {
|
if !updateAll && currentIndex <= docIndexInt {
|
||||||
return fmt.Errorf("asked to process document index %v but there are only %v document(s)", docIndex, currentIndex)
|
return fmt.Errorf("Could not process document index %v as there are only %v document(s)", docIndex, currentIndex)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -425,13 +426,16 @@ func writeProperty(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mergeProperties(cmd *cobra.Command, args []string) error {
|
func mergeProperties(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) < 2 {
|
||||||
|
return errors.New("Must provide at least 2 yaml files")
|
||||||
|
}
|
||||||
// first generate update commands from the file
|
// first generate update commands from the file
|
||||||
var filesToMerge = args[1:]
|
var filesToMerge = args[1:]
|
||||||
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
|
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
|
||||||
|
|
||||||
for _, fileToMerge := range filesToMerge {
|
for _, fileToMerge := range filesToMerge {
|
||||||
matchingNodes, errorProcessingFile := readYamlFile(fileToMerge, "**", false, 0)
|
matchingNodes, errorProcessingFile := readYamlFile(fileToMerge, "**", false, 0)
|
||||||
if errorProcessingFile != nil {
|
if errorProcessingFile != nil && (allowEmptyFlag == false || !strings.HasPrefix(errorProcessingFile.Error(), "Could not process document index")) {
|
||||||
return errorProcessingFile
|
return errorProcessingFile
|
||||||
}
|
}
|
||||||
for _, matchingNode := range matchingNodes {
|
for _, matchingNode := range matchingNodes {
|
||||||
@ -569,48 +573,6 @@ func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn)
|
|||||||
return readStream(inputFile, mapYamlDecoder(updateData, encoder))
|
return readStream(inputFile, mapYamlDecoder(updateData, encoder))
|
||||||
}
|
}
|
||||||
|
|
||||||
// func mergeProperties(cmd *cobra.Command, args []string) error {
|
|
||||||
// if len(args) < 2 {
|
|
||||||
// return errors.New("Must provide at least 2 yaml files")
|
|
||||||
// }
|
|
||||||
// var input = args[0]
|
|
||||||
// var filesToMerge = args[1:]
|
|
||||||
// var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
|
||||||
// if errorParsingDocIndex != nil {
|
|
||||||
// return errorParsingDocIndex
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
|
||||||
// if updateAll || currentIndex == docIndexInt {
|
|
||||||
// log.Debugf("Merging doc %v", currentIndex)
|
|
||||||
// var mergedData map[interface{}]interface{}
|
|
||||||
// // merge only works for maps, so put everything in a temporary
|
|
||||||
// // map
|
|
||||||
// var mapDataBucket = make(map[interface{}]interface{})
|
|
||||||
// mapDataBucket["root"] = dataBucket
|
|
||||||
// if err := lib.Merge(&mergedData, mapDataBucket, overwriteFlag, appendFlag); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// for _, f := range filesToMerge {
|
|
||||||
// var fileToMerge interface{}
|
|
||||||
// if err := readData(f, 0, &fileToMerge); err != nil {
|
|
||||||
// if allowEmptyFlag && err == io.EOF {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// mapDataBucket["root"] = fileToMerge
|
|
||||||
// if err := lib.Merge(&mergedData, mapDataBucket, overwriteFlag, appendFlag); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return mergedData["root"], nil
|
|
||||||
// }
|
|
||||||
// return dataBucket, nil
|
|
||||||
// }
|
|
||||||
// return readAndUpdate(cmd.OutOrStdout(), input, updateData)
|
|
||||||
// }
|
|
||||||
|
|
||||||
type updateCommandParsed struct {
|
type updateCommandParsed struct {
|
||||||
Command string
|
Command string
|
||||||
Path string
|
Path string
|
||||||
|
Loading…
Reference in New Issue
Block a user