From aab67e287f52dedba649037b7f71b3ea3875f6ba Mon Sep 17 00:00:00 2001 From: Uwe Krueger Date: Thu, 23 Jul 2020 10:20:07 +0200 Subject: [PATCH] keep options --- README.md | 8 +++++++- cmd/merge.go | 24 ++++++++++-------------- cmd/run.go | 12 ++++++++---- flow/cascade.go | 22 ++++++++++++++++------ flow/cascade_as_helper_test.go | 2 +- flow/environment.go | 2 +- 6 files changed, 43 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index af883a5..6dad5d8 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,7 @@ The ` merge` command offers several options: - With the option `--json` the output will be in JSON format instead of YAML. -- The Option `--path ` can be used to output a nested path, instead of the +- The option `--path ` can be used to output a nested path, instead of the the complete processed document. - If the output is a list, the option `--split` outputs every list element as @@ -234,7 +234,13 @@ The ` merge` command offers several options: state file with the `.bak` suffix. This can be used together with a manual merging as offered by the [state](libraries/state/README.md) utility library. +- The option `--preserve-escapes` will preserve the escaping for dynaml + expressions and list/map merge directives. This option can be used + if further processing steps of a processing result with *spiff* is intended. +- The option `--preserve-temporary` will preserve the fields marked as temporary + in the final document. + The folder [libraries](libraries/README.md) offers some useful utility libraries. They can also be used as an example for the power of this templating engine. diff --git a/cmd/merge.go b/cmd/merge.go index d541b9c..3708388 100644 --- a/cmd/merge.go +++ b/cmd/merge.go @@ -19,10 +19,10 @@ import ( ) var asJSON bool -var partial bool var outputPath string var selection []string var split bool +var processingOptions flow.Options var state string // mergeCmd represents the merge command @@ -38,7 +38,7 @@ var mergeCmd = &cobra.Command{ return nil }, Run: func(cmd *cobra.Command, args []string) { - merge(false, args[0], partial, asJSON, split, outputPath, selection, state, nil, args[1:]) + merge(false, args[0], processingOptions, asJSON, split, outputPath, selection, state, nil, args[1:]) }, } @@ -46,17 +46,13 @@ func init() { rootCmd.AddCommand(mergeCmd) mergeCmd.Flags().BoolVar(&asJSON, "json", false, "print output in json format") - mergeCmd.Flags().BoolVar(&debug.DebugFlag, "debug", false, "Print state info") - - mergeCmd.Flags().BoolVar(&partial, "partial", false, "Allow partial evaluation only") - + mergeCmd.Flags().BoolVar(&processingOptions.Partial, "partial", false, "Allow partial evaluation only") mergeCmd.Flags().StringVar(&outputPath, "path", "", "output is taken from given path") - mergeCmd.Flags().BoolVar(&split, "split", false, "if the output is alist it will be split into separate documents") - + mergeCmd.Flags().BoolVar(&processingOptions.PreserveEscapes, "preserve-escapes", false, "preserve escaping for escaped expressions and merges") + mergeCmd.Flags().BoolVar(&processingOptions.PreserveTemporaray, "preserve-temporary", false, "preserve temporary fields") mergeCmd.Flags().StringVar(&state, "state", "", "select state file to maintain") - mergeCmd.Flags().StringArrayVar(&selection, "select", []string{}, "filter dedicated output fields") } @@ -68,7 +64,7 @@ func fileExists(filename string) bool { return !info.IsDir() } -func merge(stdin bool, templateFilePath string, partial bool, json, split bool, +func merge(stdin bool, templateFilePath string, opts flow.Options, json, split bool, subpath string, selection []string, stateFilePath string, stubs []yaml.Node, stubFilePaths []string) { var templateFile []byte var err error @@ -142,8 +138,8 @@ func merge(stdin bool, templateFilePath string, partial bool, json, split bool, " @: dependent of or involved in a cycle\n" + " -: depending on a node with an error" - prepared, err := flow.PrepareStubs(nil, partial, stubs...) - if !partial && err != nil { + prepared, err := flow.PrepareStubs(nil, processingOptions.Partial, stubs...) + if !processingOptions.Partial && err != nil { log.Fatalln("error generating manifest:", err, legend) } @@ -157,8 +153,8 @@ func merge(stdin bool, templateFilePath string, partial bool, json, split bool, var bytes []byte if templateYAML.Value() != nil { count++ - flowed, err := flow.Apply(nil, templateYAML, prepared) - if !partial && err != nil { + flowed, err := flow.Apply(nil, templateYAML, prepared, opts) + if !opts.Partial && err != nil { log.Fatalln(fmt.Sprintf("error generating manifest%s:", doc), err, legend) } if err != nil { diff --git a/cmd/run.go b/cmd/run.go index f57c143..74c6887 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/mandelsoft/spiff/debug" + "github.com/mandelsoft/spiff/flow" "github.com/mandelsoft/spiff/yaml" "github.com/spf13/cobra" "io/ioutil" @@ -25,7 +26,7 @@ var processCmd = &cobra.Command{ return nil }, Run: func(cmd *cobra.Command, args []string) { - run(args[0], args[1], partial, asJSON, split, outputPath, selection, state, args[2:]) + run(args[0], args[1], processingOptions, asJSON, split, outputPath, selection, state, args[2:]) }, } @@ -34,13 +35,16 @@ func init() { processCmd.Flags().BoolVar(&asJSON, "json", false, "print output in json format") processCmd.Flags().BoolVar(&debug.DebugFlag, "debug", false, "Print state info") - processCmd.Flags().BoolVar(&partial, "partial", false, "Allow partial evaluation only") + processCmd.Flags().BoolVar(&processingOptions.Partial, "partial", false, "Allow partial evaluation only") processCmd.Flags().StringVar(&outputPath, "path", "", "output is taken from given path") processCmd.Flags().StringVar(&state, "state", "", "select state file to maintain") processCmd.Flags().StringArrayVar(&selection, "select", []string{}, "filter dedicated output fields") + processCmd.Flags().BoolVar(&processingOptions.PreserveEscapes, "preserve-escapes", false, "preserve escaping for escaped expressions and merges") + processCmd.Flags().BoolVar(&processingOptions.PreserveTemporaray, "preserve-temporary", false, "preserve temporary fields") + } -func run(documentFilePath, templateFilePath string, partial bool, json, split bool, +func run(documentFilePath, templateFilePath string, opts flow.Options, json, split bool, subpath string, selection []string, stateFilePath string, stubFilePaths []string) { var err error var stdin = false @@ -60,5 +64,5 @@ func run(documentFilePath, templateFilePath string, partial bool, json, split bo documentYAML = yaml.NewNode(map[string]yaml.Node{"document": documentYAML}, "<"+documentFilePath+">") stub := yaml.NewNode(map[string]yaml.Node{"document": yaml.NewNode("(( &temporary &inject (merge) ))", ")")}, "") - merge(stdin, templateFilePath, partial, json, split, subpath, selection, stateFilePath, []yaml.Node{stub, documentYAML}, stubFilePaths) + merge(stdin, templateFilePath, opts, json, split, subpath, selection, stateFilePath, []yaml.Node{stub, documentYAML}, stubFilePaths) } diff --git a/flow/cascade.go b/flow/cascade.go index a34fad6..9d4daaa 100644 --- a/flow/cascade.go +++ b/flow/cascade.go @@ -5,6 +5,12 @@ import ( "github.com/mandelsoft/spiff/yaml" ) +type Options struct { + PreserveEscapes bool + PreserveTemporaray bool + Partial bool +} + func PrepareStubs(outer dynaml.Binding, partial bool, stubs ...yaml.Node) ([]yaml.Node, error) { for i := len(stubs) - 1; i >= 0; i-- { flowed, err := NestedFlow(outer, stubs[i], stubs[i+1:]...) @@ -17,22 +23,26 @@ func PrepareStubs(outer dynaml.Binding, partial bool, stubs ...yaml.Node) ([]yam return stubs, nil } -func Apply(outer dynaml.Binding, template yaml.Node, prepared []yaml.Node) (yaml.Node, error) { +func Apply(outer dynaml.Binding, template yaml.Node, prepared []yaml.Node, opts Options) (yaml.Node, error) { result, err := NestedFlow(outer, template, prepared...) if err == nil { - result = Cleanup(result, discardTemporary) - result = Cleanup(result, unescapeDynaml) + if !opts.PreserveTemporaray { + result = Cleanup(result, discardTemporary) + } + if !opts.PreserveEscapes { + result = Cleanup(result, unescapeDynaml) + } } return result, err } -func Cascade(outer dynaml.Binding, template yaml.Node, partial bool, stubs ...yaml.Node) (yaml.Node, error) { - prepared, err := PrepareStubs(outer, partial, stubs...) +func Cascade(outer dynaml.Binding, template yaml.Node, opts Options, stubs ...yaml.Node) (yaml.Node, error) { + prepared, err := PrepareStubs(outer, opts.Partial, stubs...) if err != nil { return nil, err } - return Apply(outer, template, prepared) + return Apply(outer, template, prepared, opts) } func discardTemporary(node yaml.Node) (yaml.Node, CleanupFunction) { diff --git a/flow/cascade_as_helper_test.go b/flow/cascade_as_helper_test.go index 895d7b0..99a6e9a 100644 --- a/flow/cascade_as_helper_test.go +++ b/flow/cascade_as_helper_test.go @@ -21,7 +21,7 @@ func (matcher *CascadeAsMatcher) Match(source interface{}) (success bool, err er return false, fmt.Errorf("Refusing to compare to .") } - matcher.actual, err = Cascade(nil, source.(yaml.Node), false, matcher.Stubs...) + matcher.actual, err = Cascade(nil, source.(yaml.Node), Options{}, matcher.Stubs...) if err != nil { return false, err } diff --git a/flow/environment.go b/flow/environment.go index 6cde7ef..487196f 100644 --- a/flow/environment.go +++ b/flow/environment.go @@ -275,7 +275,7 @@ func (e DefaultEnvironment) Flow(source yaml.Node, shouldOverride bool) (yaml.No } func (e DefaultEnvironment) Cascade(outer dynaml.Binding, template yaml.Node, partial bool, templates ...yaml.Node) (yaml.Node, error) { - return Cascade(outer, template, partial, templates...) + return Cascade(outer, template, Options{Partial: partial}, templates...) } func NewEnvironment(stubs []yaml.Node, source string) dynaml.Binding {