mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	wip - write in place
This commit is contained in:
		
							parent
							
								
									1258fa199e
								
							
						
					
					
						commit
						8de10e550d
					
				| @ -2,7 +2,7 @@ package cmd | |||||||
| 
 | 
 | ||||||
| var unwrapScalar = true | var unwrapScalar = true | ||||||
| 
 | 
 | ||||||
| // var writeInplace = false | var writeInplace = false | ||||||
| var outputToJSON = false | var outputToJSON = false | ||||||
| 
 | 
 | ||||||
| // var exitStatus = false | // var exitStatus = false | ||||||
| @ -14,5 +14,3 @@ var noDocSeparators = false | |||||||
| var nullInput = false | var nullInput = false | ||||||
| var verbose = false | var verbose = false | ||||||
| var version = false | var version = false | ||||||
| 
 |  | ||||||
| // var log = logging.MustGetLogger("yq") |  | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| package cmd | package cmd | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"os" | 	"os" | ||||||
| 
 | 
 | ||||||
| 	"github.com/mikefarah/yq/v4/pkg/yqlib" | 	"github.com/mikefarah/yq/v4/pkg/yqlib" | ||||||
| @ -39,7 +40,24 @@ func evaluateAll(cmd *cobra.Command, args []string) error { | |||||||
| 	if forceColor || (!forceNoColor && (fileInfo.Mode()&os.ModeCharDevice) != 0) { | 	if forceColor || (!forceNoColor && (fileInfo.Mode()&os.ModeCharDevice) != 0) { | ||||||
| 		colorsEnabled = true | 		colorsEnabled = true | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if writeInplace && len(args) < 2 { | ||||||
|  | 		return fmt.Errorf("Write inplace flag only applicable when giving an expression and at least one file") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	completedSuccessfully := false | ||||||
|  | 
 | ||||||
|  | 	if writeInplace { | ||||||
|  | 		writeInPlaceHandler := yqlib.NewWriteInPlaceHandler(args[1]) | ||||||
|  | 		out, err = writeInPlaceHandler.CreateTempFile() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		defer writeInPlaceHandler.FinishWriteInPlace(completedSuccessfully) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	printer := yqlib.NewPrinter(out, outputToJSON, unwrapScalar, colorsEnabled, indent, !noDocSeparators) | 	printer := yqlib.NewPrinter(out, outputToJSON, unwrapScalar, colorsEnabled, indent, !noDocSeparators) | ||||||
|  | 
 | ||||||
| 	allAtOnceEvaluator := yqlib.NewAllAtOnceEvaluator() | 	allAtOnceEvaluator := yqlib.NewAllAtOnceEvaluator() | ||||||
| 	switch len(args) { | 	switch len(args) { | ||||||
| 	case 0: | 	case 0: | ||||||
| @ -59,6 +77,8 @@ func evaluateAll(cmd *cobra.Command, args []string) error { | |||||||
| 		err = allAtOnceEvaluator.EvaluateFiles(args[0], args[1:], printer) | 		err = allAtOnceEvaluator.EvaluateFiles(args[0], args[1:], printer) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	completedSuccessfully = err == nil | ||||||
|  | 
 | ||||||
| 	cmd.SilenceUsage = true | 	cmd.SilenceUsage = true | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  | |||||||
| @ -46,6 +46,7 @@ func New() *cobra.Command { | |||||||
| 
 | 
 | ||||||
| 	rootCmd.PersistentFlags().IntVarP(&indent, "indent", "I", 2, "sets indent level for output") | 	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.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit") | ||||||
|  | 	rootCmd.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace of first yaml file given.") | ||||||
| 
 | 
 | ||||||
| 	rootCmd.PersistentFlags().BoolVarP(&forceColor, "colors", "C", false, "force print with colors") | 	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().BoolVarP(&forceNoColor, "no-colors", "M", false, "force print with no colors") | ||||||
|  | |||||||
							
								
								
									
										61
									
								
								cmd/write.go
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								cmd/write.go
									
									
									
									
									
								
							| @ -1,61 +0,0 @@ | |||||||
| package cmd |  | ||||||
| 
 |  | ||||||
| // import ( |  | ||||||
| // 	"github.com/spf13/cobra" |  | ||||||
| // ) |  | ||||||
| 
 |  | ||||||
| // func createWriteCmd() *cobra.Command { |  | ||||||
| // 	var cmdWrite = &cobra.Command{ |  | ||||||
| // 		Use:     "write [yaml_file] [path_expression] [value]", |  | ||||||
| // 		Aliases: []string{"w"}, |  | ||||||
| // 		Short:   "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml 'b.e(name==fr*).value' newValue", |  | ||||||
| // 		Example: ` |  | ||||||
| // yq write things.yaml 'a.b.c' true |  | ||||||
| // yq write things.yaml 'a.*.c' true |  | ||||||
| // yq write things.yaml 'a.**' true |  | ||||||
| // yq write things.yaml 'a.(child.subchild==co*).c' true |  | ||||||
| // yq write things.yaml 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool |  | ||||||
| // yq write things.yaml 'a.b.c' --tag '!!float' 3 |  | ||||||
| // yq write --inplace -- things.yaml 'a.b.c' '--cat' # need to use '--' to stop processing arguments as flags |  | ||||||
| // yq w -i things.yaml 'a.b.c' cat |  | ||||||
| // yq w -i -s update_script.yaml things.yaml |  | ||||||
| // yq w things.yaml 'a.b.d[+]' foo # appends a new node to the 'd' array |  | ||||||
| // yq w --doc 2 things.yaml 'a.b.d[+]' foo # updates the 3rd document of the yaml file |  | ||||||
| //       `, |  | ||||||
| // 		Long: `Updates the yaml file w.r.t the given path and value. |  | ||||||
| // Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead. |  | ||||||
| 
 |  | ||||||
| // Append value to array adds the value to the end of array. |  | ||||||
| 
 |  | ||||||
| // Update Scripts: |  | ||||||
| // Note that you can give an update script to perform more sophisticated update. Update script |  | ||||||
| // format is list of update commands (update or delete) like so: |  | ||||||
| // --- |  | ||||||
| // - command: update |  | ||||||
| //   path: b.c |  | ||||||
| //   value: |  | ||||||
| //     #great |  | ||||||
| //     things: frog # wow! |  | ||||||
| // - command: delete |  | ||||||
| //   path: b.d |  | ||||||
| // `, |  | ||||||
| // 		RunE: writeProperty, |  | ||||||
| // 	} |  | ||||||
| // 	cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace") |  | ||||||
| // 	cmdWrite.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml") |  | ||||||
| // 	cmdWrite.PersistentFlags().StringVarP(&sourceYamlFile, "from", "f", "", "yaml file for updating yaml (as-is)") |  | ||||||
| // 	cmdWrite.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)") |  | ||||||
| // 	cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)") |  | ||||||
| // 	cmdWrite.PersistentFlags().StringVarP(&customStyle, "style", "", "", "formatting style of the value: single, double, folded, flow, literal, tagged") |  | ||||||
| // 	cmdWrite.PersistentFlags().StringVarP(&anchorName, "anchorName", "", "", "anchor name") |  | ||||||
| // 	cmdWrite.PersistentFlags().BoolVarP(&makeAlias, "makeAlias", "", false, "create an alias using the value as the anchor name") |  | ||||||
| // 	return cmdWrite |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func writeProperty(cmd *cobra.Command, args []string) error { |  | ||||||
| // 	var updateCommands, updateCommandsError = readUpdateCommands(args, 3, "Must provide <filename> <path_to_update> <value>", true) |  | ||||||
| // 	if updateCommandsError != nil { |  | ||||||
| // 		return updateCommandsError |  | ||||||
| // 	} |  | ||||||
| // 	return updateDoc(args[0], updateCommands, cmd.OutOrStdout()) |  | ||||||
| // } |  | ||||||
| @ -1,610 +0,0 @@ | |||||||
| package cmd |  | ||||||
| 
 |  | ||||||
| // import ( |  | ||||||
| // 	"fmt" |  | ||||||
| // 	"runtime" |  | ||||||
| // 	"strings" |  | ||||||
| // 	"testing" |  | ||||||
| 
 |  | ||||||
| // 	"github.com/mikefarah/yq/v3/test" |  | ||||||
| // ) |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 7 |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteKeepCommentsCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 # comment |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 7 # comment |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteWithTaggedStyleCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: dog |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --tag=!!str --style=tagged", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: !!str cat |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteWithDoubleQuotedStyleCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: dog |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=double", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: "cat" |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteUpdateStyleOnlyCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: dog |  | ||||||
| //   d: things |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* --style=single", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 'dog' |  | ||||||
| //   d: 'things' |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteUpdateTagOnlyCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: true |  | ||||||
| //   d: false |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* --tag=!!str", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: "true" |  | ||||||
| //   d: "false" |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteWithSingleQuotedStyleCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: dog |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=single", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 'cat' |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteWithLiteralStyleCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: dog |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=literal", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: |- |  | ||||||
| //     cat |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteWithFoldedStyleCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: dog |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c cat --style=folded", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: >- |  | ||||||
| //     cat |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteEmptyMultiDocCmd(t *testing.T) { |  | ||||||
| // 	content := `# this is empty |  | ||||||
| // --- |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s c 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `c: 7 |  | ||||||
| 
 |  | ||||||
| // # this is empty |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteSurroundingEmptyMultiDocCmd(t *testing.T) { |  | ||||||
| // 	content := `--- |  | ||||||
| // # empty |  | ||||||
| // --- |  | ||||||
| // cat: frog |  | ||||||
| // --- |  | ||||||
| 
 |  | ||||||
| // # empty |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s -d1 c 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := ` |  | ||||||
| 
 |  | ||||||
| // # empty |  | ||||||
| // --- |  | ||||||
| // cat: frog |  | ||||||
| // c: 7 |  | ||||||
| // --- |  | ||||||
| 
 |  | ||||||
| // # empty |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteFromFileCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	source := `kittens: are cute # sure are!` |  | ||||||
| // 	fromFilename := test.WriteTempYamlFile(source) |  | ||||||
| // 	defer test.RemoveTempYamlFile(fromFilename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c -f %s", filename, fromFilename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: |  | ||||||
| //     kittens: are cute # sure are! |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteEmptyCmd(t *testing.T) { |  | ||||||
| // 	content := `` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 7 |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteAutoCreateCmd(t *testing.T) { |  | ||||||
| // 	content := `applications: |  | ||||||
| //   - name: app |  | ||||||
| //     env:` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s applications[0].env.hello world", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `applications: |  | ||||||
| //   - name: app |  | ||||||
| //     env: |  | ||||||
| //       hello: world |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmdScript(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	updateScript := `- command: update |  | ||||||
| //   path: b.c |  | ||||||
| //   value: 7` |  | ||||||
| // 	scriptFilename := test.WriteTempYamlFile(updateScript) |  | ||||||
| // 	defer test.RemoveTempYamlFile(scriptFilename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 7 |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmdEmptyScript(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	updateScript := `` |  | ||||||
| // 	scriptFilename := test.WriteTempYamlFile(updateScript) |  | ||||||
| // 	defer test.RemoveTempYamlFile(scriptFilename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteMultiCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // --- |  | ||||||
| // apples: great |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // --- |  | ||||||
| // apples: ok |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| // func TestWriteInvalidDocumentIndexCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s -df apples ok", filename)) |  | ||||||
| // 	if result.Error == nil { |  | ||||||
| // 		t.Error("Expected command to fail due to invalid path") |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Error.Error()) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteBadDocumentIndexCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename)) |  | ||||||
| // 	if result.Error == nil { |  | ||||||
| // 		t.Error("Expected command to fail due to invalid path") |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `asked to process document index 1 but there are only 1 document(s)` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Error.Error()) |  | ||||||
| // } |  | ||||||
| // func TestWriteMultiAllCmd(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // --- |  | ||||||
| // apples: great |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s -d * apples ok", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // apples: ok |  | ||||||
| // --- |  | ||||||
| // apples: ok` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, strings.Trim(result.Output, "\n ")) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_EmptyArray(t *testing.T) { |  | ||||||
| // 	content := `b: 3` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s a []", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: 3 |  | ||||||
| // a: [] |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_Error(t *testing.T) { |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, "write") |  | ||||||
| // 	if result.Error == nil { |  | ||||||
| // 		t.Error("Expected command to fail due to missing arg") |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `Must provide <filename> <path_to_update> <value>` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Error.Error()) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_ErrorUnreadableFile(t *testing.T) { |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, "write fake-unknown a.b 3") |  | ||||||
| // 	if result.Error == nil { |  | ||||||
| // 		t.Error("Expected command to fail due to unknown file") |  | ||||||
| // 	} |  | ||||||
| // 	var expectedOutput string |  | ||||||
| // 	if runtime.GOOS == "windows" { |  | ||||||
| // 		expectedOutput = `open fake-unknown: The system cannot find the file specified.` |  | ||||||
| // 	} else { |  | ||||||
| // 		expectedOutput = `open fake-unknown: no such file or directory` |  | ||||||
| // 	} |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Error.Error()) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_Inplace(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write -i %s b.c 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	gotOutput := test.ReadTempYamlFile(filename) |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: 7` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, strings.Trim(gotOutput, "\n ")) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_InplaceError(t *testing.T) { |  | ||||||
| // 	content := `b: cat |  | ||||||
| //   c: 3 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write -i %s b.c 7", filename)) |  | ||||||
| // 	if result.Error == nil { |  | ||||||
| // 		t.Error("Expected Error to occur!") |  | ||||||
| // 	} |  | ||||||
| // 	gotOutput := test.ReadTempYamlFile(filename) |  | ||||||
| // 	test.AssertResult(t, content, gotOutput) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_Append(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   - foo |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   - foo |  | ||||||
| //   - 7 |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_AppendInline(t *testing.T) { |  | ||||||
| // 	content := `b: [foo]` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: [foo, 7] |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_AppendInlinePretty(t *testing.T) { |  | ||||||
| // 	content := `b: [foo]` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s -P b[+] 7", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   - foo |  | ||||||
| //   - 7 |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_AppendEmptyArray(t *testing.T) { |  | ||||||
| // 	content := `a: 2 |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b[+] v", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `a: 2 |  | ||||||
| // b: |  | ||||||
| //   - v |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_SplatArray(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| // - c: thing |  | ||||||
| // - c: another thing |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b[*].c new", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   - c: new |  | ||||||
| //   - c: new |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_SplatMap(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: thing |  | ||||||
| //   d: another thing |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.* new", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: new |  | ||||||
| //   d: new |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // func TestWriteCmd_SplatMapEmpty(t *testing.T) { |  | ||||||
| // 	content := `b: |  | ||||||
| //   c: thing |  | ||||||
| //   d: another thing |  | ||||||
| // ` |  | ||||||
| // 	filename := test.WriteTempYamlFile(content) |  | ||||||
| // 	defer test.RemoveTempYamlFile(filename) |  | ||||||
| 
 |  | ||||||
| // 	cmd := getRootCommand() |  | ||||||
| // 	result := test.RunCmd(cmd, fmt.Sprintf("write %s b.c.* new", filename)) |  | ||||||
| // 	if result.Error != nil { |  | ||||||
| // 		t.Error(result.Error) |  | ||||||
| // 	} |  | ||||||
| // 	expectedOutput := `b: |  | ||||||
| //   c: {} |  | ||||||
| //   d: another thing |  | ||||||
| // ` |  | ||||||
| // 	test.AssertResult(t, expectedOutput, result.Output) |  | ||||||
| // } |  | ||||||
							
								
								
									
										50
									
								
								pkg/yqlib/file_utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								pkg/yqlib/file_utils.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | package yqlib | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | 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) | ||||||
|  | 		log.Debug(renameError.Error()) | ||||||
|  | 		// can't do this rename when running in docker to a file targeted in a mounted volume, | ||||||
|  | 		// so gracefully degrade to copying the entire contents. | ||||||
|  | 		if copyError := copyFileContents(from, to); copyError != nil { | ||||||
|  | 			log.Errorf("Failed copying from %v to %v", from, to) | ||||||
|  | 			log.Error(copyError.Error()) | ||||||
|  | 		} else { | ||||||
|  | 			removeErr := os.Remove(from) | ||||||
|  | 			if removeErr != nil { | ||||||
|  | 				log.Errorf("failed removing original file: %s", from) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // thanks https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file-in-golang | ||||||
|  | func copyFileContents(src, dst string) (err error) { | ||||||
|  | 	in, err := os.Open(src) // nolint gosec | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer safelyCloseFile(in) | ||||||
|  | 	out, err := os.Create(dst) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer safelyCloseFile(out) | ||||||
|  | 	if _, err = io.Copy(out, in); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return out.Sync() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func safelyCloseFile(file *os.File) { | ||||||
|  | 	err := file.Close() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("Error closing file!") | ||||||
|  | 		log.Error(err.Error()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -18,6 +18,7 @@ type OperationType struct { | |||||||
| 
 | 
 | ||||||
| // operators TODO: | // operators TODO: | ||||||
| // - cookbook doc for common things | // - cookbook doc for common things | ||||||
|  | // - existStatus | ||||||
| // - write in place | // - write in place | ||||||
| // - mergeEmpty (sets only if the document is empty, do I do that now?) | // - mergeEmpty (sets only if the document is empty, do I do that now?) | ||||||
| // - compare ?? | // - compare ?? | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ import ( | |||||||
| 	"container/list" | 	"container/list" | ||||||
| 	"io" | 	"io" | ||||||
| 
 | 
 | ||||||
| 	"gopkg.in/yaml.v3" | 	yaml "gopkg.in/yaml.v3" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Printer interface { | type Printer interface { | ||||||
| @ -53,6 +53,13 @@ func (p *resultsPrinter) writeString(writer io.Writer, txt string) error { | |||||||
| 	return errorWriting | 	return errorWriting | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (p *resultsPrinter) safelyFlush(writer *bufio.Writer) { | ||||||
|  | 	if err := writer.Flush(); err != nil { | ||||||
|  | 		log.Error("Error flushing writer!") | ||||||
|  | 		log.Error(err.Error()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { | func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { | ||||||
| 	log.Debug("PrintResults for %v matches", matchingNodes.Len()) | 	log.Debug("PrintResults for %v matches", matchingNodes.Len()) | ||||||
| 	var err error | 	var err error | ||||||
| @ -66,7 +73,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	bufferedWriter := bufio.NewWriter(p.writer) | 	bufferedWriter := bufio.NewWriter(p.writer) | ||||||
| 	defer safelyFlush(bufferedWriter) | 	defer p.safelyFlush(bufferedWriter) | ||||||
| 
 | 
 | ||||||
| 	if matchingNodes.Len() == 0 { | 	if matchingNodes.Len() == 0 { | ||||||
| 		log.Debug("no matching results, nothing to print") | 		log.Debug("no matching results, nothing to print") | ||||||
|  | |||||||
| @ -9,8 +9,6 @@ import ( | |||||||
| 	yaml "gopkg.in/yaml.v3" | 	yaml "gopkg.in/yaml.v3" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| //TODO: convert to interface + struct |  | ||||||
| 
 |  | ||||||
| var treeNavigator = NewDataTreeNavigator() | var treeNavigator = NewDataTreeNavigator() | ||||||
| var treeCreator = NewPathTreeCreator() | var treeCreator = NewPathTreeCreator() | ||||||
| 
 | 
 | ||||||
| @ -52,54 +50,3 @@ func readDocuments(reader io.Reader, filename string, fileIndex int) (*list.List | |||||||
| 		currentIndex = currentIndex + 1 | 		currentIndex = currentIndex + 1 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // 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) |  | ||||||
| // 		log.Debug(renameError.Error()) |  | ||||||
| // 		// can't do this rename when running in docker to a file targeted in a mounted volume, |  | ||||||
| // 		// so gracefully degrade to copying the entire contents. |  | ||||||
| // 		if copyError := copyFileContents(from, to); copyError != nil { |  | ||||||
| // 			log.Errorf("Failed copying from %v to %v", from, to) |  | ||||||
| // 			log.Error(copyError.Error()) |  | ||||||
| // 		} else { |  | ||||||
| // 			removeErr := os.Remove(from) |  | ||||||
| // 			if removeErr != nil { |  | ||||||
| // 				log.Errorf("failed removing original file: %s", from) |  | ||||||
| // 			} |  | ||||||
| // 		} |  | ||||||
| // 	} |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| // thanks https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file-in-golang |  | ||||||
| // func copyFileContents(src, dst string) (err error) { |  | ||||||
| // 	in, err := os.Open(src) // nolint gosec |  | ||||||
| // 	if err != nil { |  | ||||||
| // 		return err |  | ||||||
| // 	} |  | ||||||
| // 	defer safelyCloseFile(in) |  | ||||||
| // 	out, err := os.Create(dst) |  | ||||||
| // 	if err != nil { |  | ||||||
| // 		return err |  | ||||||
| // 	} |  | ||||||
| // 	defer safelyCloseFile(out) |  | ||||||
| // 	if _, err = io.Copy(out, in); err != nil { |  | ||||||
| // 		return err |  | ||||||
| // 	} |  | ||||||
| // 	return out.Sync() |  | ||||||
| // } |  | ||||||
| 
 |  | ||||||
| func safelyFlush(writer *bufio.Writer) { |  | ||||||
| 	if err := writer.Flush(); err != nil { |  | ||||||
| 		log.Error("Error flushing writer!") |  | ||||||
| 		log.Error(err.Error()) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| func safelyCloseFile(file *os.File) { |  | ||||||
| 	err := file.Close() |  | ||||||
| 	if err != nil { |  | ||||||
| 		log.Error("Error closing file!") |  | ||||||
| 		log.Error(err.Error()) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | |||||||
							
								
								
									
										55
									
								
								pkg/yqlib/write_in_place_handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								pkg/yqlib/write_in_place_handler.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | package yqlib | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type WriteInPlaceHandler interface { | ||||||
|  | 	CreateTempFile() (*os.File, error) | ||||||
|  | 	FinishWriteInPlace(evaluatedSuccessfully bool) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type writeInPlaceHandler struct { | ||||||
|  | 	inputFilename string | ||||||
|  | 	tempFile      *os.File | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewWriteInPlaceHandler(inputFile string) WriteInPlaceHandler { | ||||||
|  | 
 | ||||||
|  | 	return &writeInPlaceHandler{inputFile, nil} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (w *writeInPlaceHandler) CreateTempFile() (*os.File, error) { | ||||||
|  | 	info, err := os.Stat(w.inputFilename) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	_, err = os.Stat(os.TempDir()) | ||||||
|  | 	if os.IsNotExist(err) { | ||||||
|  | 		err = os.Mkdir(os.TempDir(), 0700) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 	} else if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	file, err := ioutil.TempFile("", "temp") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = os.Chmod(file.Name(), info.Mode()) | ||||||
|  | 	w.tempFile = file | ||||||
|  | 	return file, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (w *writeInPlaceHandler) FinishWriteInPlace(evaluatedSuccessfully bool) { | ||||||
|  | 	safelyCloseFile(w.tempFile) | ||||||
|  | 	if evaluatedSuccessfully { | ||||||
|  | 		safelyRenameFile(w.tempFile.Name(), w.inputFilename) | ||||||
|  | 	} else { | ||||||
|  | 		os.Remove(w.tempFile.Name()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user