mirror of
https://github.com/taigrr/yq
synced 2025-01-18 04:53:17 -08:00
first cli
This commit is contained in:
@@ -1,83 +1,83 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
// import (
|
||||
// "strings"
|
||||
// "testing"
|
||||
|
||||
"github.com/mikefarah/yq/v3/test"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
// "github.com/mikefarah/yq/v3/test"
|
||||
// "github.com/spf13/cobra"
|
||||
// )
|
||||
|
||||
func getRootCommand() *cobra.Command {
|
||||
return New()
|
||||
}
|
||||
// func getRootCommand() *cobra.Command {
|
||||
// return New()
|
||||
// }
|
||||
|
||||
func TestRootCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
// func TestRootCmd(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "")
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
if !strings.Contains(result.Output, "Usage:") {
|
||||
t.Error("Expected usage message to be printed out, but the usage message was not found.")
|
||||
}
|
||||
}
|
||||
// if !strings.Contains(result.Output, "Usage:") {
|
||||
// t.Error("Expected usage message to be printed out, but the usage message was not found.")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestRootCmd_Help(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "--help")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
// func TestRootCmd_Help(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "--help")
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
if !strings.Contains(result.Output, "yq is a lightweight and portable command-line YAML processor. It aims to be the jq or sed of yaml files.") {
|
||||
t.Error("Expected usage message to be printed out, but the usage message was not found.")
|
||||
}
|
||||
}
|
||||
// if !strings.Contains(result.Output, "yq is a lightweight and portable command-line YAML processor. It aims to be the jq or sed of yaml files.") {
|
||||
// t.Error("Expected usage message to be printed out, but the usage message was not found.")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestRootCmd_VerboseLong(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "--verbose")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
// func TestRootCmd_VerboseLong(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "--verbose")
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
if !verbose {
|
||||
t.Error("Expected verbose to be true")
|
||||
}
|
||||
}
|
||||
// if !verbose {
|
||||
// t.Error("Expected verbose to be true")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestRootCmd_VerboseShort(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "-v")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
// func TestRootCmd_VerboseShort(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "-v")
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
if !verbose {
|
||||
t.Error("Expected verbose to be true")
|
||||
}
|
||||
}
|
||||
// if !verbose {
|
||||
// t.Error("Expected verbose to be true")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestRootCmd_VersionShort(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "-V")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
if !strings.Contains(result.Output, "yq version") {
|
||||
t.Error("expected version message to be printed out, but the message was not found.")
|
||||
}
|
||||
}
|
||||
// func TestRootCmd_VersionShort(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "-V")
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
// if !strings.Contains(result.Output, "yq version") {
|
||||
// t.Error("expected version message to be printed out, but the message was not found.")
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestRootCmd_VersionLong(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "--version")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
if !strings.Contains(result.Output, "yq version") {
|
||||
t.Error("expected version message to be printed out, but the message was not found.")
|
||||
}
|
||||
}
|
||||
// func TestRootCmd_VersionLong(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "--version")
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
// if !strings.Contains(result.Output, "yq version") {
|
||||
// t.Error("expected version message to be printed out, but the message was not found.")
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// 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"
|
||||
// )
|
||||
|
||||
// // 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 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]
|
||||
// }
|
||||
|
||||
// var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||
// if errorParsingDocIndex != nil {
|
||||
// return errorParsingDocIndex
|
||||
// }
|
||||
|
||||
// var matchingNodesA []*yqlib.NodeContext
|
||||
// var matchingNodesB []*yqlib.NodeContext
|
||||
// var errorDoingThings error
|
||||
|
||||
// matchingNodesA, errorDoingThings = readYamlFile(args[0], 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
|
||||
// }
|
||||
|
||||
// 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
|
||||
// }
|
||||
@@ -1,115 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// import (
|
||||
// "testing"
|
||||
|
||||
// "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 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")
|
||||
|
||||
// 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 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
@@ -1,8 +1,6 @@
|
||||
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"
|
||||
)
|
||||
|
||||
@@ -14,7 +12,6 @@ var customStyle = ""
|
||||
var anchorName = ""
|
||||
var makeAlias = false
|
||||
var stripComments = false
|
||||
var collectIntoArray = false
|
||||
var writeInplace = false
|
||||
var writeScript = ""
|
||||
var sourceYamlFile = ""
|
||||
@@ -22,6 +19,8 @@ var outputToJSON = false
|
||||
var exitStatus = false
|
||||
var prettyPrint = false
|
||||
var explodeAnchors = false
|
||||
var forceColor = false
|
||||
var forceNoColor = false
|
||||
var colorsEnabled = false
|
||||
var defaultValue = ""
|
||||
var indent = 2
|
||||
@@ -31,7 +30,5 @@ var arrayMergeStrategyFlag = "update"
|
||||
var commentsMergeStrategyFlag = "setWhenBlank"
|
||||
var verbose = false
|
||||
var version = false
|
||||
var docIndex = "0"
|
||||
var shellCompletion = ""
|
||||
var log = logging.MustGetLogger("yq")
|
||||
var lib = treeops.NewYqTreeLib()
|
||||
var valueParser = yqlib.NewValueParser()
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// 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 deleteProperty(cmd *cobra.Command, args []string) error {
|
||||
// if len(args) < 2 {
|
||||
// return errors.New("Must provide <filename> <path_to_delete>")
|
||||
// }
|
||||
// var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 1)
|
||||
// updateCommands[0] = yqlib.UpdateCommand{Command: "delete", Path: args[1]}
|
||||
|
||||
// return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
|
||||
// }
|
||||
@@ -1,246 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "strings"
|
||||
// "testing"
|
||||
|
||||
// "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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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 "))
|
||||
// }
|
||||
124
cmd/merge.go
124
cmd/merge.go
@@ -1,124 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// 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.
|
||||
|
||||
// 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)
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
|
||||
// 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:]
|
||||
|
||||
// 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())
|
||||
// }
|
||||
@@ -1,551 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "os"
|
||||
// "runtime"
|
||||
// "testing"
|
||||
|
||||
// "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 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 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)
|
||||
|
||||
// mergeContent := `c:
|
||||
// test: 5
|
||||
// `
|
||||
// mergeFilename := test.WriteTempYamlFile(mergeContent)
|
||||
// defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, fmt.Sprintf("merge --autocreate=false --overwrite %s %s", filename, mergeFilename))
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
// expectedOutput := `c:
|
||||
// test: 5
|
||||
// thing: whatever
|
||||
// `
|
||||
// test.AssertResult(t, expectedOutput, result.Output)
|
||||
// }
|
||||
|
||||
// func TestMergeAppendCmd(t *testing.T) {
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, "merge --autocreate=false --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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
|
||||
// mergeContent := `
|
||||
// vars:
|
||||
// variable2: &var2 puppy
|
||||
|
||||
// usage:
|
||||
// value2: *var2
|
||||
// valueAnother: *var2
|
||||
// valuePlain: *var2
|
||||
// `
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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 commentContentB = `
|
||||
// a: valueA2 # commentA2
|
||||
// b: valueB2 # commentB2
|
||||
// c: valueC2 # commentC2
|
||||
// `
|
||||
|
||||
// func TestMergeCommentsSetWhenBlankCmd(t *testing.T) {
|
||||
// filename := test.WriteTempYamlFile(commentContentA)
|
||||
// defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
// mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||
// defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=setWhenBlank %s %s", filename, mergeFilename))
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
// expectedOutput := `a: valueA1 # commentA1
|
||||
// b: valueB1 # commentB2
|
||||
// c: valueC2 # commentC2
|
||||
// `
|
||||
// test.AssertResult(t, expectedOutput, result.Output)
|
||||
// }
|
||||
|
||||
// func TestMergeCommentsIgnoreCmd(t *testing.T) {
|
||||
// filename := test.WriteTempYamlFile(commentContentA)
|
||||
// defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
// mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||
// defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=ignore %s %s", filename, mergeFilename))
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
// expectedOutput := `a: valueA1 # commentA1
|
||||
// b: valueB1
|
||||
// c: valueC2
|
||||
// `
|
||||
// test.AssertResult(t, expectedOutput, result.Output)
|
||||
// }
|
||||
|
||||
// func TestMergeCommentsAppendCmd(t *testing.T) {
|
||||
// filename := test.WriteTempYamlFile(commentContentA)
|
||||
// defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
// mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||
// defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=append %s %s", filename, mergeFilename))
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
// expectedOutput := `a: valueA1 # commentA1 # commentA2
|
||||
// b: valueB1 # commentB2
|
||||
// c: valueC2 # commentC2
|
||||
// `
|
||||
// test.AssertResult(t, expectedOutput, result.Output)
|
||||
// }
|
||||
|
||||
// func TestMergeCommentsOverwriteCmd(t *testing.T) {
|
||||
// filename := test.WriteTempYamlFile(commentContentA)
|
||||
// defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
// mergeFilename := test.WriteTempYamlFile(commentContentB)
|
||||
// defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, fmt.Sprintf("merge --comments=overwrite %s %s", filename, mergeFilename))
|
||||
// if result.Error != nil {
|
||||
// t.Error(result.Error)
|
||||
// }
|
||||
|
||||
// expectedOutput := `a: valueA1 # commentA2
|
||||
// b: valueB1 # commentB2
|
||||
// c: valueC2 # commentC2
|
||||
// `
|
||||
// test.AssertResult(t, expectedOutput, result.Output)
|
||||
// }
|
||||
|
||||
// func TestMergeOverwriteArraysTooCmd(t *testing.T) {
|
||||
// content := `a: simple # just the best
|
||||
// b: [1, 2]
|
||||
// c:
|
||||
// test: 1
|
||||
// `
|
||||
// filename := test.WriteTempYamlFile(content)
|
||||
// defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
// mergeContent := `a: things
|
||||
// b: [6]`
|
||||
// mergeFilename := test.WriteTempYamlFile(mergeContent)
|
||||
// defer test.RemoveTempYamlFile(mergeFilename)
|
||||
|
||||
// cmd := getRootCommand()
|
||||
// result := test.RunCmd(cmd, fmt.Sprintf("merge --autocreate=false --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)
|
||||
// }
|
||||
|
||||
// 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 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 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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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_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())
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
55
cmd/new.go
55
cmd/new.go
@@ -1,55 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// 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
|
||||
|
||||
// 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 <path_to_update> <value>"
|
||||
// var updateCommands, updateCommandsError = readUpdateCommands(args, 2, badArgsMessage, false)
|
||||
// if updateCommandsError != nil {
|
||||
// return updateCommandsError
|
||||
// }
|
||||
// newNode := lib.New(updateCommands[0].Path)
|
||||
|
||||
// for _, updateCommand := range updateCommands {
|
||||
|
||||
// errorUpdating := lib.Update(&newNode, updateCommand, true)
|
||||
|
||||
// if errorUpdating != nil {
|
||||
// return errorUpdating
|
||||
// }
|
||||
// }
|
||||
|
||||
// var encoder = yqlib.NewYamlEncoder(cmd.OutOrStdout(), indent, colorsEnabled)
|
||||
// return encoder.Encode(&newNode)
|
||||
// }
|
||||
120
cmd/new_test.go
120
cmd/new_test.go
@@ -1,120 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "testing"
|
||||
|
||||
// "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 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)
|
||||
// }
|
||||
|
||||
// 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 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 <path_to_update> <value>`
|
||||
// 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 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)
|
||||
// }
|
||||
@@ -1,50 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// 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 prefixProperty(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// if len(args) < 2 {
|
||||
// return errors.New("Must provide <filename> <prefixed_path>")
|
||||
// }
|
||||
// updateCommand := yqlib.UpdateCommand{Command: "update", Path: args[1]}
|
||||
// log.Debugf("args %v", args)
|
||||
|
||||
// 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)
|
||||
// }
|
||||
@@ -1,189 +0,0 @@
|
||||
package cmd
|
||||
|
||||
// import (
|
||||
// "fmt"
|
||||
// "runtime"
|
||||
// "strings"
|
||||
// "testing"
|
||||
|
||||
// "github.com/mikefarah/yq/v3/test"
|
||||
// )
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// 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 -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)
|
||||
|
||||
// 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 "))
|
||||
// }
|
||||
|
||||
// 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 <filename> <prefixed_path>`
|
||||
// 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)
|
||||
|
||||
// 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 "))
|
||||
// }
|
||||
65
cmd/read.go
65
cmd/read.go
@@ -1,65 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
errors "github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func createReadCmd() *cobra.Command {
|
||||
var cmdRead = &cobra.Command{
|
||||
Use: "read [yaml_file] [path_expression]",
|
||||
Aliases: []string{"r"},
|
||||
Short: "yq r [--printMode/-p pv] sample.yaml 'b.e(name==fr*).value'",
|
||||
Example: `
|
||||
yq read things.yaml 'a.b.c'
|
||||
yq r - 'a.b.c' # reads from stdin
|
||||
yq r things.yaml 'a.*.c'
|
||||
yq r things.yaml 'a.**.c' # deep splat
|
||||
yq r things.yaml 'a.(child.subchild==co*).c'
|
||||
yq r -d1 things.yaml 'a.array[0].blah'
|
||||
yq r things.yaml 'a.array[*].blah'
|
||||
yq r -- things.yaml '--key-starting-with-dashes.blah'
|
||||
`,
|
||||
Long: "Outputs the value of the given path in the yaml file to STDOUT",
|
||||
RunE: readProperty,
|
||||
}
|
||||
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(&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")
|
||||
cmdRead.PersistentFlags().BoolVarP(&explodeAnchors, "explodeAnchors", "X", false, "explode anchors")
|
||||
cmdRead.PersistentFlags().BoolVarP(&exitStatus, "exitStatus", "e", false, "set exit status if no matches are found")
|
||||
return cmdRead
|
||||
}
|
||||
|
||||
func readProperty(cmd *cobra.Command, args []string) error {
|
||||
var path = ""
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Must provide filename")
|
||||
} else if len(args) > 1 {
|
||||
path = args[1]
|
||||
}
|
||||
|
||||
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||
if errorParsingDocIndex != nil {
|
||||
return errorParsingDocIndex
|
||||
}
|
||||
|
||||
matchingNodes, errorReadingStream := readYamlFile(args[0], path, updateAll, docIndexInt)
|
||||
|
||||
if exitStatus && len(matchingNodes) == 0 {
|
||||
cmd.SilenceUsage = true
|
||||
return errors.New("No matches found")
|
||||
}
|
||||
|
||||
if errorReadingStream != nil {
|
||||
cmd.SilenceUsage = true
|
||||
return errorReadingStream
|
||||
}
|
||||
out := cmd.OutOrStdout()
|
||||
|
||||
return printResults(matchingNodes, out)
|
||||
}
|
||||
1463
cmd/read_test.go
1463
cmd/read_test.go
File diff suppressed because it is too large
Load Diff
70
cmd/root.go
70
cmd/root.go
@@ -1,8 +1,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib/treeops"
|
||||
"github.com/spf13/cobra"
|
||||
logging "gopkg.in/op/go-logging.v1"
|
||||
)
|
||||
@@ -17,9 +20,51 @@ func New() *cobra.Command {
|
||||
cmd.Print(GetVersionDisplay())
|
||||
return nil
|
||||
}
|
||||
cmd.Println(cmd.UsageString())
|
||||
if shellCompletion != "" {
|
||||
switch shellCompletion {
|
||||
case "bash", "":
|
||||
return cmd.GenBashCompletion(os.Stdout)
|
||||
case "zsh":
|
||||
return cmd.GenZshCompletion(os.Stdout)
|
||||
case "fish":
|
||||
return cmd.GenFishCompletion(os.Stdout, true)
|
||||
case "powershell":
|
||||
return cmd.GenPowerShellCompletion(os.Stdout)
|
||||
default:
|
||||
return fmt.Errorf("Unknown variant %v", shellCompletion)
|
||||
}
|
||||
}
|
||||
// if len(args) == 0 {
|
||||
// cmd.Println(cmd.UsageString())
|
||||
// return nil
|
||||
// }
|
||||
cmd.SilenceUsage = true
|
||||
|
||||
return nil
|
||||
var treeCreator = treeops.NewPathTreeCreator()
|
||||
|
||||
expression := ""
|
||||
if len(args) > 0 {
|
||||
expression = args[0]
|
||||
}
|
||||
|
||||
pathNode, err := treeCreator.ParsePath(expression)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
matchingNodes, err := evaluate("-", pathNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if exitStatus && matchingNodes.Len() == 0 {
|
||||
cmd.SilenceUsage = true
|
||||
return errors.New("No matches found")
|
||||
}
|
||||
|
||||
out := cmd.OutOrStdout()
|
||||
|
||||
return printResults(matchingNodes, out)
|
||||
},
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
@@ -44,18 +89,15 @@ func New() *cobra.Command {
|
||||
rootCmd.PersistentFlags().BoolVarP(&prettyPrint, "prettyPrint", "P", false, "pretty print")
|
||||
rootCmd.PersistentFlags().IntVarP(&indent, "indent", "I", 2, "sets indent level for output")
|
||||
rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit")
|
||||
rootCmd.PersistentFlags().BoolVarP(&colorsEnabled, "colors", "C", false, "print with colors")
|
||||
|
||||
rootCmd.AddCommand(
|
||||
createReadCmd(),
|
||||
// createCompareCmd(),
|
||||
createValidateCmd(),
|
||||
// createWriteCmd(),
|
||||
// createPrefixCmd(),
|
||||
// createDeleteCmd(),
|
||||
// createNewCmd(),
|
||||
// createMergeCmd(),
|
||||
createBashCompletionCmd(rootCmd),
|
||||
)
|
||||
rootCmd.Flags().StringVarP(&shellCompletion, "shellCompletion", "", "", "[bash/zsh/powershell/fish] prints shell completion script")
|
||||
|
||||
rootCmd.PersistentFlags().BoolVarP(&forceColor, "colors", "C", false, "force print with colors")
|
||||
rootCmd.PersistentFlags().BoolVarP(&forceNoColor, "no-colors", "M", false, "force print with no colors")
|
||||
|
||||
// rootCmd.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||
rootCmd.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)")
|
||||
rootCmd.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results")
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var shellVariant = "bash"
|
||||
|
||||
func createBashCompletionCmd(rootCmd *cobra.Command) *cobra.Command {
|
||||
var completionCmd = &cobra.Command{
|
||||
Use: "shell-completion",
|
||||
Short: "Generates shell completion scripts",
|
||||
Long: `To load completion for:
|
||||
bash:
|
||||
Run
|
||||
. <(yq shell-completion)
|
||||
|
||||
To configure your bash shell to load completions for each session add to
|
||||
your bashrc
|
||||
|
||||
# ~/.bashrc or ~/.profile
|
||||
. <(yq shell-completion)
|
||||
|
||||
zsh:
|
||||
The generated completion script should be put somewhere in your $fpath named _yq
|
||||
|
||||
powershell:
|
||||
Users need PowerShell version 5.0 or above, which comes with Windows 10 and
|
||||
can be downloaded separately for Windows 7 or 8.1. They can then write the
|
||||
completions to a file and source this file from their PowerShell profile,
|
||||
which is referenced by the $Profile environment variable.
|
||||
|
||||
fish:
|
||||
Save the output to a fish file and add it to your completions directory.
|
||||
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
switch shellVariant {
|
||||
case "bash", "":
|
||||
return rootCmd.GenBashCompletion(os.Stdout)
|
||||
case "zsh":
|
||||
return rootCmd.GenZshCompletion(os.Stdout)
|
||||
case "fish":
|
||||
return rootCmd.GenFishCompletion(os.Stdout, true)
|
||||
case "powershell":
|
||||
return rootCmd.GenPowerShellCompletion(os.Stdout)
|
||||
default:
|
||||
return fmt.Errorf("Unknown variant %v", shellVariant)
|
||||
}
|
||||
},
|
||||
}
|
||||
completionCmd.PersistentFlags().StringVarP(&shellVariant, "variation", "V", "", "shell variation: bash (default), zsh, fish, powershell")
|
||||
return completionCmd
|
||||
}
|
||||
441
cmd/utils.go
441
cmd/utils.go
@@ -2,103 +2,73 @@ package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"container/list"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/mikefarah/yq/v3/pkg/yqlib"
|
||||
"github.com/mikefarah/yq/v3/pkg/yqlib/treeops"
|
||||
errors "github.com/pkg/errors"
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib/treeops"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type readDataFn func(document int, dataBucket *yaml.Node) ([]*treeops.CandidateNode, error)
|
||||
|
||||
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 readStream(filename string) (*yaml.Decoder, error) {
|
||||
if filename == "" {
|
||||
return nil, errors.New("Must provide filename")
|
||||
}
|
||||
}
|
||||
|
||||
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) ([]*treeops.CandidateNode, error) {
|
||||
var matchingNodes []*treeops.CandidateNode
|
||||
|
||||
var currentIndex = 0
|
||||
var errorReadingStream = readStream(filename, func(decoder *yaml.Decoder) error {
|
||||
for {
|
||||
var dataBucket yaml.Node
|
||||
errorReading := decoder.Decode(&dataBucket)
|
||||
|
||||
if errorReading == io.EOF {
|
||||
return handleEOF(updateAll, docIndexInt, currentIndex)
|
||||
} else if errorReading != nil {
|
||||
return errorReading
|
||||
}
|
||||
|
||||
var errorParsing error
|
||||
matchingNodes, errorParsing = appendDocument(matchingNodes, dataBucket, readFn, updateAll, docIndexInt, currentIndex)
|
||||
if errorParsing != nil {
|
||||
return errorParsing
|
||||
}
|
||||
if !updateAll && currentIndex == docIndexInt {
|
||||
log.Debug("all done")
|
||||
return nil
|
||||
}
|
||||
currentIndex = currentIndex + 1
|
||||
var stream io.Reader
|
||||
if filename == "-" {
|
||||
stream = bufio.NewReader(os.Stdin)
|
||||
} else {
|
||||
file, err := os.Open(filename) // nolint gosec
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
})
|
||||
return matchingNodes, errorReadingStream
|
||||
defer safelyCloseFile(file)
|
||||
stream = file
|
||||
}
|
||||
return yaml.NewDecoder(stream), nil
|
||||
}
|
||||
|
||||
func handleEOF(updateAll bool, docIndexInt int, currentIndex int) error {
|
||||
log.Debugf("done %v / %v", currentIndex, docIndexInt)
|
||||
if !updateAll && currentIndex <= docIndexInt && docIndexInt != 0 {
|
||||
return fmt.Errorf("Could not process document index %v as there are only %v document(s)", docIndex, currentIndex)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func evaluate(filename string, node *treeops.PathTreeNode) (*list.List, 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)
|
||||
if !updateAll && currentIndex != docIndexInt {
|
||||
return originalMatchingNodes, nil
|
||||
}
|
||||
log.Debugf("reading in document %v", currentIndex)
|
||||
matchingNodes, errorParsing := readFn(currentIndex, &dataBucket)
|
||||
if errorParsing != nil {
|
||||
return nil, errors.Wrapf(errorParsing, "Error reading path in document index %v", currentIndex)
|
||||
}
|
||||
return append(originalMatchingNodes, matchingNodes...), nil
|
||||
}
|
||||
var treeNavigator = treeops.NewDataTreeNavigator(treeops.NavigationPrefs{})
|
||||
|
||||
func lengthOf(node *yaml.Node) int {
|
||||
kindToCheck := node.Kind
|
||||
if node.Kind == yaml.DocumentNode && len(node.Content) == 1 {
|
||||
log.Debugf("length of document node, calculating length of child")
|
||||
kindToCheck = node.Content[0].Kind
|
||||
}
|
||||
switch kindToCheck {
|
||||
case yaml.ScalarNode:
|
||||
return len(node.Value)
|
||||
case yaml.MappingNode:
|
||||
return len(node.Content) / 2
|
||||
default:
|
||||
return len(node.Content)
|
||||
}
|
||||
}
|
||||
var matchingNodes = list.New()
|
||||
|
||||
// transforms node before printing, if required
|
||||
func transformNode(node *yaml.Node) *yaml.Node {
|
||||
if printLength {
|
||||
return &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", lengthOf(node))}
|
||||
var currentIndex uint = 0
|
||||
var decoder, err = readStream(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return node
|
||||
|
||||
for {
|
||||
var dataBucket yaml.Node
|
||||
errorReading := decoder.Decode(&dataBucket)
|
||||
|
||||
if errorReading == io.EOF {
|
||||
return matchingNodes, nil
|
||||
} else if errorReading != nil {
|
||||
return nil, errorReading
|
||||
}
|
||||
candidateNode := &treeops.CandidateNode{
|
||||
Document: currentIndex,
|
||||
Filename: filename,
|
||||
Node: &dataBucket,
|
||||
}
|
||||
inputList := list.New()
|
||||
inputList.PushBack(candidateNode)
|
||||
|
||||
newMatches, errorParsing := treeNavigator.GetMatchingNodes(inputList, node)
|
||||
if errorParsing != nil {
|
||||
return nil, errorParsing
|
||||
}
|
||||
matchingNodes.PushBackList(newMatches)
|
||||
currentIndex = currentIndex + 1
|
||||
}
|
||||
|
||||
return matchingNodes, nil
|
||||
}
|
||||
|
||||
func printNode(node *yaml.Node, writer io.Writer) error {
|
||||
@@ -114,9 +84,10 @@ func printNode(node *yaml.Node, writer io.Writer) error {
|
||||
return encoder.Encode(node)
|
||||
}
|
||||
|
||||
func removeComments(matchingNodes []*treeops.CandidateNode) {
|
||||
for _, nodeContext := range matchingNodes {
|
||||
removeCommentOfNode(nodeContext.Node)
|
||||
func removeComments(matchingNodes *list.List) {
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*treeops.CandidateNode)
|
||||
removeCommentOfNode(candidate.Node)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,9 +101,10 @@ func removeCommentOfNode(node *yaml.Node) {
|
||||
}
|
||||
}
|
||||
|
||||
func setStyle(matchingNodes []*treeops.CandidateNode, style yaml.Style) {
|
||||
for _, nodeContext := range matchingNodes {
|
||||
updateStyleOfNode(nodeContext.Node, style)
|
||||
func setStyle(matchingNodes *list.List, style yaml.Style) {
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
candidate := el.Value.(*treeops.CandidateNode)
|
||||
updateStyleOfNode(candidate.Node, style)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,9 +206,10 @@ func explodeNode(node *yaml.Node) error {
|
||||
}
|
||||
}
|
||||
|
||||
func explode(matchingNodes []*treeops.CandidateNode) error {
|
||||
func explode(matchingNodes *list.List) error {
|
||||
log.Debug("exploding nodes")
|
||||
for _, nodeContext := range matchingNodes {
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
nodeContext := el.Value.(*treeops.CandidateNode)
|
||||
log.Debugf("exploding %v", nodeContext.GetKey())
|
||||
errorExplodingNode := explodeNode(nodeContext.Node)
|
||||
if errorExplodingNode != nil {
|
||||
@@ -246,7 +219,7 @@ func explode(matchingNodes []*treeops.CandidateNode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func printResults(matchingNodes []*treeops.CandidateNode, writer io.Writer) error {
|
||||
func printResults(matchingNodes *list.List, writer io.Writer) error {
|
||||
if prettyPrint {
|
||||
setStyle(matchingNodes, 0)
|
||||
}
|
||||
@@ -255,6 +228,12 @@ func printResults(matchingNodes []*treeops.CandidateNode, writer io.Writer) erro
|
||||
removeComments(matchingNodes)
|
||||
}
|
||||
|
||||
fileInfo, _ := os.Stdout.Stat()
|
||||
|
||||
if forceColor || (!forceNoColor && (fileInfo.Mode()&os.ModeCharDevice) != 0) {
|
||||
colorsEnabled = true
|
||||
}
|
||||
|
||||
//always explode anchors when printing json
|
||||
if explodeAnchors || outputToJSON {
|
||||
errorExploding := explode(matchingNodes)
|
||||
@@ -266,7 +245,7 @@ func printResults(matchingNodes []*treeops.CandidateNode, writer io.Writer) erro
|
||||
bufferedWriter := bufio.NewWriter(writer)
|
||||
defer safelyFlush(bufferedWriter)
|
||||
|
||||
if len(matchingNodes) == 0 {
|
||||
if matchingNodes.Len() == 0 {
|
||||
log.Debug("no matching results, nothing to print")
|
||||
if defaultValue != "" {
|
||||
return writeString(bufferedWriter, defaultValue)
|
||||
@@ -275,9 +254,9 @@ func printResults(matchingNodes []*treeops.CandidateNode, writer io.Writer) erro
|
||||
}
|
||||
var errorWriting error
|
||||
|
||||
var arrayCollection = yaml.Node{Kind: yaml.SequenceNode}
|
||||
for el := matchingNodes.Front(); el != nil; el = el.Next() {
|
||||
mappedDoc := el.Value.(*treeops.CandidateNode)
|
||||
|
||||
for _, mappedDoc := range matchingNodes {
|
||||
switch printMode {
|
||||
case "p":
|
||||
errorWriting = writeString(bufferedWriter, mappedDoc.PathStackToString()+"\n")
|
||||
@@ -289,251 +268,24 @@ func printResults(matchingNodes []*treeops.CandidateNode, writer io.Writer) erro
|
||||
var parentNode = yaml.Node{Kind: yaml.MappingNode}
|
||||
parentNode.Content = make([]*yaml.Node, 2)
|
||||
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)
|
||||
} else if err := printNode(&parentNode, bufferedWriter); err != nil {
|
||||
if mappedDoc.Node.Kind == yaml.DocumentNode {
|
||||
parentNode.Content[1] = mappedDoc.Node.Content[0]
|
||||
} else {
|
||||
parentNode.Content[1] = mappedDoc.Node
|
||||
}
|
||||
if err := printNode(&parentNode, bufferedWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
if collectIntoArray {
|
||||
arrayCollection.Content = append(arrayCollection.Content, mappedDoc.Node)
|
||||
} else if err := printNode(transformNode(mappedDoc.Node), bufferedWriter); err != nil {
|
||||
if err := printNode(mappedDoc.Node, bufferedWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if collectIntoArray {
|
||||
if err := printNode(transformNode(&arrayCollection), bufferedWriter); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseDocumentIndex() (bool, int, error) {
|
||||
if docIndex == "*" {
|
||||
return true, -1, nil
|
||||
}
|
||||
docIndexInt64, err := strconv.ParseInt(docIndex, 10, 32)
|
||||
if err != nil {
|
||||
return false, -1, errors.Wrapf(err, "Document index %v is not a integer or *", docIndex)
|
||||
}
|
||||
return false, int(docIndexInt64), nil
|
||||
}
|
||||
|
||||
type updateDataFn func(dataBucket *yaml.Node, currentIndex int) error
|
||||
|
||||
func isNullDocument(dataBucket *yaml.Node) bool {
|
||||
return dataBucket.Kind == yaml.DocumentNode && (len(dataBucket.Content) == 0 ||
|
||||
dataBucket.Content[0].Kind == yaml.ScalarNode && dataBucket.Content[0].Tag == "!!null")
|
||||
}
|
||||
|
||||
func mapYamlDecoder(updateData updateDataFn, encoder yqlib.Encoder) yamlDecoderFn {
|
||||
return func(decoder *yaml.Decoder) error {
|
||||
var dataBucket yaml.Node
|
||||
var errorReading error
|
||||
var errorWriting error
|
||||
var errorUpdating error
|
||||
var currentIndex = 0
|
||||
|
||||
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||
if errorParsingDocIndex != nil {
|
||||
return errorParsingDocIndex
|
||||
}
|
||||
|
||||
for {
|
||||
log.Debugf("Read doc %v", currentIndex)
|
||||
errorReading = decoder.Decode(&dataBucket)
|
||||
|
||||
if errorReading == io.EOF && docIndexInt == 0 && currentIndex == 0 {
|
||||
//empty document, lets just make one
|
||||
dataBucket = yaml.Node{Kind: yaml.DocumentNode, Content: make([]*yaml.Node, 1)}
|
||||
child := yaml.Node{Kind: yaml.MappingNode}
|
||||
dataBucket.Content[0] = &child
|
||||
} else if isNullDocument(&dataBucket) && (updateAll || docIndexInt == currentIndex) {
|
||||
child := yaml.Node{Kind: yaml.MappingNode}
|
||||
dataBucket.Content[0] = &child
|
||||
} else if errorReading == io.EOF {
|
||||
if !updateAll && currentIndex <= docIndexInt {
|
||||
return fmt.Errorf("asked to process document index %v but there are only %v document(s)", docIndex, currentIndex)
|
||||
}
|
||||
return nil
|
||||
} else if errorReading != nil {
|
||||
return errors.Wrapf(errorReading, "Error reading document at index %v, %v", currentIndex, errorReading)
|
||||
}
|
||||
errorUpdating = updateData(&dataBucket, currentIndex)
|
||||
if errorUpdating != nil {
|
||||
return errors.Wrapf(errorUpdating, "Error updating document at index %v", currentIndex)
|
||||
}
|
||||
|
||||
if prettyPrint {
|
||||
updateStyleOfNode(&dataBucket, 0)
|
||||
}
|
||||
|
||||
errorWriting = encoder.Encode(&dataBucket)
|
||||
|
||||
if errorWriting != nil {
|
||||
return errors.Wrapf(errorWriting, "Error writing document at index %v, %v", currentIndex, errorWriting)
|
||||
}
|
||||
currentIndex = currentIndex + 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
|
||||
|
||||
// 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
|
||||
// }
|
||||
|
||||
// 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"
|
||||
// }
|
||||
|
||||
// log.Debugf("Writing to %v from %v", destinationName, inputFile)
|
||||
|
||||
// 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 errorProcessing = readStream(inputFile, mapYamlDecoder(updateData, encoder))
|
||||
// completedSuccessfully = errorProcessing == nil
|
||||
// return errorProcessing
|
||||
// }
|
||||
|
||||
type updateCommandParsed struct {
|
||||
Command string
|
||||
Path string
|
||||
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)
|
||||
|
||||
// err := readData(writeScript, 0, &parsedCommands)
|
||||
|
||||
// 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'", 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 {
|
||||
log.Debugf("Error renaming from %v to %v, attempting to copy contents", from, to)
|
||||
@@ -584,36 +336,3 @@ func safelyCloseFile(file *os.File) {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
type yamlDecoderFn func(*yaml.Decoder) error
|
||||
|
||||
func readStream(filename string, yamlDecoder yamlDecoderFn) error {
|
||||
if filename == "" {
|
||||
return errors.New("Must provide filename")
|
||||
}
|
||||
|
||||
var stream io.Reader
|
||||
if filename == "-" {
|
||||
stream = bufio.NewReader(os.Stdin)
|
||||
} else {
|
||||
file, err := os.Open(filename) // nolint gosec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer safelyCloseFile(file)
|
||||
stream = file
|
||||
}
|
||||
return yamlDecoder(yaml.NewDecoder(stream))
|
||||
}
|
||||
|
||||
func readData(filename string, indexToRead int, parsedData interface{}) error {
|
||||
return readStream(filename, func(decoder *yaml.Decoder) error {
|
||||
for currentIndex := 0; currentIndex < indexToRead; currentIndex++ {
|
||||
errorSkipping := decoder.Decode(parsedData)
|
||||
if errorSkipping != nil {
|
||||
return errors.Wrapf(errorSkipping, "Error processing document at index %v, %v", currentIndex, errorSkipping)
|
||||
}
|
||||
}
|
||||
return decoder.Decode(parsedData)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
errors "github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func createValidateCmd() *cobra.Command {
|
||||
var cmdRead = &cobra.Command{
|
||||
Use: "validate [yaml_file]",
|
||||
Aliases: []string{"v"},
|
||||
Short: "yq v sample.yaml",
|
||||
Example: `
|
||||
yq v - # reads from stdin
|
||||
`,
|
||||
RunE: validateProperty,
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: false,
|
||||
}
|
||||
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||
return cmdRead
|
||||
}
|
||||
|
||||
func validateProperty(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 {
|
||||
return errors.New("Must provide filename")
|
||||
}
|
||||
|
||||
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||
if errorParsingDocIndex != nil {
|
||||
return errorParsingDocIndex
|
||||
}
|
||||
|
||||
_, errorReadingStream := readYamlFile(args[0], "", updateAll, docIndexInt)
|
||||
|
||||
return errorReadingStream
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/mikefarah/yq/v3/test"
|
||||
)
|
||||
|
||||
func TestValidateCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "validate ../examples/sample.yaml b.c")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "", result.Output)
|
||||
}
|
||||
|
||||
func TestValidateBadDataCmd(t *testing.T) {
|
||||
content := `[!Whatever]`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("validate %s", filename))
|
||||
if result.Error == nil {
|
||||
t.Error("Expected command to fail")
|
||||
}
|
||||
expectedOutput := `yaml: line 1: did not find expected ',' or ']'`
|
||||
test.AssertResult(t, expectedOutput, result.Error.Error())
|
||||
}
|
||||
@@ -11,7 +11,7 @@ var (
|
||||
GitDescribe string
|
||||
|
||||
// Version is main version number that is being run at the moment.
|
||||
Version = "3.4.0"
|
||||
Version = "4.0.0-beta"
|
||||
|
||||
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
|
||||
Reference in New Issue
Block a user