airobot/storage/storage_os.go
2022-12-12 08:30:21 +08:00

118 lines
2.3 KiB
Go

package storage
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
)
var _ Storage = (*OSStorage)(nil)
type OSStorage struct {
root string
}
func NewOSStorage() (Storage, error) {
urd, err := os.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("不能获取默认的根目录 : %w", err)
}
return NewOSStorageRooted(urd)
}
func NewOSStorageRooted(root string) (Storage, error) {
if !filepath.IsAbs(root) {
return nil, fmt.Errorf("root必须是绝对路径:%s", root)
}
storageRoot := filepath.Join(root, ".df")
s := &OSStorage{root: storageRoot}
mighted, err := s.migrateDeprecatedRootStorage()
if mighted {
if err != nil {
return nil, fmt.Errorf("找到不推荐使用的存储,但无法移动到新位置:%w", err)
}
return s, nil
}
err = s.mkdirIfNotExists(storageRootPath(s))
return s, err
}
func (s *OSStorage) Root() string {
return s.root
}
func (s *OSStorage) LoadConfig() (*Config, error) {
configFile := configPath(s)
f, err := os.Open(configFile)
if os.IsNotExist(err) {
return newDefaultConfig(), nil
}
if err != nil {
return newDefaultConfig(), fmt.Errorf("没有读到 URI:%w", err)
}
defer f.Close()
config := &Config{}
err = json.NewDecoder(f).Decode(config)
if err != nil {
return newDefaultConfig(), err
}
return config, nil
}
func (s *OSStorage) StoreConfig(config *Config) error {
configFile := configPath(s)
w, err := s.createFile(configFile)
if err != nil {
return err
}
defer w.Close()
return json.NewEncoder(w).Encode(config)
}
func (s *OSStorage) createFile(name string) (*os.File, error) {
return os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
}
func (s *OSStorage) isExist(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
func (s *OSStorage) mkdirIfNotExists(dir string) error {
if s.isExist(dir) {
return nil
}
return os.MkdirAll(dir, 0700)
}
// 合并弃用的根目录
func (s *OSStorage) migrateDeprecatedRootStorage() (bool, error) {
oldRoot, err := os.UserConfigDir()
if err != nil {
return false, err
}
src := filepath.Join(oldRoot, "fyne", ID, "vvv")
_, err = os.Stat(src)
if os.IsNotExist(err) {
return false, err
}
dest := storageRootPath(s)
err = os.Rename(src, dest)
if err != nil {
return false, err
}
return true, nil
}