Files
gocryptotrader/common/file/file.go
Rauno Ots 8c86aac21d Config: fix don't create empty dir when resolving path (#575)
* Config: fix don't create empty dir when resolving path

* refactor migration of default config file

* gracefully handle src == target on Move
* create target directory on Move, if necessary

* unify resolution of default config location

* refactor the use of flagSet to be explicit
* remove package variable
* use empty config file path setting if not set in flags
* resolve default file location the same way when showing the target and
when loading default config file

* don't migrate if target file is the same as source

* rename configfile to configFile

* add migrateConfig tests
2020-10-15 13:24:43 +11:00

112 lines
2.3 KiB
Go

package file
import (
"bytes"
"encoding/csv"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
)
// Write writes selected data to a file or returns an error if it fails. This
// func also ensures that all files are set to this permission (only rw access
// for the running user and the group the user is a member of)
func Write(file string, data []byte) error {
basePath := filepath.Dir(file)
if !Exists(basePath) {
if err := os.MkdirAll(basePath, 0770); err != nil {
return err
}
}
return ioutil.WriteFile(file, data, 0770)
}
// Move moves a file from a source path to a destination path
// This must be used across the codebase for compatibility with Docker volumes
// and Golang (fixes Invalid cross-device link when using os.Rename)
func Move(sourcePath, destPath string) error {
sourceAbs, err := filepath.Abs(sourcePath)
if err != nil {
return err
}
destAbs, err := filepath.Abs(destPath)
if err != nil {
return err
}
if sourceAbs == destAbs {
return nil
}
inputFile, err := os.Open(sourcePath)
if err != nil {
return err
}
destDir := filepath.Dir(destPath)
if !Exists(destDir) {
err = os.MkdirAll(destDir, 0770)
if err != nil {
return err
}
}
outputFile, err := os.Create(destPath)
if err != nil {
inputFile.Close()
return err
}
_, err = io.Copy(outputFile, inputFile)
inputFile.Close()
outputFile.Close()
if err != nil {
if errRem := os.Remove(destPath); errRem != nil {
return fmt.Errorf(
"unable to os.Remove error: %s after io.Copy error: %s",
errRem,
err,
)
}
return err
}
return os.Remove(sourcePath)
}
// Exists returns whether or not a file or path exists
func Exists(name string) bool {
_, err := os.Stat(name)
return !os.IsNotExist(err)
}
// WriteAsCSV takes a table of records and writes it as CSV
func WriteAsCSV(filename string, records [][]string) error {
if len(records) == 0 {
return errors.New("no records in matrix")
}
buf := bytes.Buffer{}
w := csv.NewWriter(&buf)
alignment := len(records[0])
for i := range records {
if len(records[i]) != alignment {
return errors.New("incorrect alignment")
}
err := w.Write(records[i])
if err != nil {
return err
}
}
w.Flush()
err := w.Error()
if err != nil {
return err
}
return Write(filename, buf.Bytes())
}