nsfwapp/backend/settings_sqlite_move.go
2026-06-23 15:22:08 +02:00

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