mirror of
https://github.com/photoprism/photoprism.git
synced 2025-12-12 00:34:13 +01:00
Backups: Improve command-line backup and restore commands #4243
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
@@ -91,7 +91,7 @@ func backupAction(ctx *cli.Context) error {
|
|||||||
if fileName == "" {
|
if fileName == "" {
|
||||||
if !fs.PathWritable(databasePath) {
|
if !fs.PathWritable(databasePath) {
|
||||||
if databasePath != "" {
|
if databasePath != "" {
|
||||||
log.Warnf("backup: specified database backup path not writable, using default backup path")
|
log.Warnf("backup: specified database backup path is not writable, using default directory instead")
|
||||||
}
|
}
|
||||||
|
|
||||||
databasePath = conf.BackupDatabasePath()
|
databasePath = conf.BackupDatabasePath()
|
||||||
@@ -109,7 +109,7 @@ func backupAction(ctx *cli.Context) error {
|
|||||||
if backupAlbums {
|
if backupAlbums {
|
||||||
if !fs.PathWritable(albumsPath) {
|
if !fs.PathWritable(albumsPath) {
|
||||||
if albumsPath != "" {
|
if albumsPath != "" {
|
||||||
log.Warnf("backup: specified album backup path not writable, using default backup path")
|
log.Warnf("backup: specified albums backup path is not writable, using default directory instead")
|
||||||
}
|
}
|
||||||
|
|
||||||
albumsPath = conf.BackupAlbumsPath()
|
albumsPath = conf.BackupAlbumsPath()
|
||||||
|
|||||||
@@ -98,12 +98,12 @@ func restoreAction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !fs.PathExists(albumsPath) {
|
if !fs.PathExists(albumsPath) {
|
||||||
log.Warnf("restore: album files path %s not found", clean.Log(albumsPath))
|
log.Warnf("restore: failed to open %s, album backups cannot be restored", clean.Log(albumsPath))
|
||||||
} else {
|
} else {
|
||||||
log.Infof("restore: restoring albums from %s", clean.Log(albumsPath))
|
log.Infof("restore: restoring album backups from %s", clean.Log(albumsPath))
|
||||||
|
|
||||||
if count, err := photoprism.RestoreAlbums(albumsPath, true); err != nil {
|
if count, restoreErr := photoprism.RestoreAlbums(albumsPath, true); restoreErr != nil {
|
||||||
return err
|
return restoreErr
|
||||||
} else {
|
} else {
|
||||||
log.Infof("restore: restored %s from YAML files", english.Plural(count, "album", "albums"))
|
log.Infof("restore: restored %s from YAML files", english.Plural(count, "album", "albums"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/dustin/go-humanize/english"
|
||||||
"github.com/sevlyar/go-daemon"
|
"github.com/sevlyar/go-daemon"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
|
||||||
@@ -126,9 +127,9 @@ func startAction(ctx *cli.Context) error {
|
|||||||
|
|
||||||
// Restore albums from YAML files.
|
// Restore albums from YAML files.
|
||||||
if count, restoreErr := photoprism.RestoreAlbums(conf.BackupAlbumsPath(), false); restoreErr != nil {
|
if count, restoreErr := photoprism.RestoreAlbums(conf.BackupAlbumsPath(), false); restoreErr != nil {
|
||||||
log.Errorf("restore: %s", restoreErr)
|
log.Errorf("restore: %s (albums)", restoreErr)
|
||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
log.Infof("%d albums restored", count)
|
log.Infof("restore: %s restored", english.Plural(count, "album backup", "album backups"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start worker that periodically deletes expired sessions.
|
// Start worker that periodically deletes expired sessions.
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func RestoreAlbums(backupPath string, force bool) (count int, result error) {
|
|||||||
c := Config()
|
c := Config()
|
||||||
|
|
||||||
if !c.BackupAlbums() && !force {
|
if !c.BackupAlbums() && !force {
|
||||||
log.Debugf("restore: album metadata backups are disabled")
|
log.Debugf("albums: metadata backup files are disabled")
|
||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ func RestoreAlbums(backupPath string, force bool) (count int, result error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(existing) > 0 && !force {
|
if len(existing) > 0 && !force {
|
||||||
log.Debugf("restore: found existing albums, backup not restored")
|
log.Debugf("albums: skipped restoring backups because albums already exist")
|
||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,14 +57,14 @@ func RestoreAlbums(backupPath string, force bool) (count int, result error) {
|
|||||||
a := entity.Album{}
|
a := entity.Album{}
|
||||||
|
|
||||||
if err = a.LoadFromYaml(fileName); err != nil {
|
if err = a.LoadFromYaml(fileName); err != nil {
|
||||||
log.Errorf("restore: %s in %s", err, clean.Log(filepath.Base(fileName)))
|
log.Errorf("albums: %s in %s (restore)", err, clean.Log(filepath.Base(fileName)))
|
||||||
result = err
|
result = err
|
||||||
} else if a.AlbumType == "" || len(a.Photos) == 0 && a.AlbumFilter == "" {
|
} else if a.AlbumType == "" || len(a.Photos) == 0 && a.AlbumFilter == "" {
|
||||||
log.Debugf("restore: skipping %s", clean.Log(filepath.Base(fileName)))
|
log.Debugf("albums: skipped %s (restore)", clean.Log(filepath.Base(fileName)))
|
||||||
} else if found := a.Find(); found != nil {
|
} else if found := a.Find(); found != nil {
|
||||||
log.Infof("%s: %s already exists", found.AlbumType, clean.Log(found.AlbumTitle))
|
log.Infof("%s: %s already exists (restore)", found.AlbumType, clean.Log(found.AlbumTitle))
|
||||||
} else if err = a.Create(); err != nil {
|
} else if err = a.Create(); err != nil {
|
||||||
log.Errorf("%s: %s in %s", a.AlbumType, err, clean.Log(filepath.Base(fileName)))
|
log.Errorf("%s: %s in %s (restore)", a.AlbumType, err, clean.Log(filepath.Base(fileName)))
|
||||||
} else {
|
} else {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func RestoreDatabase(backupPath, fileName string, fromStdIn, force bool) (err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
return fmt.Errorf("found no database backup files in %s", backupPath)
|
return fmt.Errorf("failed to find a backup in %s, index cannot be restored", backupPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(files)
|
sort.Strings(files)
|
||||||
@@ -50,22 +50,22 @@ func RestoreDatabase(backupPath, fileName string, fromStdIn, force bool) (err er
|
|||||||
fileName = files[len(files)-1]
|
fileName = files[len(files)-1]
|
||||||
|
|
||||||
if !fs.FileExistsNotEmpty(fileName) {
|
if !fs.FileExistsNotEmpty(fileName) {
|
||||||
return fmt.Errorf("no database backup found in %s", filepath.Base(fileName))
|
return fmt.Errorf("failed to open %s, index cannot be restored", filepath.Base(fileName))
|
||||||
}
|
}
|
||||||
} else if backupPath == "" {
|
} else if backupPath == "" {
|
||||||
if absName, absErr := filepath.Abs(fileName); absErr == nil && fs.FileExists(absName) {
|
if absName, absErr := filepath.Abs(fileName); absErr == nil && fs.FileExists(absName) {
|
||||||
fileName = absName
|
fileName = absName
|
||||||
} else if dir := filepath.Dir(fileName); dir != "" && dir != "." {
|
} else if dir := filepath.Dir(fileName); dir != "" && dir != "." {
|
||||||
return fmt.Errorf("file %s not found", clean.Log(fileName))
|
return fmt.Errorf("failed to find %s, index cannot be restored", clean.Log(fileName))
|
||||||
} else if absName = filepath.Join(c.BackupDatabasePath(), fileName); !fs.FileExists(absName) {
|
} else if absName = filepath.Join(c.BackupDatabasePath(), fileName); !fs.FileExists(absName) {
|
||||||
return fmt.Errorf("file %s not found in %s backup path", clean.Log(fileName), clean.Log(filepath.Base(c.BackupDatabasePath())))
|
return fmt.Errorf("failed to find %s in the %s backup path, index cannot be restored", clean.Log(fileName), clean.Log(filepath.Base(c.BackupDatabasePath())))
|
||||||
} else {
|
} else {
|
||||||
fileName = absName
|
fileName = absName
|
||||||
}
|
}
|
||||||
} else if absName, absErr := filepath.Abs(filepath.Join(backupPath, fileName)); absErr == nil && fs.FileExists(absName) {
|
} else if absName, absErr := filepath.Abs(filepath.Join(backupPath, fileName)); absErr == nil && fs.FileExists(absName) {
|
||||||
fileName = absName
|
fileName = absName
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("file %s not found in %s", clean.Log(filepath.Base(fileName)), clean.Log(backupPath))
|
return fmt.Errorf("failed to find %s in %s, index cannot be restored", clean.Log(filepath.Base(fileName)), clean.Log(backupPath))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,13 +144,15 @@ func RestoreDatabase(backupPath, fileName string, fromStdIn, force bool) (err er
|
|||||||
|
|
||||||
// Run restore command.
|
// Run restore command.
|
||||||
if cmdErr := cmd.Run(); cmdErr != nil {
|
if cmdErr := cmd.Run(); cmdErr != nil {
|
||||||
log.Errorf("restore: failed to restore database backup")
|
log.Errorf("restore: failed to restore index database")
|
||||||
|
|
||||||
if errStr := strings.TrimSpace(stderr.String()); errStr != "" {
|
if errStr := strings.TrimSpace(stderr.String()); errStr != "" {
|
||||||
return errors.New(errStr)
|
return errors.New(errStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmdErr
|
return cmdErr
|
||||||
|
} else {
|
||||||
|
log.Infof("restore: index database successfully restored")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user