2447f3f110
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).
113 lines
2.5 KiB
Go
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)
|
|
}
|