2020-06-02 19:16:02 +01:00
|
|
|
package persistence
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2020-06-11 19:04:53 +01:00
|
|
|
"log"
|
2020-06-02 19:16:02 +01:00
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
)
|
|
|
|
|
|
|
|
// dataPath global path for persistence
|
|
|
|
var dataPath = os.TempDir()
|
|
|
|
|
|
|
|
// SetPath sets the persistent path for the data storage
|
2020-06-10 12:32:15 +01:00
|
|
|
func SetPath(p string) error {
|
|
|
|
if info, err := os.Stat(p); err != nil {
|
2020-06-02 19:16:02 +01:00
|
|
|
return err
|
|
|
|
} else if !info.IsDir() {
|
|
|
|
return fmt.Errorf("path for persistence is not directory")
|
|
|
|
}
|
2020-06-10 12:32:15 +01:00
|
|
|
dataPath = p
|
2020-06-02 19:16:02 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Converts name to a full path
|
|
|
|
func jsonPath(name string) string {
|
|
|
|
return path.Join(dataPath, fmt.Sprintf("rove-%s.json", name))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save will serialise the interface into a json file
|
|
|
|
func Save(name string, data interface{}) error {
|
2020-06-10 12:32:15 +01:00
|
|
|
p := jsonPath(name)
|
2020-06-30 23:59:58 +01:00
|
|
|
b, err := json.MarshalIndent(data, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := ioutil.WriteFile(p, b, os.ModePerm); err != nil {
|
2020-06-02 19:16:02 +01:00
|
|
|
return err
|
|
|
|
}
|
2020-06-07 18:08:34 +01:00
|
|
|
|
2020-06-11 19:04:53 +01:00
|
|
|
log.Printf("Saved %s\n", p)
|
2020-06-02 19:16:02 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load will load the interface from the json file
|
|
|
|
func Load(name string, data interface{}) error {
|
2020-06-10 12:32:15 +01:00
|
|
|
p := jsonPath(name)
|
2020-06-02 19:16:02 +01:00
|
|
|
// Don't load anything if the file doesn't exist
|
2020-06-10 12:32:15 +01:00
|
|
|
_, err := os.Stat(p)
|
2020-06-02 19:16:02 +01:00
|
|
|
if os.IsNotExist(err) {
|
2020-06-11 19:04:53 +01:00
|
|
|
log.Printf("File %s didn't exist, loading with fresh data\n", p)
|
2020-06-02 19:16:02 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read and unmarshal the json
|
2020-06-10 12:32:15 +01:00
|
|
|
if b, err := ioutil.ReadFile(p); err != nil {
|
2020-06-02 19:16:02 +01:00
|
|
|
return err
|
2020-06-03 12:58:10 +01:00
|
|
|
} else if len(b) == 0 {
|
2020-06-11 19:04:53 +01:00
|
|
|
log.Printf("File %s was empty, loading with fresh data\n", p)
|
2020-06-07 18:08:34 +01:00
|
|
|
return nil
|
2020-06-02 19:16:02 +01:00
|
|
|
} else if err := json.Unmarshal(b, data); err != nil {
|
2020-06-10 12:32:15 +01:00
|
|
|
return fmt.Errorf("failed to load file %s error: %s", p, err)
|
2020-06-02 19:16:02 +01:00
|
|
|
}
|
2020-06-07 18:08:34 +01:00
|
|
|
|
2020-06-11 19:04:53 +01:00
|
|
|
log.Printf("Loaded %s\n", p)
|
2020-06-02 19:16:02 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// saveLoadFunc defines a type of function to save or load an interface
|
|
|
|
type saveLoadFunc func(string, interface{}) error
|
|
|
|
|
|
|
|
func doAll(f saveLoadFunc, args ...interface{}) error {
|
|
|
|
var name string
|
|
|
|
for i, a := range args {
|
|
|
|
if i%2 == 0 {
|
|
|
|
var ok bool
|
|
|
|
name, ok = a.(string)
|
|
|
|
if !ok {
|
2020-06-11 19:04:53 +01:00
|
|
|
return fmt.Errorf("incorrect args")
|
2020-06-02 19:16:02 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err := f(name, a); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SaveAll allows for saving multiple structures in a single call
|
|
|
|
func SaveAll(args ...interface{}) error {
|
|
|
|
return doAll(Save, args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// LoadAll allows for loading multiple structures in a single call
|
|
|
|
func LoadAll(args ...interface{}) error {
|
|
|
|
return doAll(Load, args...)
|
|
|
|
}
|