init: Add flag to specify created repository version

This commit is contained in:
Michael Eischer 2022-02-13 00:52:03 +01:00 committed by Alexander Neumann
parent 4b957e7373
commit 362ab06023
4 changed files with 42 additions and 10 deletions

View File

@ -1,10 +1,13 @@
package main package main
import ( import (
"strconv"
"github.com/restic/chunker" "github.com/restic/chunker"
"github.com/restic/restic/internal/backend/location" "github.com/restic/restic/internal/backend/location"
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -30,6 +33,7 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
type InitOptions struct { type InitOptions struct {
secondaryRepoOptions secondaryRepoOptions
CopyChunkerParameters bool CopyChunkerParameters bool
RepositoryVersion string
} }
var initOptions InitOptions var initOptions InitOptions
@ -40,9 +44,26 @@ func init() {
f := cmdInit.Flags() f := cmdInit.Flags()
initSecondaryRepoOptions(f, &initOptions.secondaryRepoOptions, "secondary", "to copy chunker parameters from") initSecondaryRepoOptions(f, &initOptions.secondaryRepoOptions, "secondary", "to copy chunker parameters from")
f.BoolVar(&initOptions.CopyChunkerParameters, "copy-chunker-params", false, "copy chunker parameters from the secondary repository (useful with the copy command)") f.BoolVar(&initOptions.CopyChunkerParameters, "copy-chunker-params", false, "copy chunker parameters from the secondary repository (useful with the copy command)")
f.StringVar(&initOptions.RepositoryVersion, "repository-version", "stable", "repository format version to use, allowed values are a format version, 'latest' and 'stable'")
} }
func runInit(opts InitOptions, gopts GlobalOptions, args []string) error { func runInit(opts InitOptions, gopts GlobalOptions, args []string) error {
var version uint
if opts.RepositoryVersion == "latest" || opts.RepositoryVersion == "" {
version = restic.MaxRepoVersion
} else if opts.RepositoryVersion == "stable" {
version = restic.StableRepoVersion
} else {
v, err := strconv.ParseUint(opts.RepositoryVersion, 10, 32)
if err != nil {
return errors.Fatal("invalid repository version")
}
version = uint(v)
}
if version < restic.MinRepoVersion || version > restic.MaxRepoVersion {
return errors.Fatalf("only repository versions between %v and %v are allowed", restic.MinRepoVersion, restic.MaxRepoVersion)
}
chunkerPolynomial, err := maybeReadChunkerPolynomial(opts, gopts) chunkerPolynomial, err := maybeReadChunkerPolynomial(opts, gopts)
if err != nil { if err != nil {
return err return err
@ -67,7 +88,7 @@ func runInit(opts InitOptions, gopts GlobalOptions, args []string) error {
s := repository.New(be) s := repository.New(be)
err = s.Init(gopts.ctx, gopts.password, chunkerPolynomial) err = s.Init(gopts.ctx, version, gopts.password, chunkerPolynomial)
if err != nil { if err != nil {
return errors.Fatalf("create key in repository at %s failed: %v\n", location.StripPassword(gopts.Repo), err) return errors.Fatalf("create key in repository at %s failed: %v\n", location.StripPassword(gopts.Repo), err)
} }

View File

@ -661,7 +661,15 @@ func (r *Repository) SearchKey(ctx context.Context, password string, maxKeys int
// Init creates a new master key with the supplied password, initializes and // Init creates a new master key with the supplied password, initializes and
// saves the repository config. // saves the repository config.
func (r *Repository) Init(ctx context.Context, password string, chunkerPolynomial *chunker.Pol) error { func (r *Repository) Init(ctx context.Context, version uint, password string, chunkerPolynomial *chunker.Pol) error {
if version > restic.MaxRepoVersion {
return fmt.Errorf("repo version %v too high", version)
}
if version < restic.MinRepoVersion {
return fmt.Errorf("repo version %v too low", version)
}
has, err := r.be.Test(ctx, restic.Handle{Type: restic.ConfigFile}) has, err := r.be.Test(ctx, restic.Handle{Type: restic.ConfigFile})
if err != nil { if err != nil {
return err return err
@ -670,7 +678,7 @@ func (r *Repository) Init(ctx context.Context, password string, chunkerPolynomia
return errors.New("repository master key and config already initialized") return errors.New("repository master key and config already initialized")
} }
cfg, err := restic.CreateConfig() cfg, err := restic.CreateConfig(version)
if err != nil { if err != nil {
return err return err
} }

View File

@ -18,9 +18,12 @@ type Config struct {
ChunkerPolynomial chunker.Pol `json:"chunker_polynomial"` ChunkerPolynomial chunker.Pol `json:"chunker_polynomial"`
} }
// RepoVersion is the version that is written to the config when a repository const MinRepoVersion = 1
const MaxRepoVersion = 2
// StableRepoVersion is the version that is written to the config when a repository
// is newly created with Init(). // is newly created with Init().
const RepoVersion = 1 const StableRepoVersion = 1
// JSONUnpackedLoader loads unpacked JSON. // JSONUnpackedLoader loads unpacked JSON.
type JSONUnpackedLoader interface { type JSONUnpackedLoader interface {
@ -29,7 +32,7 @@ type JSONUnpackedLoader interface {
// CreateConfig creates a config file with a randomly selected polynomial and // CreateConfig creates a config file with a randomly selected polynomial and
// ID. // ID.
func CreateConfig() (Config, error) { func CreateConfig(version uint) (Config, error) {
var ( var (
err error err error
cfg Config cfg Config
@ -41,7 +44,7 @@ func CreateConfig() (Config, error) {
} }
cfg.ID = NewRandomID().String() cfg.ID = NewRandomID().String()
cfg.Version = RepoVersion cfg.Version = version
debug.Log("New config: %#v", cfg) debug.Log("New config: %#v", cfg)
return cfg, nil return cfg, nil
@ -52,7 +55,7 @@ func TestCreateConfig(t testing.TB, pol chunker.Pol) (cfg Config) {
cfg.ChunkerPolynomial = pol cfg.ChunkerPolynomial = pol
cfg.ID = NewRandomID().String() cfg.ID = NewRandomID().String()
cfg.Version = RepoVersion cfg.Version = StableRepoVersion
return cfg return cfg
} }
@ -77,7 +80,7 @@ func LoadConfig(ctx context.Context, r JSONUnpackedLoader) (Config, error) {
return Config{}, err return Config{}, err
} }
if cfg.Version != RepoVersion { if cfg.Version < MinRepoVersion || cfg.Version > MaxRepoVersion {
return Config{}, errors.Errorf("unsupported repository version %v", cfg.Version) return Config{}, errors.Errorf("unsupported repository version %v", cfg.Version)
} }

View File

@ -32,7 +32,7 @@ func TestConfig(t *testing.T) {
return restic.ID{}, nil return restic.ID{}, nil
} }
cfg1, err := restic.CreateConfig() cfg1, err := restic.CreateConfig(restic.MaxRepoVersion)
rtest.OK(t, err) rtest.OK(t, err)
_, err = saver(save).SaveJSONUnpacked(restic.ConfigFile, cfg1) _, err = saver(save).SaveJSONUnpacked(restic.ConfigFile, cfg1)