117 lines
2.9 KiB
Go
117 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func sqlitePathChanged(current, next RecorderSettings) bool {
|
|
return normalizeDatabaseType(current.DatabaseType) == databaseTypeSQLite &&
|
|
normalizeDatabaseType(next.DatabaseType) == databaseTypeSQLite &&
|
|
normalizeSQLitePath(current.SQLitePath) != normalizeSQLitePath(next.SQLitePath)
|
|
}
|
|
|
|
func moveSQLiteDatabaseForSettings(current, next RecorderSettings) error {
|
|
currentConfig, err := buildModelStoreConfigFromRecorderSettings(current)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
nextConfig, err := buildModelStoreConfigFromRecorderSettings(next)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return moveSQLiteDatabaseFiles(currentConfig.SQLitePath, nextConfig.SQLitePath)
|
|
}
|
|
|
|
func restoreModelStoreForSettings(rec RecorderSettings) {
|
|
config, err := buildModelStoreConfigFromRecorderSettings(rec)
|
|
if err != nil {
|
|
return
|
|
}
|
|
store := NewModelStore(config)
|
|
if err := store.Load(); err != nil {
|
|
_ = store.Close()
|
|
return
|
|
}
|
|
setModelStore(store)
|
|
}
|
|
|
|
func moveSQLiteDatabaseFiles(sourcePath, targetPath string) error {
|
|
sourcePath = filepath.Clean(strings.TrimSpace(sourcePath))
|
|
targetPath = filepath.Clean(strings.TrimSpace(targetPath))
|
|
if sourcePath == "" || targetPath == "" {
|
|
return errors.New("sqlite source/target path fehlt")
|
|
}
|
|
if sourcePath == targetPath {
|
|
return nil
|
|
}
|
|
|
|
sourceInfo, err := os.Stat(sourcePath)
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if sourceInfo.IsDir() {
|
|
return appErrorf("sqlite source path ist ein ordner: %s", sourcePath)
|
|
}
|
|
|
|
if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, target := range append([]string{targetPath}, sqliteSidecarPaths(targetPath)...) {
|
|
if _, err := os.Stat(target); err == nil {
|
|
return appErrorf("Ziel-Datei existiert bereits: %s", target)
|
|
} else if err != nil && !errors.Is(err, os.ErrNotExist) {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if store := getModelStore(); store != nil && store.isSQLite() && store.db != nil {
|
|
_, _ = store.db.Exec(`PRAGMA wal_checkpoint(TRUNCATE);`)
|
|
_ = store.Close()
|
|
}
|
|
|
|
if err := moveDatabaseFile(sourcePath, targetPath); err != nil {
|
|
return err
|
|
}
|
|
|
|
sourceSidecars := sqliteSidecarPaths(sourcePath)
|
|
targetSidecars := sqliteSidecarPaths(targetPath)
|
|
for i, source := range sourceSidecars {
|
|
if _, err := os.Stat(source); errors.Is(err, os.ErrNotExist) {
|
|
continue
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
if err := moveDatabaseFile(source, targetSidecars[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func sqliteSidecarPaths(path string) []string {
|
|
return []string{
|
|
path + "-wal",
|
|
path + "-shm",
|
|
path + "-journal",
|
|
}
|
|
}
|
|
|
|
func moveDatabaseFile(sourcePath, targetPath string) error {
|
|
if err := renameWithRetry(sourcePath, targetPath); err == nil {
|
|
return nil
|
|
}
|
|
|
|
if _, err := copyDatabaseFile(sourcePath, targetPath); err != nil {
|
|
return err
|
|
}
|
|
return removeWithRetry(sourcePath)
|
|
}
|