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:
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:
|
||||
// - cookbook doc for common things
|
||||
// - existStatus
|
||||
// - write in place
|
||||
// - mergeEmpty (sets only if the document is empty, do I do that now?)
|
||||
// - compare ??
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"container/list"
|
||||
"io"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Printer interface {
|
||||
@@ -53,6 +53,13 @@ func (p *resultsPrinter) writeString(writer io.Writer, txt string) error {
|
||||
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 {
|
||||
log.Debug("PrintResults for %v matches", matchingNodes.Len())
|
||||
var err error
|
||||
@@ -66,7 +73,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
|
||||
}
|
||||
|
||||
bufferedWriter := bufio.NewWriter(p.writer)
|
||||
defer safelyFlush(bufferedWriter)
|
||||
defer p.safelyFlush(bufferedWriter)
|
||||
|
||||
if matchingNodes.Len() == 0 {
|
||||
log.Debug("no matching results, nothing to print")
|
||||
|
||||
@@ -9,8 +9,6 @@ import (
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
//TODO: convert to interface + struct
|
||||
|
||||
var treeNavigator = NewDataTreeNavigator()
|
||||
var treeCreator = NewPathTreeCreator()
|
||||
|
||||
@@ -52,54 +50,3 @@ func readDocuments(reader io.Reader, filename string, fileIndex int) (*list.List
|
||||
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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user