From 972e2b957561cf5353397cc074c12ecaf7db9be8 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Fri, 6 Dec 2019 16:36:42 +1100 Subject: [PATCH] wip --- examples/instruction_sample.yaml | 9 ++++-- pkg/yqlib/data_navigator.go | 15 ++------- pkg/yqlib/lib.go | 29 +++++++++++++++--- yq.go | 52 ++++++++++---------------------- 4 files changed, 50 insertions(+), 55 deletions(-) diff --git a/examples/instruction_sample.yaml b/examples/instruction_sample.yaml index b7864db..9834c94 100644 --- a/examples/instruction_sample.yaml +++ b/examples/instruction_sample.yaml @@ -1,7 +1,10 @@ -- command: update +- command: update path: b.c value: #great things: frog # wow! - -b.e[+].name: Mike Farah +- command: update + path: b.e[+].name + value: Mike Farah +- command: delete + path: a \ No newline at end of file diff --git a/pkg/yqlib/data_navigator.go b/pkg/yqlib/data_navigator.go index 6674159..744cdbc 100644 --- a/pkg/yqlib/data_navigator.go +++ b/pkg/yqlib/data_navigator.go @@ -7,14 +7,9 @@ import ( yaml "gopkg.in/yaml.v3" ) -type WriteCommand struct { - // Command string TODO - Value yaml.Node -} - type DataNavigator interface { Get(rootNode *yaml.Node, remainingPath []string) (*yaml.Node, error) - Update(rootNode *yaml.Node, remainingPath []string, writeCommand WriteCommand) error + Update(rootNode *yaml.Node, remainingPath []string, changesToApply yaml.Node) error } type navigator struct { @@ -33,7 +28,7 @@ func (n *navigator) Get(value *yaml.Node, path []string) (*yaml.Node, error) { realValue = value.Content[0] } if len(path) > 0 { - n.log.Debug("diving into %v", path[0]) + n.log.Debugf("diving into %v", path[0]) return n.recurse(realValue, path[0], path[1:]) } return realValue, nil @@ -117,15 +112,11 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string) (*yaml } } -func (n *navigator) Update(dataBucket *yaml.Node, remainingPath []string, writeCommand WriteCommand) error { +func (n *navigator) Update(dataBucket *yaml.Node, remainingPath []string, changesToApply yaml.Node) error { nodeToUpdate, errorRecursing := n.Get(dataBucket, remainingPath) if errorRecursing != nil { return errorRecursing } - // later, support ability to execute other commands - - changesToApply := writeCommand.Value - nodeToUpdate.Value = changesToApply.Value nodeToUpdate.Tag = changesToApply.Tag nodeToUpdate.Kind = changesToApply.Kind diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index a477b8d..5b630e8 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -1,24 +1,34 @@ package yqlib import ( + "fmt" + logging "gopkg.in/op/go-logging.v1" yaml "gopkg.in/yaml.v3" ) +type UpdateCommand struct { + Command string + Path string + Value yaml.Node +} + type YqLib interface { Get(rootNode *yaml.Node, path string) (*yaml.Node, error) - Update(rootNode *yaml.Node, path string, writeCommand WriteCommand) error + Update(rootNode *yaml.Node, updateCommand UpdateCommand) error } type lib struct { navigator DataNavigator parser PathParser + log *logging.Logger } func NewYqLib(l *logging.Logger) YqLib { return &lib{ navigator: NewDataNavigator(l), parser: NewPathParser(), + log: l, } } @@ -30,7 +40,18 @@ func (l *lib) Get(rootNode *yaml.Node, path string) (*yaml.Node, error) { return l.navigator.Get(rootNode, paths) } -func (l *lib) Update(rootNode *yaml.Node, path string, writeCommand WriteCommand) error { - var paths = l.parser.ParsePath(path) - return l.navigator.Update(rootNode, paths, writeCommand) +func (l *lib) Update(rootNode *yaml.Node, updateCommand UpdateCommand) error { + // later - support other command types + l.log.Debugf("%v to %v", updateCommand.Command, updateCommand.Path) + switch updateCommand.Command { + case "update": + var paths = l.parser.ParsePath(updateCommand.Path) + return l.navigator.Update(rootNode, paths, updateCommand.Value) + case "delete": + l.log.Debugf("need to implement delete") + return nil + default: + return fmt.Errorf("Unknown command %v", updateCommand.Command) + } + } diff --git a/yq.go b/yq.go index f3b0c24..5a21169 100644 --- a/yq.go +++ b/yq.go @@ -19,7 +19,7 @@ import ( ) var rawOutput = false -var trimOutput = true +var customTag = "" var writeInplace = false var writeScript = "" var outputToJSON = false @@ -74,7 +74,6 @@ func newCommandCLI() *cobra.Command { }, } - rootCmd.PersistentFlags().BoolVarP(&trimOutput, "trim", "t", true, "trim yaml output") rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode") rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit") @@ -144,6 +143,7 @@ a.b.e: } cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") cmdWrite.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml") + cmdWrite.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)") cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") return cmdWrite } @@ -327,7 +327,7 @@ func readProperty(cmd *cobra.Command, args []string) error { // } // func newYaml(args []string) (interface{}, error) { -// var writeCommands, writeCommandsError = readWriteCommands(args, 2, "Must provide ") +// var writeCommands, writeCommandsError = readUpdateCommands(args, 2, "Must provide ") // if writeCommandsError != nil { // return nil, writeCommandsError // } @@ -404,9 +404,9 @@ func mapYamlDecoder(updateData updateDataFn, encoder *yaml.Encoder) yamlDecoderF } func writeProperty(cmd *cobra.Command, args []string) error { - var writeCommands, writeCommandsError = readWriteCommands(args, 3, "Must provide ") - if writeCommandsError != nil { - return writeCommandsError + var updateCommands, updateCommandsError = readUpdateCommands(args, 3, "Must provide ") + if updateCommandsError != nil { + return updateCommandsError } var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex() if errorParsingDocIndex != nil { @@ -416,12 +416,8 @@ func writeProperty(cmd *cobra.Command, args []string) error { var updateData = func(dataBucket *yaml.Node, currentIndex int) error { if updateAll || currentIndex == docIndexInt { log.Debugf("Updating doc %v", currentIndex) - for _, entry := range writeCommands { - path := entry.Key - changesToApply := entry.Value - var paths = parsePath(path) - - errorUpdating := updateChild(dataBucket, paths, changesToApply) + for _, updateCommand := range updateCommands { + errorUpdating := lib.Update(dataBucket, updateCommand) if errorUpdating != nil { return errorUpdating } @@ -552,36 +548,20 @@ func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn) // return readAndUpdate(cmd.OutOrStdout(), input, updateData) // } -type rawWriteCommand struct { - // Command string TODO - Key string - Value yaml.Node -} - -func readWriteCommands(args []string, expectedArgs int, badArgsMessage string) ([]rawWriteCommand, error) { - var writeCommands []rawWriteCommand +func readUpdateCommands(args []string, expectedArgs int, badArgsMessage string) ([]yqlib.UpdateCommand, error) { + var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 1) if writeScript != "" { - var rawCommands yaml.Node - if err := readData(writeScript, 0, &rawCommands); err != nil { + if err := readData(writeScript, 0, &updateCommands); err != nil { return nil, err } - log.Debugf("Read write commands file '%v'", rawCommands) - var key string - for index, content := range rawCommands.Content[0].Content { - if index%2 == 0 { // must be the key - key = content.Value - } else { // its the value - writeCommands = append(writeCommands, rawWriteCommand{Key: key, Value: *content}) - } - } - log.Debugf("Read write commands '%v'", writeCommands) + log.Debugf("Read write commands file '%v'", updateCommands) } else if len(args) < expectedArgs { return nil, errors.New(badArgsMessage) } else { - writeCommands = make([]rawWriteCommand, 1) - writeCommands[0] = rawWriteCommand{Key: args[expectedArgs-2], Value: parseValue(args[expectedArgs-1])} + updateCommands = make([]yqlib.UpdateCommand, 1) + updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: parseValue(args[expectedArgs-1])} } - return writeCommands, nil + return updateCommands, nil } func parseValue(argument string) yaml.Node { @@ -619,7 +599,7 @@ func toString(context interface{}) (string, error) { if outputToJSON { return jsonConverter.JsonToString(context) } - return yamlConverter.YamlToString(context, trimOutput) + return yamlConverter.YamlToString(context, true) } func safelyRenameFile(from string, to string) {