From 55d502bbca2912848c15bf1c687295d0fdd739a7 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Tue, 20 Apr 2021 08:40:39 +0200 Subject: [PATCH] Restore: Improve command flags and usage docs #1190 #1193 --- internal/commands/backup.go | 5 ++- internal/commands/restore.go | 72 ++++++++++++++++++++++++----------- internal/commands/start.go | 2 +- internal/photoprism/albums.go | 8 +++- 4 files changed, 59 insertions(+), 28 deletions(-) diff --git a/internal/commands/backup.go b/internal/commands/backup.go index 97f89a448..725981ff9 100644 --- a/internal/commands/backup.go +++ b/internal/commands/backup.go @@ -27,7 +27,7 @@ import ( var BackupCommand = cli.Command{ Name: "backup", Usage: "Creates album and index backups", - UsageText: `A custom index sql backup FILENAME may be passed as first argument. Use - for stdout.`, + UsageText: `A custom index sql backup FILENAME may be passed as first argument. Use - for stdout. By default, the backup path is searched.`, Flags: backupFlags, Action: backupAction, } @@ -60,7 +60,6 @@ func backupAction(ctx *cli.Context) error { // Use command argument as backup file name. indexFileName := ctx.Args().First() indexPath := ctx.String("index-path") - backupIndex := ctx.Bool("index") || indexFileName != "" || indexPath != "" albumsPath := ctx.String("albums-path") @@ -179,6 +178,8 @@ func backupAction(ctx *cli.Context) error { albumsPath = conf.AlbumsPath() } + log.Infof("backing up albums to %s", txt.Quote(albumsPath)) + if count, err := photoprism.BackupAlbums(albumsPath, true); err != nil { return err } else { diff --git a/internal/commands/restore.go b/internal/commands/restore.go index 517dcb2e1..e4a1f22d3 100644 --- a/internal/commands/restore.go +++ b/internal/commands/restore.go @@ -25,10 +25,11 @@ import ( // RestoreCommand configures the backup cli command. var RestoreCommand = cli.Command{ - Name: "restore", - Usage: "Restores album and index backups", - Flags: restoreFlags, - Action: restoreAction, + Name: "restore", + Usage: "Restores album and index backups", + UsageText: `A custom index sql backup FILENAME may be passed as first argument. By default, the backup path is searched.`, + Flags: restoreFlags, + Action: restoreAction, } var restoreFlags = []cli.Flag{ @@ -40,15 +41,31 @@ var restoreFlags = []cli.Flag{ Name: "albums, a", Usage: "restore album yaml file backups", }, + cli.StringFlag{ + Name: "albums-path", + Usage: "custom album yaml file backup `PATH`", + }, cli.BoolFlag{ Name: "index, i", - Usage: "restore index database backup", + Usage: "restore index sql database backup", + }, + cli.StringFlag{ + Name: "index-path", + Usage: "custom index sql database backup `PATH`", }, } // restoreAction restores a database backup. func restoreAction(ctx *cli.Context) error { - if !ctx.Bool("index") && !ctx.Bool("albums") { + // Use command argument as backup file name. + indexFileName := ctx.Args().First() + indexPath := ctx.String("index-path") + restoreIndex := ctx.Bool("index") || indexFileName != "" || indexPath != "" + + albumsPath := ctx.String("albums-path") + restoreAlbums := ctx.Bool("albums") || albumsPath != "" + + if !restoreIndex && !restoreAlbums { for _, flag := range restoreFlags { fmt.Println(flag.String()) } @@ -67,30 +84,29 @@ func restoreAction(ctx *cli.Context) error { return err } - if ctx.Bool("index") { - // Use command argument as backup file name. - fileName := ctx.Args().First() - + if restoreIndex { // If empty, use default backup file name. - if fileName == "" { - backupPath := filepath.Join(conf.BackupPath(), conf.DatabaseDriver()) + if indexFileName == "" { + if indexPath == "" { + indexPath = filepath.Join(conf.BackupPath(), conf.DatabaseDriver()) + } - matches, err := filepath.Glob(filepath.Join(regexp.QuoteMeta(backupPath), "*.sql")) + matches, err := filepath.Glob(filepath.Join(regexp.QuoteMeta(indexPath), "*.sql")) if err != nil { return err } if len(matches) == 0 { - log.Errorf("no backup files found in %s", backupPath) + log.Errorf("no backup files found in %s", indexPath) return nil } - fileName = matches[len(matches)-1] + indexFileName = matches[len(matches)-1] } - if !fs.FileExists(fileName) { - log.Errorf("backup file not found: %s", fileName) + if !fs.FileExists(indexFileName) { + log.Errorf("backup file not found: %s", indexFileName) return nil } @@ -108,9 +124,9 @@ func restoreAction(ctx *cli.Context) error { log.Warnf("replacing existing index with %d photos", counts.Photos) } - log.Infof("restoring index from %s", txt.Quote(fileName)) + log.Infof("restoring index from %s", txt.Quote(indexFileName)) - sqlBackup, err := ioutil.ReadFile(fileName) + sqlBackup, err := ioutil.ReadFile(indexFileName) if err != nil { return err @@ -176,13 +192,23 @@ func restoreAction(ctx *cli.Context) error { conf.InitDb() - if ctx.Bool("albums") { + if restoreAlbums { service.SetConfig(conf) - if count, err := photoprism.RestoreAlbums(true); err != nil { - return err + if albumsPath == "" { + albumsPath = conf.AlbumsPath() + } + + if !fs.PathExists(albumsPath) { + log.Warnf("albums path %s not found", txt.Quote(albumsPath)) } else { - log.Infof("%d albums restored from yaml files", count) + log.Infof("restoring albums from %s", txt.Quote(albumsPath)) + + if count, err := photoprism.RestoreAlbums(albumsPath, true); err != nil { + return err + } else { + log.Infof("%d albums restored from yaml files", count) + } } } diff --git a/internal/commands/start.go b/internal/commands/start.go index 9f04493d0..c5849e015 100644 --- a/internal/commands/start.go +++ b/internal/commands/start.go @@ -111,7 +111,7 @@ func startAction(ctx *cli.Context) error { // start web server go server.Start(cctx, conf) - if count, err := photoprism.RestoreAlbums(false); err != nil { + if count, err := photoprism.RestoreAlbums(conf.AlbumsPath(), false); err != nil { log.Errorf("restore: %s", err) } else if count > 0 { log.Infof("%d albums restored", count) diff --git a/internal/photoprism/albums.go b/internal/photoprism/albums.go index f21c4966b..229b7ac87 100644 --- a/internal/photoprism/albums.go +++ b/internal/photoprism/albums.go @@ -46,7 +46,7 @@ func BackupAlbums(backupPath string, force bool) (count int, result error) { } // RestoreAlbums restores all album YAML file backups. -func RestoreAlbums(force bool) (count int, result error) { +func RestoreAlbums(backupPath string, force bool) (count int, result error) { c := Config() if !c.BackupYaml() && !force { @@ -65,7 +65,11 @@ func RestoreAlbums(force bool) (count int, result error) { return count, nil } - albums, err := filepath.Glob(regexp.QuoteMeta(c.AlbumsPath()) + "/**/*.yml") + if !fs.PathExists(backupPath) { + backupPath = c.AlbumsPath() + } + + albums, err := filepath.Glob(regexp.QuoteMeta(backupPath) + "/**/*.yml") if oAlbums, oErr := filepath.Glob(regexp.QuoteMeta(c.OriginalsAlbumsPath()) + "/**/*.yml"); oErr == nil { err = nil