From d19e9f69172f0d3ac24fb024a349f00ade3ae312 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Tue, 13 Oct 2020 12:51:37 +1100 Subject: [PATCH] read command --- cmd/compare.go | 148 +- cmd/compare_test.go | 202 +-- cmd/constant.go | 3 +- cmd/delete.go | 72 +- cmd/delete_test.go | 428 +++--- cmd/merge.go | 222 +-- cmd/merge_test.go | 970 ++++++------- cmd/new.go | 92 +- cmd/new_test.go | 214 +-- cmd/prefix.go | 86 +- cmd/prefix_test.go | 340 ++--- cmd/read.go | 1 - cmd/read_test.go | 2 +- cmd/root.go | 12 +- cmd/utils.go | 296 ++-- cmd/write.go | 110 +- cmd/write_test.go | 1217 ++++++++--------- pkg/yqlib/constants.go | 5 + pkg/yqlib/data_navigator.go | 295 ---- pkg/yqlib/data_navigator_test.go | 1 - pkg/yqlib/delete_navigation_strategy.go | 73 - ...ilter_matching_node_navigation_strategy.go | 15 - pkg/yqlib/lib.go | 208 --- pkg/yqlib/lib_test.go | 176 --- pkg/yqlib/merge_navigation_strategy.go | 103 -- pkg/yqlib/navigation_strategy.go | 180 --- pkg/yqlib/path_parser.go | 153 --- pkg/yqlib/path_parser_test.go | 79 -- .../read_for_merge_navigation_strategy.go | 37 - pkg/yqlib/read_navigation_strategy.go | 11 - pkg/yqlib/treeops/candidate_node.go | 62 + pkg/yqlib/treeops/data_tree_navigator.go | 8 +- pkg/yqlib/treeops/delete_operator.go | 8 +- pkg/yqlib/treeops/lib.go | 26 +- pkg/yqlib/treeops/operators.go | 10 +- pkg/yqlib/treeops/path_tree.go | 4 + pkg/yqlib/update_navigation_strategy.go | 43 - 37 files changed, 2308 insertions(+), 3604 deletions(-) create mode 100644 pkg/yqlib/constants.go delete mode 100644 pkg/yqlib/data_navigator.go delete mode 100644 pkg/yqlib/data_navigator_test.go delete mode 100644 pkg/yqlib/delete_navigation_strategy.go delete mode 100644 pkg/yqlib/filter_matching_node_navigation_strategy.go delete mode 100644 pkg/yqlib/lib.go delete mode 100644 pkg/yqlib/lib_test.go delete mode 100644 pkg/yqlib/merge_navigation_strategy.go delete mode 100644 pkg/yqlib/navigation_strategy.go delete mode 100644 pkg/yqlib/path_parser.go delete mode 100644 pkg/yqlib/path_parser_test.go delete mode 100644 pkg/yqlib/read_for_merge_navigation_strategy.go delete mode 100644 pkg/yqlib/read_navigation_strategy.go create mode 100644 pkg/yqlib/treeops/candidate_node.go delete mode 100644 pkg/yqlib/update_navigation_strategy.go diff --git a/cmd/compare.go b/cmd/compare.go index f6b3188..50fa6a9 100644 --- a/cmd/compare.go +++ b/cmd/compare.go @@ -1,89 +1,89 @@ package cmd -import ( - "bufio" - "bytes" - "os" - "strings" +// import ( +// "bufio" +// "bytes" +// "os" +// "strings" - "github.com/kylelemons/godebug/diff" - "github.com/mikefarah/yq/v3/pkg/yqlib" - errors "github.com/pkg/errors" - "github.com/spf13/cobra" -) +// "github.com/kylelemons/godebug/diff" +// "github.com/mikefarah/yq/v3/pkg/yqlib" +// errors "github.com/pkg/errors" +// "github.com/spf13/cobra" +// ) -// turn off for unit tests :( -var forceOsExit = true +// // turn off for unit tests :( +// var forceOsExit = true -func createCompareCmd() *cobra.Command { - var cmdCompare = &cobra.Command{ - Use: "compare [yaml_file_a] [yaml_file_b]", - Aliases: []string{"x"}, - Short: "yq x [--prettyPrint/-P] dataA.yaml dataB.yaml 'b.e(name==fr*).value'", - Example: ` -yq x - data2.yml # reads from stdin -yq x -pp dataA.yaml dataB.yaml '**' # compare paths -yq x -d1 dataA.yaml dataB.yaml 'a.b.c' -`, - Long: "Deeply compares two yaml files, prints the difference. Use with prettyPrint flag to ignore formatting differences.", - RunE: compareDocuments, - } - cmdCompare.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") - cmdCompare.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)") - cmdCompare.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results") - cmdCompare.PersistentFlags().BoolVarP(&stripComments, "stripComments", "", false, "strip comments out before comparing") - cmdCompare.PersistentFlags().BoolVarP(&explodeAnchors, "explodeAnchors", "X", false, "explode anchors") - return cmdCompare -} +// func createCompareCmd() *cobra.Command { +// var cmdCompare = &cobra.Command{ +// Use: "compare [yaml_file_a] [yaml_file_b]", +// Aliases: []string{"x"}, +// Short: "yq x [--prettyPrint/-P] dataA.yaml dataB.yaml 'b.e(name==fr*).value'", +// Example: ` +// yq x - data2.yml # reads from stdin +// yq x -pp dataA.yaml dataB.yaml '**' # compare paths +// yq x -d1 dataA.yaml dataB.yaml 'a.b.c' +// `, +// Long: "Deeply compares two yaml files, prints the difference. Use with prettyPrint flag to ignore formatting differences.", +// RunE: compareDocuments, +// } +// cmdCompare.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") +// cmdCompare.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)") +// cmdCompare.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results") +// cmdCompare.PersistentFlags().BoolVarP(&stripComments, "stripComments", "", false, "strip comments out before comparing") +// cmdCompare.PersistentFlags().BoolVarP(&explodeAnchors, "explodeAnchors", "X", false, "explode anchors") +// return cmdCompare +// } -func compareDocuments(cmd *cobra.Command, args []string) error { - var path = "" +// func compareDocuments(cmd *cobra.Command, args []string) error { +// var path = "" - if len(args) < 2 { - return errors.New("Must provide at 2 yaml files") - } else if len(args) > 2 { - path = args[2] - } +// if len(args) < 2 { +// return errors.New("Must provide at 2 yaml files") +// } else if len(args) > 2 { +// path = args[2] +// } - var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() - if errorParsingDocIndex != nil { - return errorParsingDocIndex - } +// var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() +// if errorParsingDocIndex != nil { +// return errorParsingDocIndex +// } - var matchingNodesA []*yqlib.NodeContext - var matchingNodesB []*yqlib.NodeContext - var errorDoingThings error +// var matchingNodesA []*yqlib.NodeContext +// var matchingNodesB []*yqlib.NodeContext +// var errorDoingThings error - matchingNodesA, errorDoingThings = readYamlFile(args[0], path, updateAll, docIndexInt) +// matchingNodesA, errorDoingThings = readYamlFile(args[0], path, updateAll, docIndexInt) - if errorDoingThings != nil { - return errorDoingThings - } +// if errorDoingThings != nil { +// return errorDoingThings +// } - matchingNodesB, errorDoingThings = readYamlFile(args[1], path, updateAll, docIndexInt) - if errorDoingThings != nil { - return errorDoingThings - } +// matchingNodesB, errorDoingThings = readYamlFile(args[1], path, updateAll, docIndexInt) +// if errorDoingThings != nil { +// return errorDoingThings +// } - var dataBufferA bytes.Buffer - var dataBufferB bytes.Buffer - errorDoingThings = printResults(matchingNodesA, bufio.NewWriter(&dataBufferA)) - if errorDoingThings != nil { - return errorDoingThings - } - errorDoingThings = printResults(matchingNodesB, bufio.NewWriter(&dataBufferB)) - if errorDoingThings != nil { - return errorDoingThings - } +// var dataBufferA bytes.Buffer +// var dataBufferB bytes.Buffer +// errorDoingThings = printResults(matchingNodesA, bufio.NewWriter(&dataBufferA)) +// if errorDoingThings != nil { +// return errorDoingThings +// } +// errorDoingThings = printResults(matchingNodesB, bufio.NewWriter(&dataBufferB)) +// if errorDoingThings != nil { +// return errorDoingThings +// } - diffString := diff.Diff(strings.TrimSuffix(dataBufferA.String(), "\n"), strings.TrimSuffix(dataBufferB.String(), "\n")) +// diffString := diff.Diff(strings.TrimSuffix(dataBufferA.String(), "\n"), strings.TrimSuffix(dataBufferB.String(), "\n")) - if len(diffString) > 1 { - cmd.Print(diffString) - cmd.Print("\n") - if forceOsExit { - os.Exit(1) - } - } - return nil -} +// if len(diffString) > 1 { +// cmd.Print(diffString) +// cmd.Print("\n") +// if forceOsExit { +// os.Exit(1) +// } +// } +// return nil +// } diff --git a/cmd/compare_test.go b/cmd/compare_test.go index 903b152..670b0ba 100644 --- a/cmd/compare_test.go +++ b/cmd/compare_test.go @@ -1,115 +1,115 @@ package cmd -import ( - "testing" +// import ( +// "testing" - "github.com/mikefarah/yq/v3/test" -) +// "github.com/mikefarah/yq/v3/test" +// ) -func TestCompareSameCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare ../examples/data1.yaml ../examples/data1.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestCompareSameCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare ../examples/data1.yaml ../examples/data1.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestCompareIgnoreCommentsCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare --stripComments ../examples/data1.yaml ../examples/data1-no-comments.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestCompareIgnoreCommentsCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare --stripComments ../examples/data1.yaml ../examples/data1-no-comments.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestCompareDontIgnoreCommentsCmd(t *testing.T) { - forceOsExit = false - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare ../examples/data1.yaml ../examples/data1-no-comments.yaml") +// func TestCompareDontIgnoreCommentsCmd(t *testing.T) { +// forceOsExit = false +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare ../examples/data1.yaml ../examples/data1-no-comments.yaml") - expectedOutput := `-a: simple # just the best -+a: simple - b: [1, 2] - c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `-a: simple # just the best +// +a: simple +// b: [1, 2] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestCompareExplodeAnchorsCommentsCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare --explodeAnchors ../examples/simple-anchor.yaml ../examples/simple-anchor-exploded.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestCompareExplodeAnchorsCommentsCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare --explodeAnchors ../examples/simple-anchor.yaml ../examples/simple-anchor-exploded.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestCompareDontExplodeAnchorsCmd(t *testing.T) { - forceOsExit = false - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare ../examples/simple-anchor.yaml ../examples/simple-anchor-exploded.yaml") +// func TestCompareDontExplodeAnchorsCmd(t *testing.T) { +// forceOsExit = false +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare ../examples/simple-anchor.yaml ../examples/simple-anchor-exploded.yaml") - expectedOutput := `-foo: &foo -+foo: - a: 1 - foobar: -- !!merge <<: *foo -+ a: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `-foo: &foo +// +foo: +// a: 1 +// foobar: +// - !!merge <<: *foo +// + a: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestCompareDifferentCmd(t *testing.T) { - forceOsExit = false - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare ../examples/data1.yaml ../examples/data3.yaml") +// func TestCompareDifferentCmd(t *testing.T) { +// forceOsExit = false +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare ../examples/data1.yaml ../examples/data3.yaml") - expectedOutput := `-a: simple # just the best --b: [1, 2] -+a: "simple" # just the best -+b: [1, 3] - c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `-a: simple # just the best +// -b: [1, 2] +// +a: "simple" # just the best +// +b: [1, 3] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestComparePrettyCmd(t *testing.T) { - forceOsExit = false - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare -P ../examples/data1.yaml ../examples/data3.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := ` a: simple # just the best - b: - - 1 -- - 2 -+ - 3 - c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestComparePrettyCmd(t *testing.T) { +// forceOsExit = false +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare -P ../examples/data1.yaml ../examples/data3.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := ` a: simple # just the best +// b: +// - 1 +// - - 2 +// + - 3 +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestComparePathsCmd(t *testing.T) { - forceOsExit = false - cmd := getRootCommand() - result := test.RunCmd(cmd, "compare -P -ppv ../examples/data1.yaml ../examples/data3.yaml **") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := ` a: simple # just the best - b.[0]: 1 --b.[1]: 2 -+b.[1]: 3 - c.test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestComparePathsCmd(t *testing.T) { +// forceOsExit = false +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "compare -P -ppv ../examples/data1.yaml ../examples/data3.yaml **") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := ` a: simple # just the best +// b.[0]: 1 +// -b.[1]: 2 +// +b.[1]: 3 +// c.test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } diff --git a/cmd/constant.go b/cmd/constant.go index a1f6311..9de0052 100644 --- a/cmd/constant.go +++ b/cmd/constant.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/mikefarah/yq/v3/pkg/yqlib" + "github.com/mikefarah/yq/v3/pkg/yqlib/treeops" logging "gopkg.in/op/go-logging.v1" ) @@ -32,5 +33,5 @@ var verbose = false var version = false var docIndex = "0" var log = logging.MustGetLogger("yq") -var lib = yqlib.NewYqLib() +var lib = treeops.NewYqTreeLib() var valueParser = yqlib.NewValueParser() diff --git a/cmd/delete.go b/cmd/delete.go index b115310..96531e8 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -1,41 +1,41 @@ package cmd -import ( - "github.com/mikefarah/yq/v3/pkg/yqlib" - errors "github.com/pkg/errors" - "github.com/spf13/cobra" -) +// import ( +// "github.com/mikefarah/yq/v3/pkg/yqlib" +// errors "github.com/pkg/errors" +// "github.com/spf13/cobra" +// ) -func createDeleteCmd() *cobra.Command { - var cmdDelete = &cobra.Command{ - Use: "delete [yaml_file] [path_expression]", - Aliases: []string{"d"}, - Short: "yq d [--inplace/-i] [--doc/-d index] sample.yaml 'b.e(name==fred)'", - Example: ` -yq delete things.yaml 'a.b.c' -yq delete things.yaml 'a.*.c' -yq delete things.yaml 'a.(child.subchild==co*).c' -yq delete things.yaml 'a.**' -yq delete --inplace things.yaml 'a.b.c' -yq delete --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags -yq d -i things.yaml 'a.b.c' - `, - Long: `Deletes the nodes matching the given path expression from the YAML file. -Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. -`, - RunE: deleteProperty, - } - cmdDelete.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") - cmdDelete.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") - return cmdDelete -} +// func createDeleteCmd() *cobra.Command { +// var cmdDelete = &cobra.Command{ +// Use: "delete [yaml_file] [path_expression]", +// Aliases: []string{"d"}, +// Short: "yq d [--inplace/-i] [--doc/-d index] sample.yaml 'b.e(name==fred)'", +// Example: ` +// yq delete things.yaml 'a.b.c' +// yq delete things.yaml 'a.*.c' +// yq delete things.yaml 'a.(child.subchild==co*).c' +// yq delete things.yaml 'a.**' +// yq delete --inplace things.yaml 'a.b.c' +// yq delete --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags +// yq d -i things.yaml 'a.b.c' +// `, +// Long: `Deletes the nodes matching the given path expression from the YAML file. +// Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. +// `, +// RunE: deleteProperty, +// } +// cmdDelete.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") +// cmdDelete.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") +// return cmdDelete +// } -func deleteProperty(cmd *cobra.Command, args []string) error { - if len(args) < 2 { - return errors.New("Must provide ") - } - var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 1) - updateCommands[0] = yqlib.UpdateCommand{Command: "delete", Path: args[1]} +// func deleteProperty(cmd *cobra.Command, args []string) error { +// if len(args) < 2 { +// return errors.New("Must provide ") +// } +// var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 1) +// updateCommands[0] = yqlib.UpdateCommand{Command: "delete", Path: args[1]} - return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) -} +// return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) +// } diff --git a/cmd/delete_test.go b/cmd/delete_test.go index ae5c617..b7715e6 100644 --- a/cmd/delete_test.go +++ b/cmd/delete_test.go @@ -1,246 +1,246 @@ package cmd -import ( - "fmt" - "strings" - "testing" +// import ( +// "fmt" +// "strings" +// "testing" - "github.com/mikefarah/yq/v3/test" -) +// "github.com/mikefarah/yq/v3/test" +// ) -func TestDeleteYamlCmd(t *testing.T) { - content := `a: 2 -b: - c: things - d: something else -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteYamlCmd(t *testing.T) { +// content := `a: 2 +// b: +// c: things +// d: something else +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.c", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.c", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `a: 2 -b: - d: something else -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `a: 2 +// b: +// d: something else +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteDeepDoesNotExistCmd(t *testing.T) { - content := `a: 2` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteDeepDoesNotExistCmd(t *testing.T) { +// content := `a: 2` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.c", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.c", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `a: 2 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `a: 2 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteSplatYaml(t *testing.T) { - content := `a: other -b: [3, 4] -c: - toast: leave - test: 1 - tell: 1 - tasty.taco: cool -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteSplatYaml(t *testing.T) { +// content := `a: other +// b: [3, 4] +// c: +// toast: leave +// test: 1 +// tell: 1 +// tasty.taco: cool +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s c.te*", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s c.te*", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `a: other -b: [3, 4] -c: - toast: leave - tasty.taco: cool -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `a: other +// b: [3, 4] +// c: +// toast: leave +// tasty.taco: cool +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteSplatArrayYaml(t *testing.T) { - content := `a: 2 -b: - hi: - - thing: item1 - name: fred - - thing: item2 - name: sam -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteSplatArrayYaml(t *testing.T) { +// content := `a: 2 +// b: +// hi: +// - thing: item1 +// name: fred +// - thing: item2 +// name: sam +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.hi[*].thing", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.hi[*].thing", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `a: 2 -b: - hi: - - name: fred - - name: sam -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `a: 2 +// b: +// hi: +// - name: fred +// - name: sam +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteDeepSplatArrayYaml(t *testing.T) { - content := `thing: 123 -b: - hi: - - thing: item1 - name: fred -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteDeepSplatArrayYaml(t *testing.T) { +// content := `thing: 123 +// b: +// hi: +// - thing: item1 +// name: fred +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s **.thing", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s **.thing", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `b: - hi: - - name: fred -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `b: +// hi: +// - name: fred +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteSplatPrefixYaml(t *testing.T) { - content := `a: 2 -b: - hi: - c: things - d: something else - there: - c: more things - d: more something else - there2: - c: more things also - d: more something else also -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteSplatPrefixYaml(t *testing.T) { +// content := `a: 2 +// b: +// hi: +// c: things +// d: something else +// there: +// c: more things +// d: more something else +// there2: +// c: more things also +// d: more something else also +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.there*.c", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s b.there*.c", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `a: 2 -b: - hi: - c: things - d: something else - there: - d: more something else - there2: - d: more something else also -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `a: 2 +// b: +// hi: +// c: things +// d: something else +// there: +// d: more something else +// there2: +// d: more something else also +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteYamlArrayCmd(t *testing.T) { - content := `- 1 -- 2 -- 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteYamlArrayCmd(t *testing.T) { +// content := `- 1 +// - 2 +// - 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s [1]", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s [1]", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `- 1 -- 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `- 1 +// - 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteYamlArrayExpressionCmd(t *testing.T) { - content := `- name: fred -- name: cat -- name: thing -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteYamlArrayExpressionCmd(t *testing.T) { +// content := `- name: fred +// - name: cat +// - name: thing +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s (name==cat)", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s (name==cat)", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `- name: fred -- name: thing -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `- name: fred +// - name: thing +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteYamlMulti(t *testing.T) { - content := `apples: great ---- -- 1 -- 2 -- 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteYamlMulti(t *testing.T) { +// content := `apples: great +// --- +// - 1 +// - 2 +// - 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete -d 1 %s [1]", filename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete -d 1 %s [1]", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `apples: great ---- -- 1 -- 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `apples: great +// --- +// - 1 +// - 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestDeleteYamlMultiAllCmd(t *testing.T) { - content := `b: - c: 3 -apples: great ---- -apples: great -something: else -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestDeleteYamlMultiAllCmd(t *testing.T) { +// content := `b: +// c: 3 +// apples: great +// --- +// apples: great +// something: else +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("delete %s -d * apples", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 ---- -something: else` - test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("delete %s -d * apples", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// --- +// something: else` +// test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) +// } diff --git a/cmd/merge.go b/cmd/merge.go index ef4ca92..29a6aab 100644 --- a/cmd/merge.go +++ b/cmd/merge.go @@ -1,124 +1,124 @@ package cmd -import ( - "github.com/mikefarah/yq/v3/pkg/yqlib" - errors "github.com/pkg/errors" - "github.com/spf13/cobra" - yaml "gopkg.in/yaml.v3" -) +// import ( +// "github.com/mikefarah/yq/v3/pkg/yqlib" +// errors "github.com/pkg/errors" +// "github.com/spf13/cobra" +// yaml "gopkg.in/yaml.v3" +// ) -func createMergeCmd() *cobra.Command { - var cmdMerge = &cobra.Command{ - Use: "merge [initial_yaml_file] [additional_yaml_file]...", - Aliases: []string{"m"}, - Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--arrayMerge/-a strategy] sample.yaml sample2.yaml", - Example: ` -yq merge things.yaml other.yaml -yq merge --inplace things.yaml other.yaml -yq m -i things.yaml other.yaml -yq m --overwrite things.yaml other.yaml -yq m -i -x things.yaml other.yaml -yq m -i -a=append things.yaml other.yaml -yq m -i --autocreate=false things.yaml other.yaml - `, - 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. +// func createMergeCmd() *cobra.Command { +// var cmdMerge = &cobra.Command{ +// Use: "merge [initial_yaml_file] [additional_yaml_file]...", +// Aliases: []string{"m"}, +// Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--arrayMerge/-a strategy] sample.yaml sample2.yaml", +// Example: ` +// yq merge things.yaml other.yaml +// yq merge --inplace things.yaml other.yaml +// yq m -i things.yaml other.yaml +// yq m --overwrite things.yaml other.yaml +// yq m -i -x things.yaml other.yaml +// yq m -i -a=append things.yaml other.yaml +// yq m -i --autocreate=false things.yaml other.yaml +// `, +// 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. -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. -`, - RunE: mergeProperties, - } - 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(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries") - 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)") - return cmdMerge -} +// 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. +// `, +// RunE: mergeProperties, +// } +// 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(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries") +// 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)") +// return cmdMerge +// } -/* -* We don't deeply traverse arrays when appending a merge, instead we want to -* append the entire array element. - */ -func createReadFunctionForMerge(arrayMergeStrategy yqlib.ArrayMergeStrategy) func(*yaml.Node) ([]*yqlib.NodeContext, error) { - return func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) { - return lib.GetForMerge(dataBucket, "**", arrayMergeStrategy) - } -} +// /* +// * We don't deeply traverse arrays when appending a merge, instead we want to +// * append the entire array element. +// */ +// func createReadFunctionForMerge(arrayMergeStrategy yqlib.ArrayMergeStrategy) func(*yaml.Node) ([]*yqlib.NodeContext, error) { +// return func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) { +// return lib.GetForMerge(dataBucket, "**", arrayMergeStrategy) +// } +// } -func mergeProperties(cmd *cobra.Command, args []string) error { - var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0) +// func mergeProperties(cmd *cobra.Command, args []string) error { +// var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0) - if len(args) < 1 { - return errors.New("Must provide at least 1 yaml file") - } - var arrayMergeStrategy yqlib.ArrayMergeStrategy +// if len(args) < 1 { +// return errors.New("Must provide at least 1 yaml file") +// } +// var arrayMergeStrategy yqlib.ArrayMergeStrategy - switch arrayMergeStrategyFlag { - case "update": - arrayMergeStrategy = yqlib.UpdateArrayMergeStrategy - case "append": - arrayMergeStrategy = yqlib.AppendArrayMergeStrategy - case "overwrite": - arrayMergeStrategy = yqlib.OverwriteArrayMergeStrategy - default: - return errors.New("Array merge strategy must be one of: update/append/overwrite") - } +// switch arrayMergeStrategyFlag { +// case "update": +// arrayMergeStrategy = yqlib.UpdateArrayMergeStrategy +// case "append": +// arrayMergeStrategy = yqlib.AppendArrayMergeStrategy +// case "overwrite": +// arrayMergeStrategy = yqlib.OverwriteArrayMergeStrategy +// default: +// return errors.New("Array merge strategy must be one of: update/append/overwrite") +// } - var commentsMergeStrategy yqlib.CommentsMergeStrategy +// 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") - } +// 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 { - // first generate update commands from the file - var filesToMerge = args[1:] +// if len(args) > 1 { +// // first generate update commands from the file +// var filesToMerge = args[1:] - for _, fileToMerge := range filesToMerge { - matchingNodes, errorProcessingFile := doReadYamlFile(fileToMerge, createReadFunctionForMerge(arrayMergeStrategy), false, 0) - if errorProcessingFile != nil { - return errorProcessingFile - } - log.Debugf("finished reading for merge!") - for _, matchingNode := range matchingNodes { - log.Debugf("matched node %v", lib.PathStackToString(matchingNode.PathStack)) - yqlib.DebugNode(matchingNode.Node) - } - for _, matchingNode := range matchingNodes { - mergePath := lib.MergePathStackToString(matchingNode.PathStack, arrayMergeStrategy) - updateCommands = append(updateCommands, yqlib.UpdateCommand{ - Command: "merge", - Path: mergePath, - Value: matchingNode.Node, - Overwrite: overwriteFlag, - CommentsMergeStrategy: commentsMergeStrategy, - // dont update the content for nodes midway, only leaf nodes - DontUpdateNodeContent: matchingNode.IsMiddleNode && (arrayMergeStrategy != yqlib.OverwriteArrayMergeStrategy || matchingNode.Node.Kind != yaml.SequenceNode), - }) - } - } - } +// for _, fileToMerge := range filesToMerge { +// matchingNodes, errorProcessingFile := doReadYamlFile(fileToMerge, createReadFunctionForMerge(arrayMergeStrategy), false, 0) +// if errorProcessingFile != nil { +// return errorProcessingFile +// } +// log.Debugf("finished reading for merge!") +// for _, matchingNode := range matchingNodes { +// log.Debugf("matched node %v", lib.PathStackToString(matchingNode.PathStack)) +// yqlib.DebugNode(matchingNode.Node) +// } +// for _, matchingNode := range matchingNodes { +// mergePath := lib.MergePathStackToString(matchingNode.PathStack, arrayMergeStrategy) +// updateCommands = append(updateCommands, yqlib.UpdateCommand{ +// Command: "merge", +// Path: mergePath, +// Value: matchingNode.Node, +// Overwrite: overwriteFlag, +// CommentsMergeStrategy: commentsMergeStrategy, +// // dont update the content for nodes midway, only leaf nodes +// DontUpdateNodeContent: matchingNode.IsMiddleNode && (arrayMergeStrategy != yqlib.OverwriteArrayMergeStrategy || matchingNode.Node.Kind != yaml.SequenceNode), +// }) +// } +// } +// } - return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) -} +// return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) +// } diff --git a/cmd/merge_test.go b/cmd/merge_test.go index a3d5f79..b69060e 100644 --- a/cmd/merge_test.go +++ b/cmd/merge_test.go @@ -1,551 +1,551 @@ package cmd -import ( - "fmt" - "os" - "runtime" - "testing" +// import ( +// "fmt" +// "os" +// "runtime" +// "testing" - "github.com/mikefarah/yq/v3/test" -) +// "github.com/mikefarah/yq/v3/test" +// ) -func TestMergeCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge ../examples/data1.yaml ../examples/data2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: simple # just the best -b: [1, 2] -c: - test: 1 - toast: leave - tell: 1 - tasty.taco: cool -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge ../examples/data1.yaml ../examples/data2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// toast: leave +// tell: 1 +// tasty.taco: cool +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeOneFileCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge ../examples/data1.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: simple # just the best -b: [1, 2] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeOneFileCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge ../examples/data1.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeNoAutoCreateCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge -c=false ../examples/data1.yaml ../examples/data2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: simple # just the best -b: [1, 2] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeNoAutoCreateCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge -c=false ../examples/data1.yaml ../examples/data2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeOverwriteCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge -c=false --overwrite ../examples/data1.yaml ../examples/data2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: other # just the best -b: [3, 4] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeOverwriteCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge -c=false --overwrite ../examples/data1.yaml ../examples/data2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: other # just the best +// b: [3, 4] +// c: +// test: 1 +// ` +// 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) +// 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) +// 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) - } +// 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) -} +// 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 --arrays=append ../examples/data1.yaml ../examples/data2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: simple # just the best -b: [1, 2, 3, 4] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeAppendCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge --autocreate=false --arrays=append ../examples/data1.yaml ../examples/data2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: simple # just the best +// b: [1, 2, 3, 4] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeAppendArraysCmd(t *testing.T) { - content := `people: - - name: Barry - age: 21` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestMergeAppendArraysCmd(t *testing.T) { +// content := `people: +// - name: Barry +// age: 21` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - mergeContent := `people: - - name: Roger - age: 44` - mergeFilename := test.WriteTempYamlFile(mergeContent) - defer test.RemoveTempYamlFile(mergeFilename) +// mergeContent := `people: +// - name: Roger +// age: 44` +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge --arrays=append -d* %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `people: - - name: Barry - age: 21 - - name: Roger - age: 44 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge --arrays=append -d* %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `people: +// - name: Barry +// age: 21 +// - name: Roger +// age: 44 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeAliasArraysCmd(t *testing.T) { - content := ` -vars: - variable1: &var1 cat +// func TestMergeAliasArraysCmd(t *testing.T) { +// content := ` +// vars: +// variable1: &var1 cat -usage: - value1: *var1 - valueAnother: *var1 - valuePlain: thing -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// usage: +// value1: *var1 +// valueAnother: *var1 +// valuePlain: thing +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - mergeContent := ` -vars: - variable2: &var2 puppy +// mergeContent := ` +// vars: +// variable2: &var2 puppy -usage: - value2: *var2 - valueAnother: *var2 - valuePlain: *var2 -` +// usage: +// value2: *var2 +// valueAnother: *var2 +// valuePlain: *var2 +// ` - mergeFilename := test.WriteTempYamlFile(mergeContent) - defer test.RemoveTempYamlFile(mergeFilename) +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge -x %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `vars: - variable1: &var1 cat - variable2: &var2 puppy -usage: - value1: *var1 - valueAnother: *var2 - valuePlain: *var2 - value2: *var2 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge -x %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `vars: +// variable1: &var1 cat +// variable2: &var2 puppy +// usage: +// value1: *var1 +// valueAnother: *var2 +// valuePlain: *var2 +// value2: *var2 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeOverwriteAndAppendCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge --autocreate=false --arrays=append --overwrite ../examples/data1.yaml ../examples/data2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: other # just the best -b: [1, 2, 3, 4] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeOverwriteAndAppendCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge --autocreate=false --arrays=append --overwrite ../examples/data1.yaml ../examples/data2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: other # just the best +// b: [1, 2, 3, 4] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -var commentContentA = ` -a: valueA1 # commentA1 -b: valueB1 -` +// var commentContentA = ` +// a: valueA1 # commentA1 +// b: valueB1 +// ` -var commentContentB = ` -a: valueA2 # commentA2 -b: valueB2 # commentB2 -c: valueC2 # commentC2 -` +// var commentContentB = ` +// a: valueA2 # commentA2 +// b: valueB2 # commentB2 +// c: valueC2 # commentC2 +// ` -func TestMergeCommentsSetWhenBlankCmd(t *testing.T) { - filename := test.WriteTempYamlFile(commentContentA) - defer test.RemoveTempYamlFile(filename) +// func TestMergeCommentsSetWhenBlankCmd(t *testing.T) { +// filename := test.WriteTempYamlFile(commentContentA) +// defer test.RemoveTempYamlFile(filename) - mergeFilename := test.WriteTempYamlFile(commentContentB) - defer test.RemoveTempYamlFile(mergeFilename) +// 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) - } +// 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) -} +// 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) +// func TestMergeCommentsIgnoreCmd(t *testing.T) { +// filename := test.WriteTempYamlFile(commentContentA) +// defer test.RemoveTempYamlFile(filename) - mergeFilename := test.WriteTempYamlFile(commentContentB) - defer test.RemoveTempYamlFile(mergeFilename) +// 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) - } +// 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) -} +// 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) +// func TestMergeCommentsAppendCmd(t *testing.T) { +// filename := test.WriteTempYamlFile(commentContentA) +// defer test.RemoveTempYamlFile(filename) - mergeFilename := test.WriteTempYamlFile(commentContentB) - defer test.RemoveTempYamlFile(mergeFilename) +// 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) - } +// 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) -} +// 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) +// func TestMergeCommentsOverwriteCmd(t *testing.T) { +// filename := test.WriteTempYamlFile(commentContentA) +// defer test.RemoveTempYamlFile(filename) - mergeFilename := test.WriteTempYamlFile(commentContentB) - defer test.RemoveTempYamlFile(mergeFilename) +// 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) - } +// 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) -} +// expectedOutput := `a: valueA1 # commentA2 +// b: valueB1 # commentB2 +// c: valueC2 # commentC2 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -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) +// 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) +// mergeContent := `a: things +// b: [6]` +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge --autocreate=false --arrays=overwrite --overwrite %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge --autocreate=false --arrays=overwrite --overwrite %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } - expectedOutput := `a: things # just the best -b: [6] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// expectedOutput := `a: things # just the best +// b: [6] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeRootArraysCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge --arrays=append ../examples/sample_array.yaml ../examples/sample_array_2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `- 1 -- 2 -- 3 -- 4 -- 5 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeRootArraysCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge --arrays=append ../examples/sample_array.yaml ../examples/sample_array_2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `- 1 +// - 2 +// - 3 +// - 4 +// - 5 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeOverwriteArraysCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge --arrays=overwrite ../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 TestMergeOverwriteArraysCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge --arrays=overwrite ../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 TestMergeUpdateArraysCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge -x --arrays=update ../examples/sample_array.yaml ../examples/sample_array_2.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `- 4 -- 5 -- 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeUpdateArraysCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge -x --arrays=update ../examples/sample_array.yaml ../examples/sample_array_2.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `- 4 +// - 5 +// - 3 +// ` +// 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") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: Easy! as one two three ---- -another: - document: here -a: simple # just the best -b: [1, 2] -c: - test: 1 ---- -- 1 -- 2 -` - 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") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: Easy! as one two three +// --- +// another: +// document: here +// a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// --- +// - 1 +// - 2 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeYamlMultiAllCmd(t *testing.T) { - content := `b: - c: 3 -apples: green ---- -something: else` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestMergeYamlMultiAllCmd(t *testing.T) { +// content := `b: +// c: 3 +// apples: green +// --- +// something: else` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - mergeContent := `apples: red -something: good` - mergeFilename := test.WriteTempYamlFile(mergeContent) - defer test.RemoveTempYamlFile(mergeFilename) +// mergeContent := `apples: red +// something: good` +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge -d* %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 -apples: green -something: good ---- -something: else -apples: red -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge -d* %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// apples: green +// something: good +// --- +// something: else +// apples: red +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeSpecialCharacterKeysCmd(t *testing.T) { - content := `` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestMergeSpecialCharacterKeysCmd(t *testing.T) { +// content := `` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - mergeContent := `key[bracket]: value -key.bracket: value -key"value": value -key'value': value -` - mergeFilename := test.WriteTempYamlFile(mergeContent) - defer test.RemoveTempYamlFile(mergeFilename) +// mergeContent := `key[bracket]: value +// key.bracket: value +// key"value": value +// key'value': value +// ` +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } - test.AssertResult(t, mergeContent, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// test.AssertResult(t, mergeContent, result.Output) +// } -func TestMergeYamlMultiAllOverwriteCmd(t *testing.T) { - content := `b: - c: 3 -apples: green ---- -something: else` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestMergeYamlMultiAllOverwriteCmd(t *testing.T) { +// content := `b: +// c: 3 +// apples: green +// --- +// something: else` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - mergeContent := `apples: red -something: good` - mergeFilename := test.WriteTempYamlFile(mergeContent) - defer test.RemoveTempYamlFile(mergeFilename) +// mergeContent := `apples: red +// something: good` +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge --overwrite -d* %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 -apples: red -something: good ---- -something: good -apples: red -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge --overwrite -d* %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// apples: red +// something: good +// --- +// something: good +// apples: red +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeYamlNullMapCmd(t *testing.T) { - content := `b:` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestMergeYamlNullMapCmd(t *testing.T) { +// content := `b:` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - mergeContent := `b: - thing: a frog -` - mergeFilename := test.WriteTempYamlFile(mergeContent) - defer test.RemoveTempYamlFile(mergeFilename) +// mergeContent := `b: +// thing: a frog +// ` +// mergeFilename := test.WriteTempYamlFile(mergeContent) +// defer test.RemoveTempYamlFile(mergeFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge %s %s", filename, mergeFilename)) - if result.Error != nil { - t.Error(result.Error) - } - test.AssertResult(t, mergeContent, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge %s %s", filename, mergeFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// test.AssertResult(t, mergeContent, result.Output) +// } -func TestMergeCmd_Error(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge") - if result.Error == nil { - t.Error("Expected command to fail due to missing arg") - } - expectedOutput := `Must provide at least 1 yaml file` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} +// func TestMergeCmd_Error(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge") +// if result.Error == nil { +// t.Error("Expected command to fail due to missing arg") +// } +// expectedOutput := `Must provide at least 1 yaml file` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } -func TestMergeCmd_ErrorUnreadableFile(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge ../examples/data1.yaml fake-unknown") - if result.Error == nil { - t.Error("Expected command to fail due to unknown file") - } - var expectedOutput string - if runtime.GOOS == "windows" { - expectedOutput = `open fake-unknown: The system cannot find the file specified.` - } else { - expectedOutput = `open fake-unknown: no such file or directory` - } - test.AssertResult(t, expectedOutput, result.Error.Error()) -} +// func TestMergeCmd_ErrorUnreadableFile(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge ../examples/data1.yaml fake-unknown") +// if result.Error == nil { +// t.Error("Expected command to fail due to unknown file") +// } +// var expectedOutput string +// if runtime.GOOS == "windows" { +// expectedOutput = `open fake-unknown: The system cannot find the file specified.` +// } else { +// expectedOutput = `open fake-unknown: no such file or directory` +// } +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } -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 { - t.Error(err) - } - defer test.RemoveTempYamlFile(filename) +// 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 { +// t.Error(err) +// } +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("merge -i %s ../examples/data2.yaml", filename)) - if result.Error != nil { - t.Error(result.Error) - } - info, _ := os.Stat(filename) - gotOutput := test.ReadTempYamlFile(filename) - expectedOutput := `a: simple # just the best -b: [1, 2] -c: - test: 1 - toast: leave - tell: 1 - tasty.taco: cool -` - test.AssertResult(t, expectedOutput, gotOutput) - test.AssertResult(t, os.FileMode(int(0666)), info.Mode()) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("merge -i %s ../examples/data2.yaml", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// info, _ := os.Stat(filename) +// gotOutput := test.ReadTempYamlFile(filename) +// expectedOutput := `a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// toast: leave +// tell: 1 +// tasty.taco: cool +// ` +// test.AssertResult(t, expectedOutput, gotOutput) +// test.AssertResult(t, os.FileMode(int(0666)), info.Mode()) +// } -func TestMergeAllowEmptyTargetCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge ../examples/empty.yaml ../examples/data1.yaml") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: simple # just the best -b: [1, 2] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeAllowEmptyTargetCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge ../examples/empty.yaml ../examples/data1.yaml") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestMergeAllowEmptyMergeCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "merge ../examples/data1.yaml ../examples/empty.yaml") - expectedOutput := `a: simple # just the best -b: [1, 2] -c: - test: 1 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestMergeAllowEmptyMergeCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "merge ../examples/data1.yaml ../examples/empty.yaml") +// expectedOutput := `a: simple # just the best +// b: [1, 2] +// c: +// test: 1 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } diff --git a/cmd/new.go b/cmd/new.go index fede252..46bc9bd 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -1,55 +1,55 @@ package cmd -import ( - "github.com/mikefarah/yq/v3/pkg/yqlib" - "github.com/spf13/cobra" -) +// import ( +// "github.com/mikefarah/yq/v3/pkg/yqlib" +// "github.com/spf13/cobra" +// ) -func createNewCmd() *cobra.Command { - var cmdNew = &cobra.Command{ - Use: "new [path] [value]", - Aliases: []string{"n"}, - Short: "yq n [--script/-s script_file] a.b.c newValue", - Example: ` -yq new 'a.b.c' cat -yq n 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool -yq n 'a.b[+]' cat -yq n -- '--key-starting-with-dash' cat # need to use '--' to stop processing arguments as flags -yq n --script create_script.yaml - `, - Long: `Creates a new yaml w.r.t the given path and value. -Outputs to STDOUT +// func createNewCmd() *cobra.Command { +// var cmdNew = &cobra.Command{ +// Use: "new [path] [value]", +// Aliases: []string{"n"}, +// Short: "yq n [--script/-s script_file] a.b.c newValue", +// Example: ` +// yq new 'a.b.c' cat +// yq n 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool +// yq n 'a.b[+]' cat +// yq n -- '--key-starting-with-dash' cat # need to use '--' to stop processing arguments as flags +// yq n --script create_script.yaml +// `, +// Long: `Creates a new yaml w.r.t the given path and value. +// Outputs to STDOUT -Create Scripts: -Note that you can give a create script to perform more sophisticated yaml. This follows the same format as the update script. -`, - RunE: newProperty, - } - cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for creating yaml") - cmdNew.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)") - cmdNew.PersistentFlags().StringVarP(&customStyle, "style", "", "", "formatting style of the value: single, double, folded, flow, literal, tagged") - cmdNew.PersistentFlags().StringVarP(&anchorName, "anchorName", "", "", "anchor name") - cmdNew.PersistentFlags().BoolVarP(&makeAlias, "makeAlias", "", false, "create an alias using the value as the anchor name") - return cmdNew -} +// Create Scripts: +// Note that you can give a create script to perform more sophisticated yaml. This follows the same format as the update script. +// `, +// RunE: newProperty, +// } +// cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for creating yaml") +// cmdNew.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)") +// cmdNew.PersistentFlags().StringVarP(&customStyle, "style", "", "", "formatting style of the value: single, double, folded, flow, literal, tagged") +// cmdNew.PersistentFlags().StringVarP(&anchorName, "anchorName", "", "", "anchor name") +// cmdNew.PersistentFlags().BoolVarP(&makeAlias, "makeAlias", "", false, "create an alias using the value as the anchor name") +// return cmdNew +// } -func newProperty(cmd *cobra.Command, args []string) error { - var badArgsMessage = "Must provide " - var updateCommands, updateCommandsError = readUpdateCommands(args, 2, badArgsMessage, false) - if updateCommandsError != nil { - return updateCommandsError - } - newNode := lib.New(updateCommands[0].Path) +// func newProperty(cmd *cobra.Command, args []string) error { +// var badArgsMessage = "Must provide " +// var updateCommands, updateCommandsError = readUpdateCommands(args, 2, badArgsMessage, false) +// if updateCommandsError != nil { +// return updateCommandsError +// } +// newNode := lib.New(updateCommands[0].Path) - for _, updateCommand := range updateCommands { +// for _, updateCommand := range updateCommands { - errorUpdating := lib.Update(&newNode, updateCommand, true) +// errorUpdating := lib.Update(&newNode, updateCommand, true) - if errorUpdating != nil { - return errorUpdating - } - } +// if errorUpdating != nil { +// return errorUpdating +// } +// } - var encoder = yqlib.NewYamlEncoder(cmd.OutOrStdout(), indent, colorsEnabled) - return encoder.Encode(&newNode) -} +// var encoder = yqlib.NewYamlEncoder(cmd.OutOrStdout(), indent, colorsEnabled) +// return encoder.Encode(&newNode) +// } diff --git a/cmd/new_test.go b/cmd/new_test.go index bdd9f27..fc887de 100644 --- a/cmd/new_test.go +++ b/cmd/new_test.go @@ -1,120 +1,120 @@ package cmd -import ( - "fmt" - "testing" +// import ( +// "fmt" +// "testing" - "github.com/mikefarah/yq/v3/test" -) +// "github.com/mikefarah/yq/v3/test" +// ) -func TestNewCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c 3") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c 3") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewCmdScript(t *testing.T) { - updateScript := `- command: update - path: b.c - value: 7` - scriptFilename := test.WriteTempYamlFile(updateScript) - defer test.RemoveTempYamlFile(scriptFilename) +// func TestNewCmdScript(t *testing.T) { +// updateScript := `- command: update +// path: b.c +// value: 7` +// scriptFilename := test.WriteTempYamlFile(updateScript) +// defer test.RemoveTempYamlFile(scriptFilename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("new --script %s", scriptFilename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 7 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("new --script %s", scriptFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 7 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewAnchorCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c 3 --anchorName=fred") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: &fred 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewAnchorCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c 3 --anchorName=fred") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: &fred 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewAliasCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c foo --makeAlias") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: *foo -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewAliasCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c foo --makeAlias") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: *foo +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewArrayCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b[0] 3") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - - 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewArrayCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b[0] 3") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// - 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewCmd_Error(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c") - if result.Error == nil { - t.Error("Expected command to fail due to missing arg") - } - expectedOutput := `Must provide ` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} +// func TestNewCmd_Error(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c") +// if result.Error == nil { +// t.Error("Expected command to fail due to missing arg") +// } +// expectedOutput := `Must provide ` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } -func TestNewWithTaggedStyleCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c cat --tag=!!str --style=tagged") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: !!str cat -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewWithTaggedStyleCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c cat --tag=!!str --style=tagged") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: !!str cat +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewWithDoubleQuotedStyleCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c cat --style=double") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: "cat" -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewWithDoubleQuotedStyleCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c cat --style=double") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: "cat" +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestNewWithSingleQuotedStyleCmd(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "new b.c cat --style=single") - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 'cat' -` - test.AssertResult(t, expectedOutput, result.Output) -} +// func TestNewWithSingleQuotedStyleCmd(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "new b.c cat --style=single") +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 'cat' +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } diff --git a/cmd/prefix.go b/cmd/prefix.go index ae5c28a..0fcde77 100644 --- a/cmd/prefix.go +++ b/cmd/prefix.go @@ -1,50 +1,50 @@ package cmd -import ( - "github.com/mikefarah/yq/v3/pkg/yqlib" - errors "github.com/pkg/errors" - "github.com/spf13/cobra" - yaml "gopkg.in/yaml.v3" -) +// import ( +// "github.com/mikefarah/yq/v3/pkg/yqlib" +// errors "github.com/pkg/errors" +// "github.com/spf13/cobra" +// yaml "gopkg.in/yaml.v3" +// ) -func createPrefixCmd() *cobra.Command { - var cmdPrefix = &cobra.Command{ - Use: "prefix [yaml_file] [path]", - Aliases: []string{"p"}, - Short: "yq p [--inplace/-i] [--doc/-d index] sample.yaml a.b.c", - Example: ` -yq prefix things.yaml 'a.b.c' -yq prefix --inplace things.yaml 'a.b.c' -yq prefix --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags -yq p -i things.yaml 'a.b.c' -yq p --doc 2 things.yaml 'a.b.d' -yq p -d2 things.yaml 'a.b.d' - `, - Long: `Prefixes w.r.t to the yaml file at the given path. -Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. -`, - RunE: prefixProperty, - } - cmdPrefix.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") - cmdPrefix.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") - return cmdPrefix -} +// func createPrefixCmd() *cobra.Command { +// var cmdPrefix = &cobra.Command{ +// Use: "prefix [yaml_file] [path]", +// Aliases: []string{"p"}, +// Short: "yq p [--inplace/-i] [--doc/-d index] sample.yaml a.b.c", +// Example: ` +// yq prefix things.yaml 'a.b.c' +// yq prefix --inplace things.yaml 'a.b.c' +// yq prefix --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags +// yq p -i things.yaml 'a.b.c' +// yq p --doc 2 things.yaml 'a.b.d' +// yq p -d2 things.yaml 'a.b.d' +// `, +// Long: `Prefixes w.r.t to the yaml file at the given path. +// Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. +// `, +// RunE: prefixProperty, +// } +// cmdPrefix.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") +// cmdPrefix.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") +// return cmdPrefix +// } -func prefixProperty(cmd *cobra.Command, args []string) error { +// func prefixProperty(cmd *cobra.Command, args []string) error { - if len(args) < 2 { - return errors.New("Must provide ") - } - updateCommand := yqlib.UpdateCommand{Command: "update", Path: args[1]} - log.Debugf("args %v", args) +// if len(args) < 2 { +// return errors.New("Must provide ") +// } +// updateCommand := yqlib.UpdateCommand{Command: "update", Path: args[1]} +// log.Debugf("args %v", args) - var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() - if errorParsingDocIndex != nil { - return errorParsingDocIndex - } +// var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() +// if errorParsingDocIndex != nil { +// return errorParsingDocIndex +// } - var updateData = func(dataBucket *yaml.Node, currentIndex int) error { - return prefixDocument(updateAll, docIndexInt, currentIndex, dataBucket, updateCommand) - } - return readAndUpdate(cmd.OutOrStdout(), args[0], updateData) -} +// var updateData = func(dataBucket *yaml.Node, currentIndex int) error { +// return prefixDocument(updateAll, docIndexInt, currentIndex, dataBucket, updateCommand) +// } +// return readAndUpdate(cmd.OutOrStdout(), args[0], updateData) +// } diff --git a/cmd/prefix_test.go b/cmd/prefix_test.go index ee5c198..b23437c 100644 --- a/cmd/prefix_test.go +++ b/cmd/prefix_test.go @@ -1,189 +1,189 @@ package cmd -import ( - "fmt" - "runtime" - "strings" - "testing" +// import ( +// "fmt" +// "runtime" +// "strings" +// "testing" - "github.com/mikefarah/yq/v3/test" -) +// "github.com/mikefarah/yq/v3/test" +// ) -func TestPrefixCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestPrefixCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s d", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `d: - b: - c: 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s d", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `d: +// b: +// c: 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestPrefixCmdArray(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestPrefixCmdArray(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s [+].d.[+]", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `- d: - - b: - c: 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s [+].d.[+]", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `- d: +// - b: +// c: 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestPrefixCmd_MultiLayer(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestPrefixCmd_MultiLayer(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s d.e.f", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `d: - e: - f: - b: - c: 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s d.e.f", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `d: +// e: +// f: +// b: +// c: 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } -func TestPrefixMultiCmd(t *testing.T) { - content := `b: - c: 3 ---- -apples: great -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestPrefixMultiCmd(t *testing.T) { +// content := `b: +// c: 3 +// --- +// apples: great +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -d 1 d", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 ---- -d: - apples: great -` - test.AssertResult(t, expectedOutput, result.Output) -} -func TestPrefixInvalidDocumentIndexCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -d 1 d", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// --- +// d: +// apples: great +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } +// func TestPrefixInvalidDocumentIndexCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -df d", filename)) - if result.Error == nil { - t.Error("Expected command to fail due to invalid path") - } - expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -df d", filename)) +// if result.Error == nil { +// t.Error("Expected command to fail due to invalid path") +// } +// expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } -func TestPrefixBadDocumentIndexCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestPrefixBadDocumentIndexCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -d 1 d", filename)) - 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)` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} -func TestPrefixMultiAllCmd(t *testing.T) { - content := `b: - c: 3 ---- -apples: great -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -d 1 d", filename)) +// 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)` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } +// func TestPrefixMultiAllCmd(t *testing.T) { +// content := `b: +// c: 3 +// --- +// apples: great +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -d * d", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `d: - b: - c: 3 ---- -d: - apples: great` - test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix %s -d * d", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `d: +// b: +// c: 3 +// --- +// d: +// apples: great` +// test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) +// } -func TestPrefixCmd_Error(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "prefix") - if result.Error == nil { - t.Error("Expected command to fail due to missing arg") - } - expectedOutput := `Must provide ` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} +// func TestPrefixCmd_Error(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "prefix") +// if result.Error == nil { +// t.Error("Expected command to fail due to missing arg") +// } +// expectedOutput := `Must provide ` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } -func TestPrefixCmd_ErrorUnreadableFile(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "prefix fake-unknown a.b") - if result.Error == nil { - t.Error("Expected command to fail due to unknown file") - } - var expectedOutput string - if runtime.GOOS == "windows" { - expectedOutput = `open fake-unknown: The system cannot find the file specified.` - } else { - expectedOutput = `open fake-unknown: no such file or directory` - } - test.AssertResult(t, expectedOutput, result.Error.Error()) -} +// func TestPrefixCmd_ErrorUnreadableFile(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "prefix fake-unknown a.b") +// if result.Error == nil { +// t.Error("Expected command to fail due to unknown file") +// } +// var expectedOutput string +// if runtime.GOOS == "windows" { +// expectedOutput = `open fake-unknown: The system cannot find the file specified.` +// } else { +// expectedOutput = `open fake-unknown: no such file or directory` +// } +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } -func TestPrefixCmd_Inplace(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) +// func TestPrefixCmd_Inplace(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("prefix -i %s d", filename)) - if result.Error != nil { - t.Error(result.Error) - } - gotOutput := test.ReadTempYamlFile(filename) - expectedOutput := `d: - b: - c: 3` - test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n ")) -} +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("prefix -i %s d", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// gotOutput := test.ReadTempYamlFile(filename) +// expectedOutput := `d: +// b: +// c: 3` +// test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n ")) +// } diff --git a/cmd/read.go b/cmd/read.go index 8e68f77..2453046 100644 --- a/cmd/read.go +++ b/cmd/read.go @@ -26,7 +26,6 @@ yq r -- things.yaml '--key-starting-with-dashes.blah' cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") cmdRead.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)") cmdRead.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results") - cmdRead.PersistentFlags().BoolVarP(&printLength, "length", "l", false, "print length of results") cmdRead.PersistentFlags().BoolVarP(&collectIntoArray, "collect", "c", false, "collect results into array") cmdRead.PersistentFlags().BoolVarP(&unwrapScalar, "unwrapScalar", "", true, "unwrap scalar, print the value with no quotes, colors or comments") cmdRead.PersistentFlags().BoolVarP(&stripComments, "stripComments", "", false, "print yaml without any comments") diff --git a/cmd/read_test.go b/cmd/read_test.go index e193ff2..bbbb6e6 100644 --- a/cmd/read_test.go +++ b/cmd/read_test.go @@ -127,7 +127,7 @@ func TestReadWithAdvancedFilterCmd(t *testing.T) { func TestReadWithAdvancedFilterMapCmd(t *testing.T) { cmd := getRootCommand() - result := test.RunCmd(cmd, "read ../examples/sample.yaml b.e[name`==`fr*]") + result := test.RunCmd(cmd, "read ../examples/sample.yaml b.e(name==fr*)") if result.Error != nil { t.Error(result.Error) } diff --git a/cmd/root.go b/cmd/root.go index a7f9b6b..b2e3ff4 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -48,13 +48,13 @@ func New() *cobra.Command { rootCmd.AddCommand( createReadCmd(), - createCompareCmd(), + // createCompareCmd(), createValidateCmd(), - createWriteCmd(), - createPrefixCmd(), - createDeleteCmd(), - createNewCmd(), - createMergeCmd(), + // createWriteCmd(), + // createPrefixCmd(), + // createDeleteCmd(), + // createNewCmd(), + // createMergeCmd(), createBashCompletionCmd(rootCmd), ) return rootCmd diff --git a/cmd/utils.go b/cmd/utils.go index 9b1ca72..9d3e5a7 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -4,29 +4,29 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "os" "strconv" "github.com/mikefarah/yq/v3/pkg/yqlib" + "github.com/mikefarah/yq/v3/pkg/yqlib/treeops" errors "github.com/pkg/errors" yaml "gopkg.in/yaml.v3" ) -type readDataFn func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) +type readDataFn func(document int, dataBucket *yaml.Node) ([]*treeops.CandidateNode, error) -func createReadFunction(path string) func(*yaml.Node) ([]*yqlib.NodeContext, error) { - return func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) { - return lib.Get(dataBucket, path) +func createReadFunction(path string) func(int, *yaml.Node) ([]*treeops.CandidateNode, error) { + return func(document int, dataBucket *yaml.Node) ([]*treeops.CandidateNode, error) { + return lib.Get(document, dataBucket, path) } } -func readYamlFile(filename string, path string, updateAll bool, docIndexInt int) ([]*yqlib.NodeContext, error) { +func readYamlFile(filename string, path string, updateAll bool, docIndexInt int) ([]*treeops.CandidateNode, error) { return doReadYamlFile(filename, createReadFunction(path), updateAll, docIndexInt) } -func doReadYamlFile(filename string, readFn readDataFn, updateAll bool, docIndexInt int) ([]*yqlib.NodeContext, error) { - var matchingNodes []*yqlib.NodeContext +func doReadYamlFile(filename string, readFn readDataFn, updateAll bool, docIndexInt int) ([]*treeops.CandidateNode, error) { + var matchingNodes []*treeops.CandidateNode var currentIndex = 0 var errorReadingStream = readStream(filename, func(decoder *yaml.Decoder) error { @@ -63,14 +63,14 @@ func handleEOF(updateAll bool, docIndexInt int, currentIndex int) error { return nil } -func appendDocument(originalMatchingNodes []*yqlib.NodeContext, dataBucket yaml.Node, readFn readDataFn, updateAll bool, docIndexInt int, currentIndex int) ([]*yqlib.NodeContext, error) { +func appendDocument(originalMatchingNodes []*treeops.CandidateNode, dataBucket yaml.Node, readFn readDataFn, updateAll bool, docIndexInt int, currentIndex int) ([]*treeops.CandidateNode, error) { log.Debugf("processing document %v - requested index %v", currentIndex, docIndexInt) - yqlib.DebugNode(&dataBucket) + // yqlib.DebugNode(&dataBucket) if !updateAll && currentIndex != docIndexInt { return originalMatchingNodes, nil } log.Debugf("reading in document %v", currentIndex) - matchingNodes, errorParsing := readFn(&dataBucket) + matchingNodes, errorParsing := readFn(currentIndex, &dataBucket) if errorParsing != nil { return nil, errors.Wrapf(errorParsing, "Error reading path in document index %v", currentIndex) } @@ -114,7 +114,7 @@ func printNode(node *yaml.Node, writer io.Writer) error { return encoder.Encode(node) } -func removeComments(matchingNodes []*yqlib.NodeContext) { +func removeComments(matchingNodes []*treeops.CandidateNode) { for _, nodeContext := range matchingNodes { removeCommentOfNode(nodeContext.Node) } @@ -130,7 +130,7 @@ func removeCommentOfNode(node *yaml.Node) { } } -func setStyle(matchingNodes []*yqlib.NodeContext, style yaml.Style) { +func setStyle(matchingNodes []*treeops.CandidateNode, style yaml.Style) { for _, nodeContext := range matchingNodes { updateStyleOfNode(nodeContext.Node, style) } @@ -234,10 +234,10 @@ func explodeNode(node *yaml.Node) error { } } -func explode(matchingNodes []*yqlib.NodeContext) error { +func explode(matchingNodes []*treeops.CandidateNode) error { log.Debug("exploding nodes") for _, nodeContext := range matchingNodes { - log.Debugf("exploding %v", nodeContext.Head) + log.Debugf("exploding %v", nodeContext.GetKey()) errorExplodingNode := explodeNode(nodeContext.Node) if errorExplodingNode != nil { return errorExplodingNode @@ -246,7 +246,7 @@ func explode(matchingNodes []*yqlib.NodeContext) error { return nil } -func printResults(matchingNodes []*yqlib.NodeContext, writer io.Writer) error { +func printResults(matchingNodes []*treeops.CandidateNode, writer io.Writer) error { if prettyPrint { setStyle(matchingNodes, 0) } @@ -280,7 +280,7 @@ func printResults(matchingNodes []*yqlib.NodeContext, writer io.Writer) error { for _, mappedDoc := range matchingNodes { switch printMode { case "p": - errorWriting = writeString(bufferedWriter, lib.PathStackToString(mappedDoc.PathStack)+"\n") + errorWriting = writeString(bufferedWriter, mappedDoc.PathStackToString()+"\n") if errorWriting != nil { return errorWriting } @@ -288,7 +288,7 @@ func printResults(matchingNodes []*yqlib.NodeContext, writer io.Writer) error { // put it into a node and print that. var parentNode = yaml.Node{Kind: yaml.MappingNode} parentNode.Content = make([]*yaml.Node, 2) - parentNode.Content[0] = &yaml.Node{Kind: yaml.ScalarNode, Value: lib.PathStackToString(mappedDoc.PathStack)} + parentNode.Content[0] = &yaml.Node{Kind: yaml.ScalarNode, Value: mappedDoc.PathStackToString()} parentNode.Content[1] = transformNode(mappedDoc.Node) if collectIntoArray { arrayCollection.Content = append(arrayCollection.Content, &parentNode) @@ -383,102 +383,102 @@ func mapYamlDecoder(updateData updateDataFn, encoder yqlib.Encoder) yamlDecoderF } } -func prefixDocument(updateAll bool, docIndexInt int, currentIndex int, dataBucket *yaml.Node, updateCommand yqlib.UpdateCommand) error { - if updateAll || currentIndex == docIndexInt { - log.Debugf("Prefixing document %v", currentIndex) - yqlib.DebugNode(dataBucket) - updateCommand.Value = dataBucket.Content[0] - dataBucket.Content = make([]*yaml.Node, 1) +// func prefixDocument(updateAll bool, docIndexInt int, currentIndex int, dataBucket *yaml.Node, updateCommand yqlib.UpdateCommand) error { +// if updateAll || currentIndex == docIndexInt { +// log.Debugf("Prefixing document %v", currentIndex) +// // yqlib.DebugNode(dataBucket) +// updateCommand.Value = dataBucket.Content[0] +// dataBucket.Content = make([]*yaml.Node, 1) - newNode := lib.New(updateCommand.Path) - dataBucket.Content[0] = &newNode +// newNode := lib.New(updateCommand.Path) +// dataBucket.Content[0] = &newNode - errorUpdating := lib.Update(dataBucket, updateCommand, true) - if errorUpdating != nil { - return errorUpdating - } - } - return nil -} +// errorUpdating := lib.Update(dataBucket, updateCommand, true) +// if errorUpdating != nil { +// return errorUpdating +// } +// } +// return nil +// } -func updateDoc(inputFile string, updateCommands []yqlib.UpdateCommand, writer io.Writer) error { - var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() - if errorParsingDocIndex != nil { - return errorParsingDocIndex - } +// func updateDoc(inputFile string, updateCommands []yqlib.UpdateCommand, writer io.Writer) error { +// var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() +// if errorParsingDocIndex != nil { +// return errorParsingDocIndex +// } - var updateData = func(dataBucket *yaml.Node, currentIndex int) error { - if updateAll || currentIndex == docIndexInt { - log.Debugf("Updating doc %v", currentIndex) - for _, updateCommand := range updateCommands { - log.Debugf("Processing update to Path %v", updateCommand.Path) - errorUpdating := lib.Update(dataBucket, updateCommand, autoCreateFlag) - if errorUpdating != nil { - return errorUpdating - } - } - } - return nil - } - return readAndUpdate(writer, inputFile, updateData) -} +// var updateData = func(dataBucket *yaml.Node, currentIndex int) error { +// if updateAll || currentIndex == docIndexInt { +// log.Debugf("Updating doc %v", currentIndex) +// for _, updateCommand := range updateCommands { +// log.Debugf("Processing update to Path %v", updateCommand.Path) +// errorUpdating := lib.Update(dataBucket, updateCommand, autoCreateFlag) +// if errorUpdating != nil { +// return errorUpdating +// } +// } +// } +// return nil +// } +// return readAndUpdate(writer, inputFile, updateData) +// } -func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn) error { - var destination io.Writer - var destinationName string - var completedSuccessfully = false - if writeInplace { - info, err := os.Stat(inputFile) - if err != nil { - return err - } - // mkdir temp dir as some docker images does not have temp dir - _, err = os.Stat(os.TempDir()) - if os.IsNotExist(err) { - err = os.Mkdir(os.TempDir(), 0700) - if err != nil { - return err - } - } else if err != nil { - return err - } - tempFile, err := ioutil.TempFile("", "temp") - if err != nil { - return err - } - destinationName = tempFile.Name() - err = os.Chmod(destinationName, info.Mode()) - if err != nil { - return err - } - destination = tempFile - defer func() { - safelyCloseFile(tempFile) - if completedSuccessfully { - safelyRenameFile(tempFile.Name(), inputFile) - } - }() - } else { - destination = stdOut - destinationName = "Stdout" - } +// func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn) error { +// var destination io.Writer +// var destinationName string +// var completedSuccessfully = false +// if writeInplace { +// info, err := os.Stat(inputFile) +// if err != nil { +// return err +// } +// // mkdir temp dir as some docker images does not have temp dir +// _, err = os.Stat(os.TempDir()) +// if os.IsNotExist(err) { +// err = os.Mkdir(os.TempDir(), 0700) +// if err != nil { +// return err +// } +// } else if err != nil { +// return err +// } +// tempFile, err := ioutil.TempFile("", "temp") +// if err != nil { +// return err +// } +// destinationName = tempFile.Name() +// err = os.Chmod(destinationName, info.Mode()) +// if err != nil { +// return err +// } +// destination = tempFile +// defer func() { +// safelyCloseFile(tempFile) +// if completedSuccessfully { +// safelyRenameFile(tempFile.Name(), inputFile) +// } +// }() +// } else { +// destination = stdOut +// destinationName = "Stdout" +// } - log.Debugf("Writing to %v from %v", destinationName, inputFile) +// log.Debugf("Writing to %v from %v", destinationName, inputFile) - bufferedWriter := bufio.NewWriter(destination) - defer safelyFlush(bufferedWriter) +// bufferedWriter := bufio.NewWriter(destination) +// defer safelyFlush(bufferedWriter) - var encoder yqlib.Encoder - if outputToJSON { - encoder = yqlib.NewJsonEncoder(bufferedWriter, prettyPrint, indent) - } else { - encoder = yqlib.NewYamlEncoder(bufferedWriter, indent, colorsEnabled) - } +// var encoder yqlib.Encoder +// if outputToJSON { +// encoder = yqlib.NewJsonEncoder(bufferedWriter, prettyPrint, indent) +// } else { +// encoder = yqlib.NewYamlEncoder(bufferedWriter, indent, colorsEnabled) +// } - var errorProcessing = readStream(inputFile, mapYamlDecoder(updateData, encoder)) - completedSuccessfully = errorProcessing == nil - return errorProcessing -} +// var errorProcessing = readStream(inputFile, mapYamlDecoder(updateData, encoder)) +// completedSuccessfully = errorProcessing == nil +// return errorProcessing +// } type updateCommandParsed struct { Command string @@ -486,53 +486,53 @@ type updateCommandParsed struct { Value yaml.Node } -func readUpdateCommands(args []string, expectedArgs int, badArgsMessage string, allowNoValue bool) ([]yqlib.UpdateCommand, error) { - var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0) - if writeScript != "" { - var parsedCommands = make([]updateCommandParsed, 0) +// func readUpdateCommands(args []string, expectedArgs int, badArgsMessage string, allowNoValue bool) ([]yqlib.UpdateCommand, error) { +// var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0) +// if writeScript != "" { +// var parsedCommands = make([]updateCommandParsed, 0) - err := readData(writeScript, 0, &parsedCommands) +// err := readData(writeScript, 0, &parsedCommands) - if err != nil && err != io.EOF { - return nil, err - } +// if err != nil && err != io.EOF { +// return nil, err +// } - log.Debugf("Read write commands file '%v'", parsedCommands) - for index := range parsedCommands { - parsedCommand := parsedCommands[index] - updateCommand := yqlib.UpdateCommand{Command: parsedCommand.Command, Path: parsedCommand.Path, Value: &parsedCommand.Value, Overwrite: true} - updateCommands = append(updateCommands, updateCommand) - } +// log.Debugf("Read write commands file '%v'", parsedCommands) +// for index := range parsedCommands { +// parsedCommand := parsedCommands[index] +// updateCommand := yqlib.UpdateCommand{Command: parsedCommand.Command, Path: parsedCommand.Path, Value: &parsedCommand.Value, Overwrite: true} +// updateCommands = append(updateCommands, updateCommand) +// } - log.Debugf("Read write commands file '%v'", updateCommands) - } else if sourceYamlFile != "" && len(args) == expectedArgs-1 { - log.Debugf("Reading value from %v", sourceYamlFile) - var value yaml.Node - err := readData(sourceYamlFile, 0, &value) - if err != nil && err != io.EOF { - return nil, err - } - log.Debug("args %v", args[expectedArgs-2]) - updateCommands = make([]yqlib.UpdateCommand, 1) - updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: value.Content[0], Overwrite: true} - } else if len(args) == expectedArgs { - updateCommands = make([]yqlib.UpdateCommand, 1) - log.Debug("args %v", args) - log.Debug("path %v", args[expectedArgs-2]) - log.Debug("Value %v", args[expectedArgs-1]) - value := valueParser.Parse(args[expectedArgs-1], customTag, customStyle, anchorName, makeAlias) - updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: value, Overwrite: true, CommentsMergeStrategy: yqlib.IgnoreCommentsMergeStrategy} - } else if len(args) == expectedArgs-1 && allowNoValue { - // don't update the value - updateCommands = make([]yqlib.UpdateCommand, 1) - log.Debug("args %v", args) - log.Debug("path %v", args[expectedArgs-2]) - updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: valueParser.Parse("", customTag, customStyle, anchorName, makeAlias), Overwrite: true, DontUpdateNodeValue: true} - } else { - return nil, errors.New(badArgsMessage) - } - return updateCommands, nil -} +// log.Debugf("Read write commands file '%v'", updateCommands) +// } else if sourceYamlFile != "" && len(args) == expectedArgs-1 { +// log.Debugf("Reading value from %v", sourceYamlFile) +// var value yaml.Node +// err := readData(sourceYamlFile, 0, &value) +// if err != nil && err != io.EOF { +// return nil, err +// } +// log.Debug("args %v", args[expectedArgs-2]) +// updateCommands = make([]yqlib.UpdateCommand, 1) +// updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: value.Content[0], Overwrite: true} +// } else if len(args) == expectedArgs { +// updateCommands = make([]yqlib.UpdateCommand, 1) +// log.Debug("args %v", args) +// log.Debug("path %v", args[expectedArgs-2]) +// log.Debug("Value %v", args[expectedArgs-1]) +// value := valueParser.Parse(args[expectedArgs-1], customTag, customStyle, anchorName, makeAlias) +// updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: value, Overwrite: true, CommentsMergeStrategy: yqlib.IgnoreCommentsMergeStrategy} +// } else if len(args) == expectedArgs-1 && allowNoValue { +// // don't update the value +// updateCommands = make([]yqlib.UpdateCommand, 1) +// log.Debug("args %v", args) +// log.Debug("path %v", args[expectedArgs-2]) +// updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: valueParser.Parse("", customTag, customStyle, anchorName, makeAlias), Overwrite: true, DontUpdateNodeValue: true} +// } else { +// return nil, errors.New(badArgsMessage) +// } +// return updateCommands, nil +// } func safelyRenameFile(from string, to string) { if renameError := os.Rename(from, to); renameError != nil { diff --git a/cmd/write.go b/cmd/write.go index be14a13..a1c3060 100644 --- a/cmd/write.go +++ b/cmd/write.go @@ -1,61 +1,61 @@ package cmd -import ( - "github.com/spf13/cobra" -) +// import ( +// "github.com/spf13/cobra" +// ) -func createWriteCmd() *cobra.Command { - var cmdWrite = &cobra.Command{ - Use: "write [yaml_file] [path_expression] [value]", - Aliases: []string{"w"}, - Short: "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml 'b.e(name==fr*).value' newValue", - Example: ` -yq write things.yaml 'a.b.c' true -yq write things.yaml 'a.*.c' true -yq write things.yaml 'a.**' true -yq write things.yaml 'a.(child.subchild==co*).c' true -yq write things.yaml 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool -yq write things.yaml 'a.b.c' --tag '!!float' 3 -yq write --inplace -- things.yaml 'a.b.c' '--cat' # need to use '--' to stop processing arguments as flags -yq w -i things.yaml 'a.b.c' cat -yq w -i -s update_script.yaml things.yaml -yq w things.yaml 'a.b.d[+]' foo # appends a new node to the 'd' array -yq w --doc 2 things.yaml 'a.b.d[+]' foo # updates the 3rd document of the yaml file - `, - Long: `Updates the yaml file w.r.t the given path and value. -Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. +// func createWriteCmd() *cobra.Command { +// var cmdWrite = &cobra.Command{ +// Use: "write [yaml_file] [path_expression] [value]", +// Aliases: []string{"w"}, +// Short: "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml 'b.e(name==fr*).value' newValue", +// Example: ` +// yq write things.yaml 'a.b.c' true +// yq write things.yaml 'a.*.c' true +// yq write things.yaml 'a.**' true +// yq write things.yaml 'a.(child.subchild==co*).c' true +// yq write things.yaml 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool +// yq write things.yaml 'a.b.c' --tag '!!float' 3 +// yq write --inplace -- things.yaml 'a.b.c' '--cat' # need to use '--' to stop processing arguments as flags +// yq w -i things.yaml 'a.b.c' cat +// yq w -i -s update_script.yaml things.yaml +// yq w things.yaml 'a.b.d[+]' foo # appends a new node to the 'd' array +// yq w --doc 2 things.yaml 'a.b.d[+]' foo # updates the 3rd document of the yaml file +// `, +// Long: `Updates the yaml file w.r.t the given path and value. +// Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. -Append value to array adds the value to the end of array. +// Append value to array adds the value to the end of array. -Update Scripts: -Note that you can give an update script to perform more sophisticated update. Update script -format is list of update commands (update or delete) like so: ---- -- command: update - path: b.c - value: - #great - things: frog # wow! -- command: delete - path: b.d -`, - RunE: writeProperty, - } - cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") - cmdWrite.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml") - cmdWrite.PersistentFlags().StringVarP(&sourceYamlFile, "from", "f", "", "yaml file for updating yaml (as-is)") - cmdWrite.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)") - cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") - cmdWrite.PersistentFlags().StringVarP(&customStyle, "style", "", "", "formatting style of the value: single, double, folded, flow, literal, tagged") - cmdWrite.PersistentFlags().StringVarP(&anchorName, "anchorName", "", "", "anchor name") - cmdWrite.PersistentFlags().BoolVarP(&makeAlias, "makeAlias", "", false, "create an alias using the value as the anchor name") - return cmdWrite -} +// Update Scripts: +// Note that you can give an update script to perform more sophisticated update. Update script +// format is list of update commands (update or delete) like so: +// --- +// - command: update +// path: b.c +// value: +// #great +// things: frog # wow! +// - command: delete +// path: b.d +// `, +// RunE: writeProperty, +// } +// cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") +// cmdWrite.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml") +// cmdWrite.PersistentFlags().StringVarP(&sourceYamlFile, "from", "f", "", "yaml file for updating yaml (as-is)") +// cmdWrite.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)") +// cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") +// cmdWrite.PersistentFlags().StringVarP(&customStyle, "style", "", "", "formatting style of the value: single, double, folded, flow, literal, tagged") +// cmdWrite.PersistentFlags().StringVarP(&anchorName, "anchorName", "", "", "anchor name") +// cmdWrite.PersistentFlags().BoolVarP(&makeAlias, "makeAlias", "", false, "create an alias using the value as the anchor name") +// return cmdWrite +// } -func writeProperty(cmd *cobra.Command, args []string) error { - var updateCommands, updateCommandsError = readUpdateCommands(args, 3, "Must provide ", true) - if updateCommandsError != nil { - return updateCommandsError - } - return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) -} +// func writeProperty(cmd *cobra.Command, args []string) error { +// var updateCommands, updateCommandsError = readUpdateCommands(args, 3, "Must provide ", true) +// if updateCommandsError != nil { +// return updateCommandsError +// } +// return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) +// } diff --git a/cmd/write_test.go b/cmd/write_test.go index 8249a89..bb1ab67 100644 --- a/cmd/write_test.go +++ b/cmd/write_test.go @@ -1,611 +1,610 @@ package cmd -import ( - "fmt" - "runtime" - "strings" - "testing" - - "github.com/mikefarah/yq/v3/test" -) - -func TestWriteCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("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 TestWriteKeepCommentsCmd(t *testing.T) { - content := `b: - c: 3 # comment -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 7 # comment -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteWithTaggedStyleCmd(t *testing.T) { - content := `b: - c: dog -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --tag=!!str --style=tagged", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: !!str cat -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteWithDoubleQuotedStyleCmd(t *testing.T) { - content := `b: - c: dog -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=double", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: "cat" -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteUpdateStyleOnlyCmd(t *testing.T) { - content := `b: - c: dog - d: things -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* --style=single", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 'dog' - d: 'things' -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteUpdateTagOnlyCmd(t *testing.T) { - content := `b: - c: true - d: false -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* --tag=!!str", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: "true" - d: "false" -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteWithSingleQuotedStyleCmd(t *testing.T) { - content := `b: - c: dog -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=single", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 'cat' -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteWithLiteralStyleCmd(t *testing.T) { - content := `b: - c: dog -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=literal", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: |- - cat -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteWithFoldedStyleCmd(t *testing.T) { - content := `b: - c: dog -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=folded", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: >- - cat -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteEmptyMultiDocCmd(t *testing.T) { - content := `# this is empty ---- -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s c 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `c: 7 - -# this is empty -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteSurroundingEmptyMultiDocCmd(t *testing.T) { - content := `--- -# empty ---- -cat: frog ---- - -# empty -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s -d1 c 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := ` - -# empty ---- -cat: frog -c: 7 ---- - - -# empty -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteFromFileCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - source := `kittens: are cute # sure are!` - fromFilename := test.WriteTempYamlFile(source) - defer test.RemoveTempYamlFile(fromFilename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c -f %s", filename, fromFilename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: - kittens: are cute # sure are! -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteEmptyCmd(t *testing.T) { - content := `` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("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 TestWriteAutoCreateCmd(t *testing.T) { - content := `applications: - - name: app - env:` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s applications[0].env.hello world", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `applications: - - name: app - env: - hello: world -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmdScript(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - updateScript := `- command: update - path: b.c - value: 7` - scriptFilename := test.WriteTempYamlFile(updateScript) - defer test.RemoveTempYamlFile(scriptFilename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 7 -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmdEmptyScript(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - updateScript := `` - scriptFilename := test.WriteTempYamlFile(updateScript) - defer test.RemoveTempYamlFile(scriptFilename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteMultiCmd(t *testing.T) { - content := `b: - c: 3 ---- -apples: great -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 ---- -apples: ok -` - test.AssertResult(t, expectedOutput, result.Output) -} -func TestWriteInvalidDocumentIndexCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s -df apples ok", filename)) - if result.Error == nil { - t.Error("Expected command to fail due to invalid path") - } - expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} - -func TestWriteBadDocumentIndexCmd(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename)) - 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)` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} -func TestWriteMultiAllCmd(t *testing.T) { - content := `b: - c: 3 ---- -apples: great -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s -d * apples ok", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: 3 -apples: ok ---- -apples: ok` - test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) -} - -func TestWriteCmd_EmptyArray(t *testing.T) { - content := `b: 3` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s a []", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: 3 -a: [] -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_Error(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "write") - if result.Error == nil { - t.Error("Expected command to fail due to missing arg") - } - expectedOutput := `Must provide ` - test.AssertResult(t, expectedOutput, result.Error.Error()) -} - -func TestWriteCmd_ErrorUnreadableFile(t *testing.T) { - cmd := getRootCommand() - result := test.RunCmd(cmd, "write fake-unknown a.b 3") - if result.Error == nil { - t.Error("Expected command to fail due to unknown file") - } - var expectedOutput string - if runtime.GOOS == "windows" { - expectedOutput = `open fake-unknown: The system cannot find the file specified.` - } else { - expectedOutput = `open fake-unknown: no such file or directory` - } - test.AssertResult(t, expectedOutput, result.Error.Error()) -} - -func TestWriteCmd_Inplace(t *testing.T) { - content := `b: - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write -i %s b.c 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - gotOutput := test.ReadTempYamlFile(filename) - expectedOutput := `b: - c: 7` - test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n ")) -} - -func TestWriteCmd_InplaceError(t *testing.T) { - content := `b: cat - c: 3 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write -i %s b.c 7", filename)) - if result.Error == nil { - t.Error("Expected Error to occur!") - } - gotOutput := test.ReadTempYamlFile(filename) - test.AssertResult(t, content, gotOutput) -} - -func TestWriteCmd_Append(t *testing.T) { - content := `b: - - foo -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - - foo - - 7 -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_AppendInline(t *testing.T) { - content := `b: [foo]` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: [foo, 7] -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_AppendInlinePretty(t *testing.T) { - content := `b: [foo]` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s -P b[+] 7", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - - foo - - 7 -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_AppendEmptyArray(t *testing.T) { - content := `a: 2 -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] v", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `a: 2 -b: - - v -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_SplatArray(t *testing.T) { - content := `b: -- c: thing -- c: another thing -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b[*].c new", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - - c: new - - c: new -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_SplatMap(t *testing.T) { - content := `b: - c: thing - d: another thing -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* new", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: new - d: new -` - test.AssertResult(t, expectedOutput, result.Output) -} - -func TestWriteCmd_SplatMapEmpty(t *testing.T) { - content := `b: - c: thing - d: another thing -` - filename := test.WriteTempYamlFile(content) - defer test.RemoveTempYamlFile(filename) - - cmd := getRootCommand() - result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c.* new", filename)) - if result.Error != nil { - t.Error(result.Error) - } - expectedOutput := `b: - c: {} - d: another thing -` - test.AssertResult(t, expectedOutput, result.Output) -} +// import ( +// "fmt" +// "runtime" +// "strings" +// "testing" + +// "github.com/mikefarah/yq/v3/test" +// ) + +// func TestWriteCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("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 TestWriteKeepCommentsCmd(t *testing.T) { +// content := `b: +// c: 3 # comment +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 7 # comment +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteWithTaggedStyleCmd(t *testing.T) { +// content := `b: +// c: dog +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --tag=!!str --style=tagged", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: !!str cat +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteWithDoubleQuotedStyleCmd(t *testing.T) { +// content := `b: +// c: dog +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=double", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: "cat" +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteUpdateStyleOnlyCmd(t *testing.T) { +// content := `b: +// c: dog +// d: things +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* --style=single", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 'dog' +// d: 'things' +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteUpdateTagOnlyCmd(t *testing.T) { +// content := `b: +// c: true +// d: false +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* --tag=!!str", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: "true" +// d: "false" +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteWithSingleQuotedStyleCmd(t *testing.T) { +// content := `b: +// c: dog +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=single", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 'cat' +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteWithLiteralStyleCmd(t *testing.T) { +// content := `b: +// c: dog +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=literal", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: |- +// cat +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteWithFoldedStyleCmd(t *testing.T) { +// content := `b: +// c: dog +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=folded", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: >- +// cat +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteEmptyMultiDocCmd(t *testing.T) { +// content := `# this is empty +// --- +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s c 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `c: 7 + +// # this is empty +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteSurroundingEmptyMultiDocCmd(t *testing.T) { +// content := `--- +// # empty +// --- +// cat: frog +// --- + +// # empty +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s -d1 c 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := ` + +// # empty +// --- +// cat: frog +// c: 7 +// --- + +// # empty +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteFromFileCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// source := `kittens: are cute # sure are!` +// fromFilename := test.WriteTempYamlFile(source) +// defer test.RemoveTempYamlFile(fromFilename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c -f %s", filename, fromFilename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: +// kittens: are cute # sure are! +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteEmptyCmd(t *testing.T) { +// content := `` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("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 TestWriteAutoCreateCmd(t *testing.T) { +// content := `applications: +// - name: app +// env:` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s applications[0].env.hello world", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `applications: +// - name: app +// env: +// hello: world +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmdScript(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// updateScript := `- command: update +// path: b.c +// value: 7` +// scriptFilename := test.WriteTempYamlFile(updateScript) +// defer test.RemoveTempYamlFile(scriptFilename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 7 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmdEmptyScript(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// updateScript := `` +// scriptFilename := test.WriteTempYamlFile(updateScript) +// defer test.RemoveTempYamlFile(scriptFilename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteMultiCmd(t *testing.T) { +// content := `b: +// c: 3 +// --- +// apples: great +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// --- +// apples: ok +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } +// func TestWriteInvalidDocumentIndexCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s -df apples ok", filename)) +// if result.Error == nil { +// t.Error("Expected command to fail due to invalid path") +// } +// expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } + +// func TestWriteBadDocumentIndexCmd(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename)) +// 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)` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } +// func TestWriteMultiAllCmd(t *testing.T) { +// content := `b: +// c: 3 +// --- +// apples: great +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s -d * apples ok", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: 3 +// apples: ok +// --- +// apples: ok` +// test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) +// } + +// func TestWriteCmd_EmptyArray(t *testing.T) { +// content := `b: 3` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s a []", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: 3 +// a: [] +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_Error(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "write") +// if result.Error == nil { +// t.Error("Expected command to fail due to missing arg") +// } +// expectedOutput := `Must provide ` +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } + +// func TestWriteCmd_ErrorUnreadableFile(t *testing.T) { +// cmd := getRootCommand() +// result := test.RunCmd(cmd, "write fake-unknown a.b 3") +// if result.Error == nil { +// t.Error("Expected command to fail due to unknown file") +// } +// var expectedOutput string +// if runtime.GOOS == "windows" { +// expectedOutput = `open fake-unknown: The system cannot find the file specified.` +// } else { +// expectedOutput = `open fake-unknown: no such file or directory` +// } +// test.AssertResult(t, expectedOutput, result.Error.Error()) +// } + +// func TestWriteCmd_Inplace(t *testing.T) { +// content := `b: +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write -i %s b.c 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// gotOutput := test.ReadTempYamlFile(filename) +// expectedOutput := `b: +// c: 7` +// test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n ")) +// } + +// func TestWriteCmd_InplaceError(t *testing.T) { +// content := `b: cat +// c: 3 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write -i %s b.c 7", filename)) +// if result.Error == nil { +// t.Error("Expected Error to occur!") +// } +// gotOutput := test.ReadTempYamlFile(filename) +// test.AssertResult(t, content, gotOutput) +// } + +// func TestWriteCmd_Append(t *testing.T) { +// content := `b: +// - foo +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// - foo +// - 7 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_AppendInline(t *testing.T) { +// content := `b: [foo]` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: [foo, 7] +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_AppendInlinePretty(t *testing.T) { +// content := `b: [foo]` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s -P b[+] 7", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// - foo +// - 7 +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_AppendEmptyArray(t *testing.T) { +// content := `a: 2 +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] v", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `a: 2 +// b: +// - v +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_SplatArray(t *testing.T) { +// content := `b: +// - c: thing +// - c: another thing +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b[*].c new", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// - c: new +// - c: new +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_SplatMap(t *testing.T) { +// content := `b: +// c: thing +// d: another thing +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* new", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: new +// d: new +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } + +// func TestWriteCmd_SplatMapEmpty(t *testing.T) { +// content := `b: +// c: thing +// d: another thing +// ` +// filename := test.WriteTempYamlFile(content) +// defer test.RemoveTempYamlFile(filename) + +// cmd := getRootCommand() +// result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c.* new", filename)) +// if result.Error != nil { +// t.Error(result.Error) +// } +// expectedOutput := `b: +// c: {} +// d: another thing +// ` +// test.AssertResult(t, expectedOutput, result.Output) +// } diff --git a/pkg/yqlib/constants.go b/pkg/yqlib/constants.go new file mode 100644 index 0000000..d8c4f7d --- /dev/null +++ b/pkg/yqlib/constants.go @@ -0,0 +1,5 @@ +package yqlib + +import "gopkg.in/op/go-logging.v1" + +var log = logging.MustGetLogger("yq-lib") diff --git a/pkg/yqlib/data_navigator.go b/pkg/yqlib/data_navigator.go deleted file mode 100644 index a7c41c6..0000000 --- a/pkg/yqlib/data_navigator.go +++ /dev/null @@ -1,295 +0,0 @@ -package yqlib - -import ( - "fmt" - "strconv" - - yaml "gopkg.in/yaml.v3" -) - -type DataNavigator interface { - Traverse(value *yaml.Node, path []interface{}) error -} - -type navigator struct { - navigationStrategy NavigationStrategy -} - -func NewDataNavigator(NavigationStrategy NavigationStrategy) DataNavigator { - return &navigator{ - navigationStrategy: NavigationStrategy, - } -} - -func (n *navigator) Traverse(value *yaml.Node, path []interface{}) error { - emptyArray := make([]interface{}, 0) - log.Debugf("Traversing path %v", pathStackToString(path)) - return n.doTraverse(value, "", path, emptyArray) -} - -func (n *navigator) doTraverse(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error { - - log.Debug("head %v", head) - DebugNode(value) - var nodeContext = NewNodeContext(value, head, tail, pathStack) - - var errorDeepSplatting error - // no need to deeply traverse the DocumentNode, as it's already covered by its first child. - if head == "**" && value.Kind != yaml.DocumentNode && value.Kind != yaml.ScalarNode && n.navigationStrategy.ShouldDeeplyTraverse(nodeContext) { - if len(pathStack) == 0 || pathStack[len(pathStack)-1] != "<<" { - errorDeepSplatting = n.recurse(value, head, tail, pathStack) - } - // ignore errors here, we are deep splatting so we may accidently give a string key - // to an array sequence - if len(tail) > 0 { - _ = n.recurse(value, tail[0], tail[1:], pathStack) - } - return errorDeepSplatting - } - - if value.Kind == yaml.DocumentNode { - log.Debugf("its a document, diving into %v", head) - DebugNode(value) - return n.recurse(value, head, tail, pathStack) - } else if len(tail) > 0 && value.Kind != yaml.ScalarNode { - log.Debugf("diving into %v", tail[0]) - DebugNode(value) - return n.recurse(value, tail[0], tail[1:], pathStack) - } - return n.navigationStrategy.Visit(nodeContext) -} - -func (n *navigator) getOrReplace(original *yaml.Node, expectedKind yaml.Kind) *yaml.Node { - if original.Kind != expectedKind { - log.Debug("wanted %v but it was %v, overriding", KindString(expectedKind), KindString(original.Kind)) - return &yaml.Node{Kind: expectedKind} - } - return original -} - -func (n *navigator) recurse(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error { - log.Debug("recursing, processing %v, pathStack %v", head, pathStackToString(pathStack)) - - nodeContext := NewNodeContext(value, head, tail, pathStack) - - if head == "**" && !n.navigationStrategy.ShouldOnlyDeeplyVisitLeaves(nodeContext) { - nodeContext.IsMiddleNode = true - errorVisitingDeeply := n.navigationStrategy.Visit(nodeContext) - if errorVisitingDeeply != nil { - return errorVisitingDeeply - } - } - - switch value.Kind { - case yaml.MappingNode: - log.Debug("its a map with %v entries", len(value.Content)/2) - headString := fmt.Sprintf("%v", head) - return n.recurseMap(value, headString, tail, pathStack) - - case yaml.SequenceNode: - log.Debug("its a sequence of %v things!", len(value.Content)) - - switch head := head.(type) { - case int64: - return n.recurseArray(value, head, head, tail, pathStack) - default: - - if head == "+" { - return n.appendArray(value, head, tail, pathStack) - } else if len(value.Content) == 0 && head == "**" { - return n.navigationStrategy.Visit(nodeContext) - } - return n.splatArray(value, head, tail, pathStack) - } - case yaml.AliasNode: - log.Debug("its an alias!") - DebugNode(value.Alias) - if n.navigationStrategy.FollowAlias(nodeContext) { - log.Debug("following the alias") - return n.recurse(value.Alias, head, tail, pathStack) - } - return nil - case yaml.DocumentNode: - return n.doTraverse(value.Content[0], head, tail, pathStack) - default: - return n.navigationStrategy.Visit(nodeContext) - } -} - -func (n *navigator) recurseMap(value *yaml.Node, head string, tail []interface{}, pathStack []interface{}) error { - traversedEntry := false - errorVisiting := n.visitMatchingEntries(value, head, tail, pathStack, func(contents []*yaml.Node, indexInMap int) error { - log.Debug("recurseMap: visitMatchingEntries for %v", contents[indexInMap].Value) - n.navigationStrategy.DebugVisitedNodes() - newPathStack := append(pathStack, contents[indexInMap].Value) - log.Debug("should I traverse? head: %v, path: %v", head, pathStackToString(newPathStack)) - DebugNode(value) - if n.navigationStrategy.ShouldTraverse(NewNodeContext(contents[indexInMap+1], head, tail, newPathStack), contents[indexInMap].Value) { - log.Debug("recurseMap: Going to traverse") - traversedEntry = true - contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(head, tail, contents[indexInMap+1].Kind)) - errorTraversing := n.doTraverse(contents[indexInMap+1], head, tail, newPathStack) - log.Debug("recurseMap: Finished traversing") - n.navigationStrategy.DebugVisitedNodes() - return errorTraversing - } else { - log.Debug("nope not traversing") - } - return nil - }) - - if errorVisiting != nil { - return errorVisiting - } - - if len(value.Content) == 0 && head == "**" { - return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack)) - } else if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) { - return nil - } - - _, errorParsingInt := strconv.ParseInt(head, 10, 64) - - mapEntryKey := yaml.Node{Value: head, Kind: yaml.ScalarNode} - - if errorParsingInt == nil { - // fixes a json encoding problem where keys that look like numbers - // get treated as numbers and cannot be used in a json map - mapEntryKey.Style = yaml.LiteralStyle - } - - value.Content = append(value.Content, &mapEntryKey) - mapEntryValue := yaml.Node{Kind: guessKind(head, tail, 0)} - value.Content = append(value.Content, &mapEntryValue) - log.Debug("adding a new node %v - def a string", head) - return n.doTraverse(&mapEntryValue, head, tail, append(pathStack, head)) -} - -// need to pass the node in, as it may be aliased -type mapVisitorFn func(contents []*yaml.Node, index int) error - -func (n *navigator) visitDirectMatchingEntries(node *yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error { - var contents = node.Content - for index := 0; index < len(contents); index = index + 2 { - content := contents[index] - - log.Debug("index %v, checking %v, %v", index, content.Value, content.Tag) - n.navigationStrategy.DebugVisitedNodes() - errorVisiting := visit(contents, index) - if errorVisiting != nil { - return errorVisiting - } - } - return nil -} - -func (n *navigator) visitMatchingEntries(node *yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error { - var contents = node.Content - log.Debug("visitMatchingEntries %v", head) - DebugNode(node) - // value.Content is a concatenated array of key, value, - // so keys are in the even indexes, values in odd. - // merge aliases are defined first, but we only want to traverse them - // if we don't find a match directly on this node first. - errorVisitedDirectEntries := n.visitDirectMatchingEntries(node, head, tail, pathStack, visit) - - if errorVisitedDirectEntries != nil || !n.navigationStrategy.FollowAlias(NewNodeContext(node, head, tail, pathStack)) { - return errorVisitedDirectEntries - } - return n.visitAliases(contents, head, tail, pathStack, visit) -} - -func (n *navigator) visitAliases(contents []*yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error { - // merge aliases are defined first, but we only want to traverse them - // if we don't find a match on this node first. - // traverse them backwards so that the last alias overrides the preceding. - // a node can either be - // an alias to one other node (e.g. <<: *blah) - // or a sequence of aliases (e.g. <<: [*blah, *foo]) - log.Debug("checking for aliases, head: %v, pathstack: %v", head, pathStackToString(pathStack)) - for index := len(contents) - 2; index >= 0; index = index - 2 { - - if contents[index+1].Kind == yaml.AliasNode && contents[index].Value == "<<" { - valueNode := contents[index+1] - log.Debug("found an alias") - DebugNode(contents[index]) - DebugNode(valueNode) - - errorInAlias := n.visitMatchingEntries(valueNode.Alias, head, tail, pathStack, visit) - if errorInAlias != nil { - return errorInAlias - } - } else if contents[index+1].Kind == yaml.SequenceNode { - // could be an array of aliases... - errorVisitingAliasSeq := n.visitAliasSequence(contents[index+1].Content, head, tail, pathStack, visit) - if errorVisitingAliasSeq != nil { - return errorVisitingAliasSeq - } - } - } - return nil -} - -func (n *navigator) visitAliasSequence(possibleAliasArray []*yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error { - // need to search this backwards too, so that aliases defined last override the preceding. - for aliasIndex := len(possibleAliasArray) - 1; aliasIndex >= 0; aliasIndex = aliasIndex - 1 { - child := possibleAliasArray[aliasIndex] - if child.Kind == yaml.AliasNode { - log.Debug("found an alias") - DebugNode(child) - errorInAlias := n.visitMatchingEntries(child.Alias, head, tail, pathStack, visit) - if errorInAlias != nil { - return errorInAlias - } - } - } - return nil -} - -func (n *navigator) splatArray(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error { - for index, childValue := range value.Content { - log.Debug("processing") - DebugNode(childValue) - childValue = n.getOrReplace(childValue, guessKind(head, tail, childValue.Kind)) - - newPathStack := append(pathStack, index) - if n.navigationStrategy.ShouldTraverse(NewNodeContext(childValue, head, tail, newPathStack), childValue.Value) { - // here we should not deeply traverse the array if we are appending..not sure how to do that. - // need to visit instead... - // easiest way is to pop off the head and pass the rest of the tail in. - var err = n.doTraverse(childValue, head, tail, newPathStack) - if err != nil { - return err - } - } - } - return nil -} - -func (n *navigator) appendArray(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error { - var newNode = yaml.Node{Kind: guessKind(head, tail, 0)} - value.Content = append(value.Content, &newNode) - log.Debug("appending a new node, %v", value.Content) - return n.doTraverse(&newNode, head, tail, append(pathStack, len(value.Content)-1)) -} - -func (n *navigator) recurseArray(value *yaml.Node, index int64, head interface{}, tail []interface{}, pathStack []interface{}) error { - var contentLength = int64(len(value.Content)) - for contentLength <= index { - value.Content = append(value.Content, &yaml.Node{Kind: guessKind(head, tail, 0)}) - contentLength = int64(len(value.Content)) - } - var indexToUse = index - - if indexToUse < 0 { - indexToUse = contentLength + indexToUse - } - - if indexToUse < 0 { - return fmt.Errorf("Index [%v] out of range, array size is %v", index, contentLength) - } - - value.Content[indexToUse] = n.getOrReplace(value.Content[indexToUse], guessKind(head, tail, value.Content[indexToUse].Kind)) - - return n.doTraverse(value.Content[indexToUse], head, tail, append(pathStack, index)) -} diff --git a/pkg/yqlib/data_navigator_test.go b/pkg/yqlib/data_navigator_test.go deleted file mode 100644 index 88c44e9..0000000 --- a/pkg/yqlib/data_navigator_test.go +++ /dev/null @@ -1 +0,0 @@ -package yqlib diff --git a/pkg/yqlib/delete_navigation_strategy.go b/pkg/yqlib/delete_navigation_strategy.go deleted file mode 100644 index a0792c3..0000000 --- a/pkg/yqlib/delete_navigation_strategy.go +++ /dev/null @@ -1,73 +0,0 @@ -package yqlib - -import ( - yaml "gopkg.in/yaml.v3" -) - -func DeleteNavigationStrategy(pathElementToDelete interface{}) NavigationStrategy { - parser := NewPathParser() - return &NavigationStrategyImpl{ - visitedNodes: []*NodeContext{}, - pathParser: parser, - followAlias: func(nodeContext NodeContext) bool { - return false - }, - shouldOnlyDeeplyVisitLeaves: func(nodeContext NodeContext) bool { - return false - }, - visit: func(nodeContext NodeContext) error { - node := nodeContext.Node - log.Debug("need to find and delete %v in here (%v)", pathElementToDelete, pathStackToString(nodeContext.PathStack)) - DebugNode(node) - if node.Kind == yaml.SequenceNode { - newContent := deleteFromArray(parser, node.Content, nodeContext.PathStack, pathElementToDelete) - node.Content = newContent - } else if node.Kind == yaml.MappingNode { - node.Content = deleteFromMap(parser, node.Content, nodeContext.PathStack, pathElementToDelete) - } - return nil - }, - } -} -func deleteFromMap(pathParser PathParser, contents []*yaml.Node, pathStack []interface{}, pathElementToDelete interface{}) []*yaml.Node { - newContents := make([]*yaml.Node, 0) - for index := 0; index < len(contents); index = index + 2 { - keyNode := contents[index] - valueNode := contents[index+1] - if !pathParser.MatchesNextPathElement(NewNodeContext(keyNode, pathElementToDelete, make([]interface{}, 0), pathStack), keyNode.Value) { - log.Debug("adding node %v", keyNode.Value) - newContents = append(newContents, keyNode, valueNode) - } else { - log.Debug("skipping node %v", keyNode.Value) - } - } - return newContents -} - -func deleteFromArray(pathParser PathParser, content []*yaml.Node, pathStack []interface{}, pathElementToDelete interface{}) []*yaml.Node { - - switch pathElementToDelete := pathElementToDelete.(type) { - case int64: - return deleteIndexInArray(content, pathElementToDelete) - default: - log.Debug("%v is not a numeric index, finding matching patterns", pathElementToDelete) - var newArray = make([]*yaml.Node, 0) - - for _, childValue := range content { - if !pathParser.MatchesNextPathElement(NewNodeContext(childValue, pathElementToDelete, make([]interface{}, 0), pathStack), childValue.Value) { - newArray = append(newArray, childValue) - } - } - return newArray - } - -} - -func deleteIndexInArray(content []*yaml.Node, index int64) []*yaml.Node { - log.Debug("deleting index %v in array", index) - if index >= int64(len(content)) { - log.Debug("index %v is greater than content length %v", index, len(content)) - return content - } - return append(content[:index], content[index+1:]...) -} diff --git a/pkg/yqlib/filter_matching_node_navigation_strategy.go b/pkg/yqlib/filter_matching_node_navigation_strategy.go deleted file mode 100644 index 4c15c4f..0000000 --- a/pkg/yqlib/filter_matching_node_navigation_strategy.go +++ /dev/null @@ -1,15 +0,0 @@ -package yqlib - -func FilterMatchingNodesNavigationStrategy(value string) NavigationStrategy { - return &NavigationStrategyImpl{ - visitedNodes: []*NodeContext{}, - pathParser: NewPathParser(), - visit: func(nodeContext NodeContext) error { - return nil - }, - shouldVisitExtraFn: func(nodeContext NodeContext) bool { - log.Debug("does %v match %v ? %v", nodeContext.Node.Value, value, nodeContext.Node.Value == value) - return matchesString(value, nodeContext.Node.Value) - }, - } -} diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go deleted file mode 100644 index 3f548f6..0000000 --- a/pkg/yqlib/lib.go +++ /dev/null @@ -1,208 +0,0 @@ -package yqlib - -import ( - "bytes" - "fmt" - "strconv" - "strings" - - logging "gopkg.in/op/go-logging.v1" - yaml "gopkg.in/yaml.v3" -) - -var log = logging.MustGetLogger("yq") - -type UpdateCommand struct { - Command string - Path string - Value *yaml.Node - Overwrite bool - DontUpdateNodeValue bool - DontUpdateNodeContent bool - CommentsMergeStrategy CommentsMergeStrategy -} - -func KindString(kind yaml.Kind) string { - switch kind { - case yaml.ScalarNode: - return "ScalarNode" - case yaml.SequenceNode: - return "SequenceNode" - case yaml.MappingNode: - return "MappingNode" - case yaml.DocumentNode: - return "DocumentNode" - case yaml.AliasNode: - return "AliasNode" - default: - return "unknown!" - } -} - -func DebugNode(value *yaml.Node) { - if value == nil { - log.Debug("-- node is nil --") - } else if log.IsEnabledFor(logging.DEBUG) { - buf := new(bytes.Buffer) - encoder := yaml.NewEncoder(buf) - errorEncoding := encoder.Encode(value) - if errorEncoding != nil { - log.Error("Error debugging node, %v", errorEncoding.Error()) - } - encoder.Close() - log.Debug("Tag: %v, Kind: %v, Anchor: %v", value.Tag, KindString(value.Kind), value.Anchor) - log.Debug("Head Comment: %v", value.HeadComment) - log.Debug("Line Comment: %v", value.LineComment) - log.Debug("FootComment Comment: %v", value.FootComment) - log.Debug("\n%v", buf.String()) - } -} - -func pathStackToString(pathStack []interface{}) string { - return mergePathStackToString(pathStack, UpdateArrayMergeStrategy) -} - -func mergePathStackToString(pathStack []interface{}, arrayMergeStrategy ArrayMergeStrategy) string { - var sb strings.Builder - for index, path := range pathStack { - switch path.(type) { - case int, int64: - if arrayMergeStrategy == AppendArrayMergeStrategy { - sb.WriteString("[+]") - } else { - sb.WriteString(fmt.Sprintf("[%v]", path)) - } - - default: - s := fmt.Sprintf("%v", path) - var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint - - hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"") - hasDoubleQuotes := strings.Contains(s, "\"") - wrappingCharacterStart := "\"" - wrappingCharacterEnd := "\"" - if hasDoubleQuotes { - wrappingCharacterStart = "(" - wrappingCharacterEnd = ")" - } - if hasSpecial || errParsingInt == nil { - sb.WriteString(wrappingCharacterStart) - } - sb.WriteString(s) - if hasSpecial || errParsingInt == nil { - sb.WriteString(wrappingCharacterEnd) - } - } - - if index < len(pathStack)-1 { - sb.WriteString(".") - } - } - return sb.String() -} - -func guessKind(head interface{}, tail []interface{}, guess yaml.Kind) yaml.Kind { - log.Debug("guessKind: tail %v", tail) - if len(tail) == 0 && guess == 0 { - log.Debug("end of path, must be a scalar") - return yaml.ScalarNode - } else if len(tail) == 0 { - return guess - } - var next = tail[0] - switch next.(type) { - case int64: - return yaml.SequenceNode - default: - var nextString = fmt.Sprintf("%v", next) - if nextString == "+" { - return yaml.SequenceNode - } - pathParser := NewPathParser() - if pathParser.IsPathExpression(nextString) && (guess == yaml.SequenceNode || guess == yaml.MappingNode) { - return guess - } else if guess == yaml.AliasNode { - log.Debug("guess was an alias, okey doke.") - return guess - } else if head == "**" { - log.Debug("deep wildcard, go with the guess") - return guess - } - log.Debug("forcing a mapping node") - log.Debug("yaml.SequenceNode %v", guess == yaml.SequenceNode) - log.Debug("yaml.ScalarNode %v", guess == yaml.ScalarNode) - return yaml.MappingNode - } -} - -type YqLib interface { - Get(rootNode *yaml.Node, path string) ([]*NodeContext, error) - GetForMerge(rootNode *yaml.Node, path string, arrayMergeStrategy ArrayMergeStrategy) ([]*NodeContext, error) - Update(rootNode *yaml.Node, updateCommand UpdateCommand, autoCreate bool) error - New(path string) yaml.Node - - PathStackToString(pathStack []interface{}) string - MergePathStackToString(pathStack []interface{}, arrayMergeStrategy ArrayMergeStrategy) string -} - -type lib struct { - parser PathParser -} - -func NewYqLib() YqLib { - return &lib{ - parser: NewPathParser(), - } -} - -func (l *lib) Get(rootNode *yaml.Node, path string) ([]*NodeContext, error) { - var paths = l.parser.ParsePath(path) - navigationStrategy := ReadNavigationStrategy() - navigator := NewDataNavigator(navigationStrategy) - error := navigator.Traverse(rootNode, paths) - return navigationStrategy.GetVisitedNodes(), error -} - -func (l *lib) GetForMerge(rootNode *yaml.Node, path string, arrayMergeStrategy ArrayMergeStrategy) ([]*NodeContext, error) { - var paths = l.parser.ParsePath(path) - navigationStrategy := ReadForMergeNavigationStrategy(arrayMergeStrategy) - navigator := NewDataNavigator(navigationStrategy) - error := navigator.Traverse(rootNode, paths) - return navigationStrategy.GetVisitedNodes(), error -} - -func (l *lib) PathStackToString(pathStack []interface{}) string { - return pathStackToString(pathStack) -} - -func (l *lib) MergePathStackToString(pathStack []interface{}, arrayMergeStrategy ArrayMergeStrategy) string { - return mergePathStackToString(pathStack, arrayMergeStrategy) -} - -func (l *lib) New(path string) yaml.Node { - var paths = l.parser.ParsePath(path) - newNode := yaml.Node{Kind: guessKind("", paths, 0)} - return newNode -} - -func (l *lib) Update(rootNode *yaml.Node, updateCommand UpdateCommand, autoCreate bool) error { - log.Debugf("%v to %v", updateCommand.Command, updateCommand.Path) - switch updateCommand.Command { - case "update": - var paths = l.parser.ParsePath(updateCommand.Path) - navigator := NewDataNavigator(UpdateNavigationStrategy(updateCommand, autoCreate)) - return navigator.Traverse(rootNode, paths) - case "merge": - var paths = l.parser.ParsePath(updateCommand.Path) - navigator := NewDataNavigator(MergeNavigationStrategy(updateCommand, autoCreate)) - return navigator.Traverse(rootNode, paths) - case "delete": - var paths = l.parser.ParsePath(updateCommand.Path) - lastBit, newTail := paths[len(paths)-1], paths[:len(paths)-1] - navigator := NewDataNavigator(DeleteNavigationStrategy(lastBit)) - return navigator.Traverse(rootNode, newTail) - default: - return fmt.Errorf("Unknown command %v", updateCommand.Command) - } - -} diff --git a/pkg/yqlib/lib_test.go b/pkg/yqlib/lib_test.go deleted file mode 100644 index 52e7933..0000000 --- a/pkg/yqlib/lib_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package yqlib - -import ( - "testing" - - "github.com/mikefarah/yq/v3/test" -) - -func TestLib(t *testing.T) { - - subject := NewYqLib() - - t.Run("PathStackToString_Empty", func(t *testing.T) { - emptyArray := make([]interface{}, 0) - got := subject.PathStackToString(emptyArray) - test.AssertResult(t, ``, got) - }) - - t.Run("PathStackToString", func(t *testing.T) { - array := make([]interface{}, 3) - array[0] = "a" - array[1] = 0 - array[2] = "b" - got := subject.PathStackToString(array) - test.AssertResult(t, `a.[0].b`, got) - }) - - t.Run("MergePathStackToString", func(t *testing.T) { - array := make([]interface{}, 3) - array[0] = "a" - array[1] = 0 - array[2] = "b" - got := subject.MergePathStackToString(array, AppendArrayMergeStrategy) - test.AssertResult(t, `a.[+].b`, got) - }) - - // t.Run("TestReadPath_WithError", func(t *testing.T) { - // var data = test.ParseData(` - // --- - // b: - // - c - // `) - - // _, err := subject.ReadPath(data, "b.[a]") - // if err == nil { - // t.Fatal("Expected error due to invalid path") - // } - // }) - - // t.Run("TestWritePath", func(t *testing.T) { - // var data = test.ParseData(` - // --- - // b: - // 2: c - // `) - - // got := subject.WritePath(data, "b.3", "a") - // test.AssertResult(t, `[{b [{2 c} {3 a}]}]`, fmt.Sprintf("%v", got)) - // }) - - // t.Run("TestPrefixPath", func(t *testing.T) { - // var data = test.ParseData(` - // --- - // b: - // 2: c - // `) - - // got := subject.PrefixPath(data, "a.d") - // test.AssertResult(t, `[{a [{d [{b [{2 c}]}]}]}]`, fmt.Sprintf("%v", got)) - // }) - - // t.Run("TestDeletePath", func(t *testing.T) { - // var data = test.ParseData(` - // --- - // b: - // 2: c - // 3: a - // `) - - // got, _ := subject.DeletePath(data, "b.2") - // test.AssertResult(t, `[{b [{3 a}]}]`, fmt.Sprintf("%v", got)) - // }) - - // t.Run("TestDeletePath_WithError", func(t *testing.T) { - // var data = test.ParseData(` - // --- - // b: - // - c - // `) - - // _, err := subject.DeletePath(data, "b.[a]") - // if err == nil { - // t.Fatal("Expected error due to invalid path") - // } - // }) - - // t.Run("TestMerge", func(t *testing.T) { - // var dst = test.ParseData(` - // --- - // a: b - // c: d - // `) - // var src = test.ParseData(` - // --- - // a: 1 - // b: 2 - // `) - - // var mergedData = make(map[interface{}]interface{}) - // mergedData["root"] = dst - // var mapDataBucket = make(map[interface{}]interface{}) - // mapDataBucket["root"] = src - - // err := subject.Merge(&mergedData, mapDataBucket, false, false) - // if err != nil { - // t.Fatal("Unexpected error") - // } - // test.AssertResult(t, `[{a b} {c d}]`, fmt.Sprintf("%v", mergedData["root"])) - // }) - - // t.Run("TestMerge_WithOverwrite", func(t *testing.T) { - // var dst = test.ParseData(` - // --- - // a: b - // c: d - // `) - // var src = test.ParseData(` - // --- - // a: 1 - // b: 2 - // `) - - // var mergedData = make(map[interface{}]interface{}) - // mergedData["root"] = dst - // var mapDataBucket = make(map[interface{}]interface{}) - // mapDataBucket["root"] = src - - // err := subject.Merge(&mergedData, mapDataBucket, true, false) - // if err != nil { - // t.Fatal("Unexpected error") - // } - // test.AssertResult(t, `[{a 1} {b 2}]`, fmt.Sprintf("%v", mergedData["root"])) - // }) - - // t.Run("TestMerge_WithAppend", func(t *testing.T) { - // var dst = test.ParseData(` - // --- - // a: b - // c: d - // `) - // var src = test.ParseData(` - // --- - // a: 1 - // b: 2 - // `) - - // var mergedData = make(map[interface{}]interface{}) - // mergedData["root"] = dst - // var mapDataBucket = make(map[interface{}]interface{}) - // mapDataBucket["root"] = src - - // err := subject.Merge(&mergedData, mapDataBucket, false, true) - // if err != nil { - // t.Fatal("Unexpected error") - // } - // test.AssertResult(t, `[{a b} {c d} {a 1} {b 2}]`, fmt.Sprintf("%v", mergedData["root"])) - // }) - - // t.Run("TestMerge_WithError", func(t *testing.T) { - // err := subject.Merge(nil, nil, false, false) - // if err == nil { - // t.Fatal("Expected error due to nil") - // } - // }) - -} diff --git a/pkg/yqlib/merge_navigation_strategy.go b/pkg/yqlib/merge_navigation_strategy.go deleted file mode 100644 index 686ba4e..0000000 --- a/pkg/yqlib/merge_navigation_strategy.go +++ /dev/null @@ -1,103 +0,0 @@ -package yqlib - -import "gopkg.in/yaml.v3" - -type ArrayMergeStrategy uint32 - -const ( - UpdateArrayMergeStrategy ArrayMergeStrategy = 1 << iota - OverwriteArrayMergeStrategy - AppendArrayMergeStrategy -) - -type CommentsMergeStrategy uint32 - -const ( - SetWhenBlankCommentsMergeStrategy CommentsMergeStrategy = 1 << iota - IgnoreCommentsMergeStrategy - OverwriteCommentsMergeStrategy - AppendCommentsMergeStrategy -) - -func MergeNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy { - return &NavigationStrategyImpl{ - visitedNodes: []*NodeContext{}, - pathParser: NewPathParser(), - followAlias: func(nodeContext NodeContext) bool { - return false - }, - autoCreateMap: func(nodeContext NodeContext) bool { - return autoCreate - }, - visit: func(nodeContext NodeContext) error { - node := nodeContext.Node - changesToApply := updateCommand.Value - - if node.Kind == yaml.DocumentNode && changesToApply.Kind != yaml.DocumentNode { - // when the path is empty, it matches both the top level pseudo document node - // and the actual top level node (e.g. map/sequence/whatever) - // so when we are updating with no path, make sure we update the right node. - node = node.Content[0] - } - - log.Debug("going to update") - DebugNode(node) - log.Debug("with") - DebugNode(changesToApply) - - if updateCommand.Overwrite || node.Value == "" { - node.Value = changesToApply.Value - node.Tag = changesToApply.Tag - node.Kind = changesToApply.Kind - node.Style = changesToApply.Style - node.Anchor = changesToApply.Anchor - node.Alias = changesToApply.Alias - - if !updateCommand.DontUpdateNodeContent { - node.Content = changesToApply.Content - } - } else { - 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 - }, - } -} diff --git a/pkg/yqlib/navigation_strategy.go b/pkg/yqlib/navigation_strategy.go deleted file mode 100644 index e88641d..0000000 --- a/pkg/yqlib/navigation_strategy.go +++ /dev/null @@ -1,180 +0,0 @@ -package yqlib - -import ( - "fmt" - - yaml "gopkg.in/yaml.v3" -) - -type NodeContext struct { - Node *yaml.Node - Head interface{} - Tail []interface{} - PathStack []interface{} - // middle nodes are nodes that match along the original path, but not a - // target match of the path. This is only relevant when ShouldOnlyDeeplyVisitLeaves is false. - IsMiddleNode bool -} - -func NewNodeContext(node *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) NodeContext { - newTail := make([]interface{}, len(tail)) - copy(newTail, tail) - - newPathStack := make([]interface{}, len(pathStack)) - copy(newPathStack, pathStack) - return NodeContext{ - Node: node, - Head: head, - Tail: newTail, - PathStack: newPathStack, - } -} - -type NavigationStrategy interface { - FollowAlias(nodeContext NodeContext) bool - AutoCreateMap(nodeContext NodeContext) bool - Visit(nodeContext NodeContext) error - // node key is the string value of the last element in the path stack - // we use it to match against the pathExpression in head. - ShouldTraverse(nodeContext NodeContext, nodeKey string) bool - ShouldDeeplyTraverse(nodeContext NodeContext) bool - // when deeply traversing, should we visit all matching nodes, or just leaves? - ShouldOnlyDeeplyVisitLeaves(NodeContext) bool - GetVisitedNodes() []*NodeContext - DebugVisitedNodes() - GetPathParser() PathParser -} - -type NavigationStrategyImpl struct { - followAlias func(nodeContext NodeContext) bool - autoCreateMap func(nodeContext NodeContext) bool - visit func(nodeContext NodeContext) error - shouldVisitExtraFn func(nodeContext NodeContext) bool - shouldDeeplyTraverse func(nodeContext NodeContext) bool - shouldOnlyDeeplyVisitLeaves func(nodeContext NodeContext) bool - visitedNodes []*NodeContext - pathParser PathParser -} - -func (ns *NavigationStrategyImpl) GetPathParser() PathParser { - return ns.pathParser -} - -func (ns *NavigationStrategyImpl) GetVisitedNodes() []*NodeContext { - return ns.visitedNodes -} - -func (ns *NavigationStrategyImpl) FollowAlias(nodeContext NodeContext) bool { - if ns.followAlias != nil { - return ns.followAlias(nodeContext) - } - return true -} - -func (ns *NavigationStrategyImpl) AutoCreateMap(nodeContext NodeContext) bool { - if ns.autoCreateMap != nil { - return ns.autoCreateMap(nodeContext) - } - return false -} - -func (ns *NavigationStrategyImpl) ShouldDeeplyTraverse(nodeContext NodeContext) bool { - if ns.shouldDeeplyTraverse != nil { - return ns.shouldDeeplyTraverse(nodeContext) - } - return true -} - -func (ns *NavigationStrategyImpl) ShouldOnlyDeeplyVisitLeaves(nodeContext NodeContext) bool { - if ns.shouldOnlyDeeplyVisitLeaves != nil { - return ns.shouldOnlyDeeplyVisitLeaves(nodeContext) - } - return true - -} - -func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKey string) bool { - // we should traverse aliases (if enabled), but not visit them :/ - if len(nodeContext.PathStack) == 0 { - return true - } - - if ns.alreadyVisited(nodeContext.PathStack) { - return false - } - - return (nodeKey == "<<" && ns.FollowAlias(nodeContext)) || (nodeKey != "<<" && - ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey)) -} - -func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool { - pathStack := nodeContext.PathStack - if len(pathStack) == 0 { - return true - } - log.Debug("tail len %v", len(nodeContext.Tail)) - - if ns.alreadyVisited(pathStack) || len(nodeContext.Tail) != 0 { - return false - } - - nodeKey := fmt.Sprintf("%v", pathStack[len(pathStack)-1]) - log.Debug("nodeKey: %v, nodeContext.Head: %v", nodeKey, nodeContext.Head) - - // only visit aliases if its an exact match - return ((nodeKey == "<<" && nodeContext.Head == "<<") || (nodeKey != "<<" && - ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext)) -} - -func (ns *NavigationStrategyImpl) Visit(nodeContext NodeContext) error { - log.Debug("Visit?, %v, %v", nodeContext.Head, pathStackToString(nodeContext.PathStack)) - DebugNode(nodeContext.Node) - if ns.shouldVisit(nodeContext) { - log.Debug("yep, visiting") - // pathStack array must be - // copied, as append() may sometimes reuse and modify the array - ns.visitedNodes = append(ns.visitedNodes, &nodeContext) - ns.DebugVisitedNodes() - return ns.visit(nodeContext) - } - log.Debug("nope, skip it") - return nil -} - -func (ns *NavigationStrategyImpl) DebugVisitedNodes() { - log.Debug("Visited Nodes:") - for _, candidate := range ns.visitedNodes { - log.Debug(" - %v", pathStackToString(candidate.PathStack)) - } -} - -func (ns *NavigationStrategyImpl) alreadyVisited(pathStack []interface{}) bool { - log.Debug("checking already visited pathStack: %v", pathStackToString(pathStack)) - for _, candidate := range ns.visitedNodes { - candidatePathStack := candidate.PathStack - if patchStacksMatch(candidatePathStack, pathStack) { - log.Debug("paths match, already seen it") - return true - } - - } - log.Debug("never seen it before!") - return false -} - -func patchStacksMatch(path1 []interface{}, path2 []interface{}) bool { - log.Debug("checking against path: %v", pathStackToString(path1)) - - if len(path1) != len(path2) { - return false - } - for index, p1Value := range path1 { - - p2Value := path2[index] - if p1Value != p2Value { - return false - } - } - return true - -} diff --git a/pkg/yqlib/path_parser.go b/pkg/yqlib/path_parser.go deleted file mode 100644 index 4e51899..0000000 --- a/pkg/yqlib/path_parser.go +++ /dev/null @@ -1,153 +0,0 @@ -package yqlib - -import ( - "fmt" - "strconv" - "strings" - - yaml "gopkg.in/yaml.v3" -) - -type PathParser interface { - ParsePath(path string) []interface{} - MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool - IsPathExpression(pathElement string) bool -} - -type pathParser struct{} - -func NewPathParser() PathParser { - return &pathParser{} -} - -func matchesString(expression string, value string) bool { - var prefixMatch = strings.TrimSuffix(expression, "*") - if prefixMatch != expression { - log.Debug("prefix match, %v", strings.HasPrefix(value, prefixMatch)) - return strings.HasPrefix(value, prefixMatch) - } - return value == expression -} - -func (p *pathParser) IsPathExpression(pathElement string) bool { - return pathElement == "*" || pathElement == "**" || strings.Contains(pathElement, "==") -} - -/** - * node: node that we may traverse/visit - * head: path element expression to match against - * tail: remaining path element expressions - * pathStack: stack of actual paths we've matched to get to node - * nodeKey: actual value of this nodes 'key' or index. - */ -func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool { - head := nodeContext.Head - if head == "**" || head == "*" { - return true - } - var headString = fmt.Sprintf("%v", head) - - if strings.Contains(headString, "==") && nodeContext.Node.Kind != yaml.ScalarNode { - log.Debug("ooh deep recursion time") - result := strings.SplitN(headString, "==", 2) - path := strings.TrimSpace(result[0]) - value := strings.TrimSpace(result[1]) - log.Debug("path %v", path) - log.Debug("value %v", value) - DebugNode(nodeContext.Node) - navigationStrategy := FilterMatchingNodesNavigationStrategy(value) - - navigator := NewDataNavigator(navigationStrategy) - err := navigator.Traverse(nodeContext.Node, p.ParsePath(path)) - if err != nil { - log.Error("Error deep recursing - ignoring") - log.Error(err.Error()) - } - log.Debug("done deep recursing, found %v matches", len(navigationStrategy.GetVisitedNodes())) - return len(navigationStrategy.GetVisitedNodes()) > 0 - } else if strings.Contains(headString, "==") && nodeContext.Node.Kind == yaml.ScalarNode { - result := strings.SplitN(headString, "==", 2) - path := strings.TrimSpace(result[0]) - value := strings.TrimSpace(result[1]) - if path == "." { - log.Debug("need to match scalar") - return matchesString(value, nodeContext.Node.Value) - } - } - - if head == "+" { - log.Debug("head is +, nodeKey is %v", nodeKey) - var _, err = strconv.ParseInt(nodeKey, 10, 64) // nolint - if err == nil { - return true - } - } - - return matchesString(headString, nodeKey) -} - -func (p *pathParser) ParsePath(path string) []interface{} { - var paths = make([]interface{}, 0) - if path == "" { - return paths - } - return p.parsePathAccum(paths, path) -} - -func (p *pathParser) parsePathAccum(paths []interface{}, remaining string) []interface{} { - head, tail := p.nextYamlPath(remaining) - if tail == "" { - return append(paths, head) - } - return p.parsePathAccum(append(paths, head), tail) -} - -func (p *pathParser) nextYamlPath(path string) (pathElement interface{}, remaining string) { - switch path[0] { - case '[': - // e.g [0].blah.cat -> we need to return "0" and "blah.cat" - var value, remainingBit = p.search(path[1:], []uint8{']'}, true) - var number, errParsingInt = strconv.ParseInt(value, 10, 64) // nolint - if errParsingInt == nil { - return number, remainingBit - } - return value, remainingBit - case '"': - // e.g "a.b".blah.cat -> we need to return "a.b" and "blah.cat" - return p.search(path[1:], []uint8{'"'}, true) - case '(': - // e.g "a.b".blah.cat -> we need to return "a.b" and "blah.cat" - return p.search(path[1:], []uint8{')'}, true) - default: - // e.g "a.blah.cat" -> return "a" and "blah.cat" - return p.search(path[0:], []uint8{'.', '[', '"', '('}, false) - } -} - -func (p *pathParser) search(path string, matchingChars []uint8, skipNext bool) (pathElement string, remaining string) { - for i := 0; i < len(path); i++ { - var char = path[i] - if p.contains(matchingChars, char) { - var remainingStart = i + 1 - if skipNext { - remainingStart = remainingStart + 1 - } else if !skipNext && char != '.' { - remainingStart = i - } - if remainingStart > len(path) { - remainingStart = len(path) - } - return path[0:i], path[remainingStart:] - } - } - return path, "" -} - -func (p *pathParser) contains(matchingChars []uint8, candidate uint8) bool { - for _, a := range matchingChars { - if a == candidate { - return true - } - } - return false -} diff --git a/pkg/yqlib/path_parser_test.go b/pkg/yqlib/path_parser_test.go deleted file mode 100644 index 7af1266..0000000 --- a/pkg/yqlib/path_parser_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package yqlib - -import ( - "testing" - - "github.com/mikefarah/yq/v3/test" -) - -var parser = NewPathParser() - -var parsePathsTests = []struct { - path string - expectedPaths []interface{} -}{ - {"a.b", append(make([]interface{}, 0), "a", "b")}, - {"a.b.**", append(make([]interface{}, 0), "a", "b", "**")}, - {"a.b.*", append(make([]interface{}, 0), "a", "b", "*")}, - {"a.b[0]", append(make([]interface{}, 0), "a", "b", int64(0))}, - {"a.b.0", append(make([]interface{}, 0), "a", "b", "0")}, - {"a.b.d[+]", append(make([]interface{}, 0), "a", "b", "d", "+")}, - {"a", append(make([]interface{}, 0), "a")}, - {"a.b.c", append(make([]interface{}, 0), "a", "b", "c")}, - {"\"a.b\".c", append(make([]interface{}, 0), "a.b", "c")}, - {"a.\"b.c\".d", append(make([]interface{}, 0), "a", "b.c", "d")}, - {"[1].a.d", append(make([]interface{}, 0), int64(1), "a", "d")}, - {"a[0].c", append(make([]interface{}, 0), "a", int64(0), "c")}, - {"[0]", append(make([]interface{}, 0), int64(0))}, -} - -func TestPathParserParsePath(t *testing.T) { - for _, tt := range parsePathsTests { - test.AssertResultComplex(t, tt.expectedPaths, parser.ParsePath(tt.path)) - } -} - -func TestPathParserMatchesNextPathElementSplat(t *testing.T) { - var node = NodeContext{Head: "*"} - test.AssertResult(t, true, parser.MatchesNextPathElement(node, "")) -} - -func TestPathParserMatchesNextPathElementDeepSplat(t *testing.T) { - var node = NodeContext{Head: "**"} - test.AssertResult(t, true, parser.MatchesNextPathElement(node, "")) -} - -func TestPathParserMatchesNextPathElementAppendArrayValid(t *testing.T) { - var node = NodeContext{Head: "+"} - test.AssertResult(t, true, parser.MatchesNextPathElement(node, "3")) -} - -func TestPathParserMatchesNextPathElementAppendArrayInvalid(t *testing.T) { - var node = NodeContext{Head: "+"} - test.AssertResult(t, false, parser.MatchesNextPathElement(node, "cat")) -} - -func TestPathParserMatchesNextPathElementPrefixMatchesWhole(t *testing.T) { - var node = NodeContext{Head: "cat*"} - test.AssertResult(t, true, parser.MatchesNextPathElement(node, "cat")) -} - -func TestPathParserMatchesNextPathElementPrefixMatchesStart(t *testing.T) { - var node = NodeContext{Head: "cat*"} - test.AssertResult(t, true, parser.MatchesNextPathElement(node, "caterpillar")) -} - -func TestPathParserMatchesNextPathElementPrefixMismatch(t *testing.T) { - var node = NodeContext{Head: "cat*"} - test.AssertResult(t, false, parser.MatchesNextPathElement(node, "dog")) -} - -func TestPathParserMatchesNextPathElementExactMatch(t *testing.T) { - var node = NodeContext{Head: "farahtek"} - test.AssertResult(t, true, parser.MatchesNextPathElement(node, "farahtek")) -} - -func TestPathParserMatchesNextPathElementExactMismatch(t *testing.T) { - var node = NodeContext{Head: "farahtek"} - test.AssertResult(t, false, parser.MatchesNextPathElement(node, "othertek")) -} diff --git a/pkg/yqlib/read_for_merge_navigation_strategy.go b/pkg/yqlib/read_for_merge_navigation_strategy.go deleted file mode 100644 index 7306133..0000000 --- a/pkg/yqlib/read_for_merge_navigation_strategy.go +++ /dev/null @@ -1,37 +0,0 @@ -package yqlib - -import "gopkg.in/yaml.v3" - -func ReadForMergeNavigationStrategy(arrayMergeStrategy ArrayMergeStrategy) NavigationStrategy { - return &NavigationStrategyImpl{ - visitedNodes: []*NodeContext{}, - pathParser: NewPathParser(), - followAlias: func(nodeContext NodeContext) bool { - return false - }, - shouldOnlyDeeplyVisitLeaves: func(nodeContext NodeContext) bool { - return false - }, - visit: func(nodeContext NodeContext) error { - return nil - }, - shouldDeeplyTraverse: func(nodeContext NodeContext) bool { - if nodeContext.Node.Kind == yaml.SequenceNode && arrayMergeStrategy == OverwriteArrayMergeStrategy { - nodeContext.IsMiddleNode = false - return false - } - - var isInArray = false - if len(nodeContext.PathStack) > 0 { - var lastElement = nodeContext.PathStack[len(nodeContext.PathStack)-1] - switch lastElement.(type) { - case int: - isInArray = true - default: - isInArray = false - } - } - return arrayMergeStrategy == UpdateArrayMergeStrategy || !isInArray - }, - } -} diff --git a/pkg/yqlib/read_navigation_strategy.go b/pkg/yqlib/read_navigation_strategy.go deleted file mode 100644 index ba29e94..0000000 --- a/pkg/yqlib/read_navigation_strategy.go +++ /dev/null @@ -1,11 +0,0 @@ -package yqlib - -func ReadNavigationStrategy() NavigationStrategy { - return &NavigationStrategyImpl{ - visitedNodes: []*NodeContext{}, - pathParser: NewPathParser(), - visit: func(nodeContext NodeContext) error { - return nil - }, - } -} diff --git a/pkg/yqlib/treeops/candidate_node.go b/pkg/yqlib/treeops/candidate_node.go new file mode 100644 index 0000000..1357689 --- /dev/null +++ b/pkg/yqlib/treeops/candidate_node.go @@ -0,0 +1,62 @@ +package treeops + +import ( + "fmt" + "strconv" + "strings" + + "gopkg.in/yaml.v3" +) + +type CandidateNode struct { + Node *yaml.Node // the actual node + Path []interface{} /// the path we took to get to this node + Document uint // the document index of this node +} + +func (n *CandidateNode) GetKey() string { + return fmt.Sprintf("%v - %v", n.Document, n.Path) +} + +func (n *CandidateNode) PathStackToString() string { + return mergePathStackToString(n.Path) +} + +func mergePathStackToString(pathStack []interface{}) string { + var sb strings.Builder + for index, path := range pathStack { + switch path.(type) { + case int, int64: + // if arrayMergeStrategy == AppendArrayMergeStrategy { + // sb.WriteString("[+]") + // } else { + sb.WriteString(fmt.Sprintf("[%v]", path)) + // } + + default: + s := fmt.Sprintf("%v", path) + var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint + + hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"") + hasDoubleQuotes := strings.Contains(s, "\"") + wrappingCharacterStart := "\"" + wrappingCharacterEnd := "\"" + if hasDoubleQuotes { + wrappingCharacterStart = "(" + wrappingCharacterEnd = ")" + } + if hasSpecial || errParsingInt == nil { + sb.WriteString(wrappingCharacterStart) + } + sb.WriteString(s) + if hasSpecial || errParsingInt == nil { + sb.WriteString(wrappingCharacterEnd) + } + } + + if index < len(pathStack)-1 { + sb.WriteString(".") + } + } + return sb.String() +} diff --git a/pkg/yqlib/treeops/data_tree_navigator.go b/pkg/yqlib/treeops/data_tree_navigator.go index 1a33c1e..a5cfaaa 100644 --- a/pkg/yqlib/treeops/data_tree_navigator.go +++ b/pkg/yqlib/treeops/data_tree_navigator.go @@ -35,7 +35,7 @@ func (d *dataTreeNavigator) traverse(matchMap *orderedmap.OrderedMap, pathNode * return nil, err } for _, n := range newNodes { - matchingNodeMap.Set(n.getKey(), n) + matchingNodeMap.Set(n.GetKey(), n) } } @@ -46,7 +46,7 @@ func (d *dataTreeNavigator) GetMatchingNodes(matchingNodes []*CandidateNode, pat var matchingNodeMap = orderedmap.NewOrderedMap() for _, n := range matchingNodes { - matchingNodeMap.Set(n.getKey(), n) + matchingNodeMap.Set(n.GetKey(), n) } matchedNodes, err := d.getMatchingNodes(matchingNodeMap, pathNode) @@ -63,6 +63,10 @@ func (d *dataTreeNavigator) GetMatchingNodes(matchingNodes []*CandidateNode, pat } func (d *dataTreeNavigator) getMatchingNodes(matchingNodes *orderedmap.OrderedMap, pathNode *PathTreeNode) (*orderedmap.OrderedMap, error) { + if pathNode == nil { + log.Debugf("getMatchingNodes - nothing to do") + return matchingNodes, nil + } log.Debugf("Processing Path: %v", pathNode.PathElement.toString()) if pathNode.PathElement.PathElementType == SelfReference { return matchingNodes, nil diff --git a/pkg/yqlib/treeops/delete_operator.go b/pkg/yqlib/treeops/delete_operator.go index c86354a..c80479b 100644 --- a/pkg/yqlib/treeops/delete_operator.go +++ b/pkg/yqlib/treeops/delete_operator.go @@ -17,7 +17,7 @@ func DeleteChildOperator(d *dataTreeNavigator, matchingNodes *orderedmap.Ordered for el := lhs.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) elMap := orderedmap.NewOrderedMap() - elMap.Set(candidate.getKey(), candidate) + elMap.Set(candidate.GetKey(), candidate) nodesToDelete, err := d.getMatchingNodes(elMap, pathNode.Rhs) log.Debug("nodesToDelete:\n%v", NodesToString(nodesToDelete)) if err != nil { @@ -50,9 +50,9 @@ func deleteFromMap(candidate *CandidateNode, nodesToDelete *orderedmap.OrderedMa Document: candidate.Document, Path: append(candidate.Path, key.Value), } - _, shouldDelete := nodesToDelete.Get(childCandidate.getKey()) + _, shouldDelete := nodesToDelete.Get(childCandidate.GetKey()) - log.Debugf("shouldDelete %v ? %v", childCandidate.getKey(), shouldDelete) + log.Debugf("shouldDelete %v ? %v", childCandidate.GetKey(), shouldDelete) if !shouldDelete { newContents = append(newContents, key, value) @@ -76,7 +76,7 @@ func deleteFromArray(candidate *CandidateNode, nodesToDelete *orderedmap.Ordered Path: append(candidate.Path, index), } - _, shouldDelete := nodesToDelete.Get(childCandidate.getKey()) + _, shouldDelete := nodesToDelete.Get(childCandidate.GetKey()) if !shouldDelete { newContents = append(newContents, value) } diff --git a/pkg/yqlib/treeops/lib.go b/pkg/yqlib/treeops/lib.go index 0ec9f27..f52319a 100644 --- a/pkg/yqlib/treeops/lib.go +++ b/pkg/yqlib/treeops/lib.go @@ -11,16 +11,6 @@ import ( var log = logging.MustGetLogger("yq-treeops") -type CandidateNode struct { - Node *yaml.Node // the actual node - Path []interface{} /// the path we took to get to this node - Document uint // the document index of this node -} - -func (n *CandidateNode) getKey() string { - return fmt.Sprintf("%v - %v", n.Document, n.Path) -} - type PathElementType uint32 const ( @@ -76,7 +66,7 @@ func (p *PathElement) toString() string { } type YqTreeLib interface { - Get(rootNode *yaml.Node, path string) ([]*CandidateNode, error) + Get(document int, documentNode *yaml.Node, path string) ([]*CandidateNode, error) // GetForMerge(rootNode *yaml.Node, path string, arrayMergeStrategy ArrayMergeStrategy) ([]*NodeContext, error) // Update(rootNode *yaml.Node, updateCommand UpdateCommand, autoCreate bool) error // New(path string) yaml.Node @@ -85,10 +75,24 @@ type YqTreeLib interface { // MergePathStackToString(pathStack []interface{}, arrayMergeStrategy ArrayMergeStrategy) string } +func NewYqTreeLib() YqTreeLib { + return &lib{treeCreator: NewPathTreeCreator()} +} + type lib struct { treeCreator PathTreeCreator } +func (l *lib) Get(document int, documentNode *yaml.Node, path string) ([]*CandidateNode, error) { + nodes := []*CandidateNode{&CandidateNode{Node: documentNode.Content[0], Document: 0}} + navigator := NewDataTreeNavigator(NavigationPrefs{}) + pathNode, errPath := l.treeCreator.ParsePath(path) + if errPath != nil { + return nil, errPath + } + return navigator.GetMatchingNodes(nodes, pathNode) +} + //use for debugging only func NodesToString(collection *orderedmap.OrderedMap) string { if !log.IsEnabledFor(logging.DEBUG) { diff --git a/pkg/yqlib/treeops/operators.go b/pkg/yqlib/treeops/operators.go index b6042ce..16eabce 100644 --- a/pkg/yqlib/treeops/operators.go +++ b/pkg/yqlib/treeops/operators.go @@ -24,7 +24,7 @@ func AssignOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, } for el := lhs.Front(); el != nil; el = el.Next() { node := el.Value.(*CandidateNode) - log.Debugf("Assiging %v to %v", node.getKey(), pathNode.Rhs.PathElement.StringValue) + log.Debugf("Assiging %v to %v", node.GetKey(), pathNode.Rhs.PathElement.StringValue) node.Node.Value = pathNode.Rhs.PathElement.StringValue } return lhs, nil @@ -41,7 +41,7 @@ func UnionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.OrderedMap, p } for el := rhs.Front(); el != nil; el = el.Next() { node := el.Value.(*CandidateNode) - lhs.Set(node.getKey(), node) + lhs.Set(node.GetKey(), node) } return lhs, nil } @@ -67,7 +67,7 @@ func IntersectionOperator(d *dataTreeNavigator, matchingNodes *orderedmap.Ordere func splatNode(d *dataTreeNavigator, candidate *CandidateNode) (*orderedmap.OrderedMap, error) { elMap := orderedmap.NewOrderedMap() - elMap.Set(candidate.getKey(), candidate) + elMap.Set(candidate.GetKey(), candidate) //need to splat matching nodes, then search through them splatter := &PathTreeNode{PathElement: &PathElement{ PathElementType: PathKey, @@ -112,7 +112,7 @@ func CountOperator(d *dataTreeNavigator, matchMap *orderedmap.OrderedMap, pathNo length := childMatches.Len() node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"} lengthCand := &CandidateNode{Node: node, Document: candidate.Document, Path: candidate.Path} - results.Set(candidate.getKey(), lengthCand) + results.Set(candidate.GetKey(), lengthCand) } @@ -131,7 +131,7 @@ func findMatchingChildren(d *dataTreeNavigator, results *orderedmap.OrderedMap, } } else { children = orderedmap.NewOrderedMap() - children.Set(candidate.getKey(), candidate) + children.Set(candidate.GetKey(), candidate) } for childEl := children.Front(); childEl != nil; childEl = childEl.Next() { diff --git a/pkg/yqlib/treeops/path_tree.go b/pkg/yqlib/treeops/path_tree.go index fe1353f..3ca09e3 100644 --- a/pkg/yqlib/treeops/path_tree.go +++ b/pkg/yqlib/treeops/path_tree.go @@ -39,6 +39,10 @@ func (p *pathTreeCreator) ParsePath(path string) (*PathTreeNode, error) { func (p *pathTreeCreator) CreatePathTree(postFixPath []*PathElement) (*PathTreeNode, error) { var stack = make([]*PathTreeNode, 0) + if len(postFixPath) == 0 { + return nil, nil + } + for _, pathElement := range postFixPath { var newNode = PathTreeNode{PathElement: pathElement} if pathElement.PathElementType == Operation { diff --git a/pkg/yqlib/update_navigation_strategy.go b/pkg/yqlib/update_navigation_strategy.go deleted file mode 100644 index b5b0e75..0000000 --- a/pkg/yqlib/update_navigation_strategy.go +++ /dev/null @@ -1,43 +0,0 @@ -package yqlib - -func UpdateNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy { - return &NavigationStrategyImpl{ - visitedNodes: []*NodeContext{}, - pathParser: NewPathParser(), - followAlias: func(nodeContext NodeContext) bool { - return false - }, - autoCreateMap: func(nodeContext NodeContext) bool { - return autoCreate - }, - visit: func(nodeContext NodeContext) error { - node := nodeContext.Node - changesToApply := updateCommand.Value - if updateCommand.Overwrite || node.Value == "" { - log.Debug("going to update") - DebugNode(node) - log.Debug("with") - DebugNode(changesToApply) - if !updateCommand.DontUpdateNodeValue { - node.Value = changesToApply.Value - } - node.Tag = changesToApply.Tag - node.Kind = changesToApply.Kind - node.Style = changesToApply.Style - if !updateCommand.DontUpdateNodeContent { - node.Content = changesToApply.Content - } - node.Anchor = changesToApply.Anchor - node.Alias = changesToApply.Alias - if updateCommand.CommentsMergeStrategy != IgnoreCommentsMergeStrategy { - node.HeadComment = changesToApply.HeadComment - node.LineComment = changesToApply.LineComment - node.FootComment = changesToApply.FootComment - } - } else { - log.Debug("skipping update as node already has value %v and overwriteFlag is ", node.Value, updateCommand.Overwrite) - } - return nil - }, - } -}