package util
import (
"bufio"
"encoding/json"
"io"
"io/ioutil"
"os"
"path"
)
func EnsureFileExists(file string) error {
if _, err := os.Stat(file); os.IsNotExist(err) {
os.MkdirAll(path.Dir(file), 0755)
f, err := os.Create(file);
if err != nil {
return err
}
f.Close()
}
return nil
}
// AddLineTo appends the line to the file, unless it already exists.
// If the file doesn't exist, it will be created, including directories.
func AddLineTo(file string, line string) error {
if !LineExistsIn(file, line) {
if fileIsMissingNewline(file) {
err := AppendStringTo(file, "\n")
if err != nil {
return err
}
}
return AppendStringTo(file, line + "\n")
}
return nil
}
// LineExistsIn returns true if the line exists in the file.
func LineExistsIn(file string, line string) bool {
// read one line at a time
f, err := os.Open(file)
if err != nil {
return false
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
if scanner.Text() == line {
return true
}
}
return false
}
// isFileEmpty returns true if the file is empty or non-existent.
func isFileEmpty(file string) bool {
f, err := os.Open(file)
if err != nil {
return true
}
defer f.Close()
_, err = f.Seek(0, 2)
return err == nil
}
// AppendStringTo appends the string to the file.
func AppendStringTo(file string, str string) error {
EnsureFileExists(file)
f, err := os.OpenFile(file, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = io.WriteString(f, str)
return err
}
// ReadJsonFile parses the contents of 'file' as a JSON object.
func ReadJsonFile(file string, obj interface{}) error {
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()
return json.NewDecoder(f).Decode(obj)
}
// fileIsMissingNewline returns true if the file ends in a non-newline byte.
func fileIsMissingNewline(file string) bool {
f, err := os.Open(file)
if err != nil {
return false
}
defer f.Close()
_, err = f.Seek(-1, 2)
if err != nil {
return false
}
b := make([]byte, 1)
_, err = f.Read(b)
return err != nil || b[0] != '\n'
}
// ReadDir reads all the files in the directory.
// Obviously, don't do this if the whole contents don't fit in RAM.
func ReadDir(dir string) (map[string]string, error) {
files, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
res := make(map[string]string)
for _, f := range files {
fpath := path.Join(dir, f.Name())
contents, err := ioutil.ReadFile(fpath)
if err != nil {
return nil, err
}
res[f.Name()] = string(contents)
}
return res, nil
}
func IsDir(fpath string) bool {
fi, err := os.Stat(fpath)
return err == nil && fi.IsDir()
}