Add layout name parser
This commit is contained in:
parent
c6b8ffbb61
commit
50dfa64a54
4 changed files with 106 additions and 12 deletions
|
@ -108,8 +108,13 @@ func hasSubdirBackendFile(fs Filesystem, dir string) (bool, error) {
|
|||
}
|
||||
|
||||
// DetectLayout tries to find out which layout is used in a local (or sftp)
|
||||
// filesystem at the given path.
|
||||
// filesystem at the given path. If repo is nil, an instance of LocalFilesystem
|
||||
// is used.
|
||||
func DetectLayout(repo Filesystem, dir string) (Layout, error) {
|
||||
if repo == nil {
|
||||
repo = &LocalFilesystem{}
|
||||
}
|
||||
|
||||
// key file in the "keys" dir (DefaultLayout or CloudLayout)
|
||||
foundKeysFile, err := hasBackendFile(repo, repo.Join(dir, defaultLayoutPaths[restic.KeyFile]))
|
||||
if err != nil {
|
||||
|
@ -148,3 +153,36 @@ func DetectLayout(repo Filesystem, dir string) (Layout, error) {
|
|||
|
||||
return nil, errors.New("auto-detecting the filesystem layout failed")
|
||||
}
|
||||
|
||||
// ParseLayout parses the config string and returns a Layout. When layout is
|
||||
// the empty string, DetectLayout is used. If repo is nil, an instance of LocalFilesystem
|
||||
// is used.
|
||||
func ParseLayout(repo Filesystem, layout, path string) (l Layout, err error) {
|
||||
if repo == nil {
|
||||
repo = &LocalFilesystem{}
|
||||
}
|
||||
|
||||
switch layout {
|
||||
case "default":
|
||||
l = &DefaultLayout{
|
||||
Path: path,
|
||||
Join: repo.Join,
|
||||
}
|
||||
case "cloud":
|
||||
l = &CloudLayout{
|
||||
Path: path,
|
||||
Join: repo.Join,
|
||||
}
|
||||
case "s3":
|
||||
l = &S3Layout{
|
||||
Path: path,
|
||||
Join: repo.Join,
|
||||
}
|
||||
case "":
|
||||
return DetectLayout(repo, path)
|
||||
default:
|
||||
return nil, errors.Errorf("unknown backend layout string %q, may be one of default/cloud/s3", layout)
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
|
|
@ -229,10 +229,49 @@ func TestDetectLayout(t *testing.T) {
|
|||
|
||||
var fs = &LocalFilesystem{}
|
||||
for _, test := range tests {
|
||||
t.Run(test.filename, func(t *testing.T) {
|
||||
SetupTarTestFixture(t, path, filepath.Join("testdata", test.filename))
|
||||
for _, fs := range []Filesystem{fs, nil} {
|
||||
t.Run(fmt.Sprintf("%v/fs-%T", test.filename, fs), func(t *testing.T) {
|
||||
SetupTarTestFixture(t, path, filepath.Join("testdata", test.filename))
|
||||
|
||||
layout, err := DetectLayout(fs, filepath.Join(path, "repo"))
|
||||
layout, err := DetectLayout(fs, filepath.Join(path, "repo"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if layout == nil {
|
||||
t.Fatal("wanted some layout, but detect returned nil")
|
||||
}
|
||||
|
||||
layoutName := fmt.Sprintf("%T", layout)
|
||||
if layoutName != test.want {
|
||||
t.Fatalf("want layout %v, got %v", test.want, layoutName)
|
||||
}
|
||||
|
||||
RemoveAll(t, filepath.Join(path, "repo"))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseLayout(t *testing.T) {
|
||||
path, cleanup := TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
var tests = []struct {
|
||||
layoutName string
|
||||
want string
|
||||
}{
|
||||
{"default", "*backend.DefaultLayout"},
|
||||
{"cloud", "*backend.CloudLayout"},
|
||||
{"s3", "*backend.S3Layout"},
|
||||
{"", "*backend.CloudLayout"},
|
||||
}
|
||||
|
||||
SetupTarTestFixture(t, path, filepath.Join("testdata", "repo-layout-cloud.tar.gz"))
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.layoutName, func(t *testing.T) {
|
||||
layout, err := ParseLayout(nil, test.layoutName, filepath.Join(path, "repo"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -245,8 +284,24 @@ func TestDetectLayout(t *testing.T) {
|
|||
if layoutName != test.want {
|
||||
t.Fatalf("want layout %v, got %v", test.want, layoutName)
|
||||
}
|
||||
|
||||
RemoveAll(t, filepath.Join(path, "repo"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseLayoutInvalid(t *testing.T) {
|
||||
path, cleanup := TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
var invalidNames = []string{
|
||||
"foo", "bar", "local",
|
||||
}
|
||||
|
||||
for _, name := range invalidNames {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
layout, err := ParseLayout(nil, name, path)
|
||||
if err == nil {
|
||||
t.Fatalf("expected error not found for layout name %v, layout is %v", name, layout)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ import (
|
|||
|
||||
// Config holds all information needed to open a local repository.
|
||||
type Config struct {
|
||||
Path string
|
||||
Path string
|
||||
Layout string
|
||||
}
|
||||
|
||||
// ParseConfig parses a local backend config.
|
||||
|
|
|
@ -24,13 +24,13 @@ var _ restic.Backend = &Local{}
|
|||
|
||||
// Open opens the local backend as specified by config.
|
||||
func Open(cfg Config) (*Local, error) {
|
||||
be := &Local{Config: cfg}
|
||||
|
||||
be.Layout = &backend.DefaultLayout{
|
||||
Path: cfg.Path,
|
||||
Join: filepath.Join,
|
||||
l, err := backend.ParseLayout(nil, cfg.Layout, cfg.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
be := &Local{Config: cfg, Layout: l}
|
||||
|
||||
// test if all necessary dirs are there
|
||||
for _, d := range be.Paths() {
|
||||
if _, err := fs.Stat(d); err != nil {
|
||||
|
|
Loading…
Reference in a new issue