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() }