restic/cmd/restic/cmd_migrate.go
Jason Cox 2447f3f110 Update usage strings to put flags before args
The standard UNIX-style ordering of command-line arguments places
optional flags before other positional arguments. All of restic's
commands support this ordering, but some of the usage strings showed the
flags after the positional arguments (which restic also parses just
fine). This change updates the doc strings to reflect the standard
ordering.

Because the `restic help` command comes directly from Cobra, there does
not appear to be a way to update the argument ordering in its usage
string, so it maintains the non-standard ordering (positional arguments
before optional flags).
2020-08-28 02:16:22 +00:00

113 lines
2.5 KiB
Go

package main
import (
"github.com/restic/restic/internal/migrations"
"github.com/restic/restic/internal/restic"
"github.com/spf13/cobra"
)
var cmdMigrate = &cobra.Command{
Use: "migrate [flags] [name]",
Short: "Apply migrations",
Long: `
The "migrate" command applies migrations to a repository. When no migration
name is explicitly given, a list of migrations that can be applied is printed.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runMigrate(migrateOptions, globalOptions, args)
},
}
// MigrateOptions bundles all options for the 'check' command.
type MigrateOptions struct {
Force bool
}
var migrateOptions MigrateOptions
func init() {
cmdRoot.AddCommand(cmdMigrate)
f := cmdMigrate.Flags()
f.BoolVarP(&migrateOptions.Force, "force", "f", false, `apply a migration a second time`)
}
func checkMigrations(opts MigrateOptions, gopts GlobalOptions, repo restic.Repository) error {
ctx := gopts.ctx
Printf("available migrations:\n")
for _, m := range migrations.All {
ok, err := m.Check(ctx, repo)
if err != nil {
return err
}
if ok {
Printf(" %v: %v\n", m.Name(), m.Desc())
}
}
return nil
}
func applyMigrations(opts MigrateOptions, gopts GlobalOptions, repo restic.Repository, args []string) error {
ctx := gopts.ctx
var firsterr error
for _, name := range args {
for _, m := range migrations.All {
if m.Name() == name {
ok, err := m.Check(ctx, repo)
if err != nil {
return err
}
if !ok {
if !opts.Force {
Warnf("migration %v cannot be applied: check failed\nIf you want to apply this migration anyway, re-run with option --force\n", m.Name())
continue
}
Warnf("check for migration %v failed, continuing anyway\n", m.Name())
}
Printf("applying migration %v...\n", m.Name())
if err = m.Apply(ctx, repo); err != nil {
Warnf("migration %v failed: %v\n", m.Name(), err)
if firsterr == nil {
firsterr = err
}
continue
}
Printf("migration %v: success\n", m.Name())
}
}
}
return firsterr
}
func runMigrate(opts MigrateOptions, gopts GlobalOptions, args []string) error {
repo, err := OpenRepository(gopts)
if err != nil {
return err
}
lock, err := lockRepoExclusive(repo)
defer unlockRepo(lock)
if err != nil {
return err
}
if len(args) == 0 {
return checkMigrations(opts, gopts, repo)
}
return applyMigrations(opts, gopts, repo, args)
}