github.com/mckael/restic@v0.8.3/cmd/restic/cmd_migrate.go (about)

     1  package main
     2  
     3  import (
     4  	"github.com/restic/restic/internal/migrations"
     5  	"github.com/restic/restic/internal/restic"
     6  
     7  	"github.com/spf13/cobra"
     8  )
     9  
    10  var cmdMigrate = &cobra.Command{
    11  	Use:   "migrate [name]",
    12  	Short: "Apply migrations",
    13  	Long: `
    14  The "migrate" command applies migrations to a repository. When no migration
    15  name is explicitly given, a list of migrations that can be applied is printed.
    16  `,
    17  	DisableAutoGenTag: true,
    18  	RunE: func(cmd *cobra.Command, args []string) error {
    19  		return runMigrate(migrateOptions, globalOptions, args)
    20  	},
    21  }
    22  
    23  // MigrateOptions bundles all options for the 'check' command.
    24  type MigrateOptions struct {
    25  	Force bool
    26  }
    27  
    28  var migrateOptions MigrateOptions
    29  
    30  func init() {
    31  	cmdRoot.AddCommand(cmdMigrate)
    32  	f := cmdMigrate.Flags()
    33  	f.BoolVarP(&migrateOptions.Force, "force", "f", false, `apply a migration a second time`)
    34  }
    35  
    36  func checkMigrations(opts MigrateOptions, gopts GlobalOptions, repo restic.Repository) error {
    37  	ctx := gopts.ctx
    38  	Printf("available migrations:\n")
    39  	for _, m := range migrations.All {
    40  		ok, err := m.Check(ctx, repo)
    41  		if err != nil {
    42  			return err
    43  		}
    44  
    45  		if ok {
    46  			Printf("  %v: %v\n", m.Name(), m.Desc())
    47  		}
    48  	}
    49  
    50  	return nil
    51  }
    52  
    53  func applyMigrations(opts MigrateOptions, gopts GlobalOptions, repo restic.Repository, args []string) error {
    54  	ctx := gopts.ctx
    55  
    56  	var firsterr error
    57  	for _, name := range args {
    58  		for _, m := range migrations.All {
    59  			if m.Name() == name {
    60  				ok, err := m.Check(ctx, repo)
    61  				if err != nil {
    62  					return err
    63  				}
    64  
    65  				if !ok {
    66  					if !opts.Force {
    67  						Warnf("migration %v cannot be applied: check failed\nIf you want to apply this migration anyway, re-run with option --force\n", m.Name())
    68  						continue
    69  					}
    70  
    71  					Warnf("check for migration %v failed, continuing anyway\n", m.Name())
    72  				}
    73  
    74  				Printf("applying migration %v...\n", m.Name())
    75  				if err = m.Apply(ctx, repo); err != nil {
    76  					Warnf("migration %v failed: %v\n", m.Name(), err)
    77  					if firsterr == nil {
    78  						firsterr = err
    79  					}
    80  					continue
    81  				}
    82  
    83  				Printf("migration %v: success\n", m.Name())
    84  			}
    85  		}
    86  	}
    87  
    88  	return firsterr
    89  }
    90  
    91  func runMigrate(opts MigrateOptions, gopts GlobalOptions, args []string) error {
    92  	repo, err := OpenRepository(gopts)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	lock, err := lockRepoExclusive(repo)
    98  	defer unlockRepo(lock)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	if len(args) == 0 {
   104  		return checkMigrations(opts, gopts, repo)
   105  	}
   106  
   107  	return applyMigrations(opts, gopts, repo, args)
   108  }