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)
|
// 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) {
|
func DetectLayout(repo Filesystem, dir string) (Layout, error) {
|
||||||
|
if repo == nil {
|
||||||
|
repo = &LocalFilesystem{}
|
||||||
|
}
|
||||||
|
|
||||||
// key file in the "keys" dir (DefaultLayout or CloudLayout)
|
// key file in the "keys" dir (DefaultLayout or CloudLayout)
|
||||||
foundKeysFile, err := hasBackendFile(repo, repo.Join(dir, defaultLayoutPaths[restic.KeyFile]))
|
foundKeysFile, err := hasBackendFile(repo, repo.Join(dir, defaultLayoutPaths[restic.KeyFile]))
|
||||||
if err != nil {
|
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")
|
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,7 +229,8 @@ func TestDetectLayout(t *testing.T) {
|
||||||
|
|
||||||
var fs = &LocalFilesystem{}
|
var fs = &LocalFilesystem{}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.filename, func(t *testing.T) {
|
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))
|
SetupTarTestFixture(t, path, filepath.Join("testdata", test.filename))
|
||||||
|
|
||||||
layout, err := DetectLayout(fs, filepath.Join(path, "repo"))
|
layout, err := DetectLayout(fs, filepath.Join(path, "repo"))
|
||||||
|
@ -249,4 +250,58 @@ func TestDetectLayout(t *testing.T) {
|
||||||
RemoveAll(t, filepath.Join(path, "repo"))
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
// Config holds all information needed to open a local repository.
|
// Config holds all information needed to open a local repository.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Path string
|
Path string
|
||||||
|
Layout string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseConfig parses a local backend config.
|
// ParseConfig parses a local backend config.
|
||||||
|
|
|
@ -24,13 +24,13 @@ var _ restic.Backend = &Local{}
|
||||||
|
|
||||||
// Open opens the local backend as specified by config.
|
// Open opens the local backend as specified by config.
|
||||||
func Open(cfg Config) (*Local, error) {
|
func Open(cfg Config) (*Local, error) {
|
||||||
be := &Local{Config: cfg}
|
l, err := backend.ParseLayout(nil, cfg.Layout, cfg.Path)
|
||||||
|
if err != nil {
|
||||||
be.Layout = &backend.DefaultLayout{
|
return nil, err
|
||||||
Path: cfg.Path,
|
|
||||||
Join: filepath.Join,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
be := &Local{Config: cfg, Layout: l}
|
||||||
|
|
||||||
// test if all necessary dirs are there
|
// test if all necessary dirs are there
|
||||||
for _, d := range be.Paths() {
|
for _, d := range be.Paths() {
|
||||||
if _, err := fs.Stat(d); err != nil {
|
if _, err := fs.Stat(d); err != nil {
|
||||||
|
|
Loading…
Reference in a new issue