diff --git a/commands_test.go b/commands_test.go index 6e4c5271..c310d59e 100644 --- a/commands_test.go +++ b/commands_test.go @@ -243,7 +243,7 @@ func TestReadBadDocumentIndexCmd(t *testing.T) { if result.Error == nil { 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()) } @@ -829,18 +829,6 @@ func TestNewCmd_Error(t *testing.T) { 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) { content := `b: c: 3 @@ -998,24 +986,6 @@ func TestWriteCmd_ErrorUnreadableFile(t *testing.T) { 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) { content := `b: c: 3 @@ -1193,7 +1163,7 @@ b: defer test.RemoveTempYamlFile(filename) 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 { t.Error(result.Error) } @@ -1224,7 +1194,7 @@ b: defer test.RemoveTempYamlFile(filename) 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 { t.Error(result.Error) } @@ -1315,7 +1285,7 @@ func TestMergeCmd(t *testing.T) { if result.Error != nil { t.Error(result.Error) } - expectedOutput := `a: simple + expectedOutput := `a: simple # just the best b: [1, 2] c: test: 1 @@ -1332,7 +1302,7 @@ func TestMergeNoAutoCreateCmd(t *testing.T) { if result.Error != nil { t.Error(result.Error) } - expectedOutput := `a: simple + expectedOutput := `a: simple # just the best b: [1, 2] c: test: 1 @@ -1401,7 +1371,7 @@ c: test.AssertResult(t, expectedOutput, result.Output) } -func xTestMergeYamlMultiAllCmd(t *testing.T) { +func TestMergeYamlMultiAllCmd(t *testing.T) { content := `b: c: 3 apples: green @@ -1420,17 +1390,18 @@ something: good` if result.Error != nil { t.Error(result.Error) } - expectedOutput := `apples: green -b: + expectedOutput := `b: c: 3 +apples: green something: good --- +something: else 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: c: 3 apples: green @@ -1449,17 +1420,18 @@ something: good` if result.Error != nil { t.Error(result.Error) } - expectedOutput := `apples: red -b: + expectedOutput := `b: c: 3 +apples: red something: good --- +something: good 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() result := test.RunCmd(cmd, "merge examples/data1.yaml") if result.Error == nil { @@ -1469,7 +1441,7 @@ func xTestMergeCmd_Error(t *testing.T) { test.AssertResult(t, expectedOutput, result.Error.Error()) } -func xTestMergeCmd_ErrorUnreadableFile(t *testing.T) { +func TestMergeCmd_ErrorUnreadableFile(t *testing.T) { cmd := getRootCommand() result := test.RunCmd(cmd, "merge examples/data1.yaml fake-unknown") if result.Error == nil { @@ -1477,30 +1449,14 @@ func xTestMergeCmd_ErrorUnreadableFile(t *testing.T) { } var expectedOutput string 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 { - 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()) } -func xTestMergeCmd_Verbose(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) { +func TestMergeCmd_Inplace(t *testing.T) { filename := test.WriteTempYamlFile(test.ReadTempYamlFile("examples/data1.yaml")) err := os.Chmod(filename, os.FileMode(int(0666))) if err != nil { @@ -1515,26 +1471,35 @@ func xTestMergeCmd_Inplace(t *testing.T) { } info, _ := os.Stat(filename) gotOutput := test.ReadTempYamlFile(filename) - expectedOutput := `a: simple -b: -- 1 -- 2 + expectedOutput := `a: simple # just the best +b: [1, 2] c: - test: 1` - test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n ")) + test: 1 + toast: leave + tell: 1 + taco: cool +` + test.AssertResult(t, expectedOutput, gotOutput) test.AssertResult(t, os.FileMode(int(0666)), info.Mode()) } -func xTestMergeAllowEmptyCmd(t *testing.T) { +func TestMergeAllowEmptyCmd(t *testing.T) { cmd := getRootCommand() result := test.RunCmd(cmd, "merge --allow-empty examples/data1.yaml examples/empty.yaml") if result.Error != nil { t.Error(result.Error) } - expectedOutput := `a: simple -b: -- 1 -- 2 + expectedOutput := `a: simple # just the best +b: [1, 2] +c: + test: 1 ` 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()) +} diff --git a/yq.go b/yq.go index a1333791..adfd05f6 100644 --- a/yq.go +++ b/yq.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "strconv" + "strings" "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(&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(&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)") 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 { log.Debugf("done %v / %v", 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 } @@ -425,13 +426,16 @@ func writeProperty(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 var filesToMerge = args[1:] var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0) for _, fileToMerge := range filesToMerge { 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 } for _, matchingNode := range matchingNodes { @@ -569,48 +573,6 @@ func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn) 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 { Command string Path string