local: Add Config struct

This commit is contained in:
Alexander Neumann 2017-03-25 13:20:03 +01:00
parent 6a8700d86c
commit 482a6e9840
6 changed files with 54 additions and 30 deletions

View file

@ -322,7 +322,7 @@ func open(s string) (restic.Backend, error) {
switch loc.Scheme { switch loc.Scheme {
case "local": case "local":
debug.Log("opening local repository at %#v", loc.Config) debug.Log("opening local repository at %#v", loc.Config)
be, err = local.Open(loc.Config.(string)) be, err = local.Open(loc.Config.(local.Config))
case "sftp": case "sftp":
debug.Log("opening sftp repository at %#v", loc.Config) debug.Log("opening sftp repository at %#v", loc.Config)
be, err = sftp.OpenWithConfig(loc.Config.(sftp.Config)) be, err = sftp.OpenWithConfig(loc.Config.(sftp.Config))
@ -362,7 +362,7 @@ func create(s string) (restic.Backend, error) {
switch loc.Scheme { switch loc.Scheme {
case "local": case "local":
debug.Log("create local repository at %#v", loc.Config) debug.Log("create local repository at %#v", loc.Config)
return local.Create(loc.Config.(string)) return local.Create(loc.Config.(local.Config))
case "sftp": case "sftp":
debug.Log("create sftp repository at %#v", loc.Config) debug.Log("create sftp repository at %#v", loc.Config)
return sftp.CreateWithConfig(loc.Config.(sftp.Config)) return sftp.CreateWithConfig(loc.Config.(sftp.Config))

View file

@ -6,11 +6,16 @@ import (
"restic/errors" "restic/errors"
) )
// Config holds all information needed to open a local repository.
type Config struct {
Path string
}
// ParseConfig parses a local backend config. // ParseConfig parses a local backend config.
func ParseConfig(cfg string) (interface{}, error) { func ParseConfig(cfg string) (interface{}, error) {
if !strings.HasPrefix(cfg, "local:") { if !strings.HasPrefix(cfg, "local:") {
return nil, errors.New(`invalid format, prefix "local" not found`) return nil, errors.New(`invalid format, prefix "local" not found`)
} }
return cfg[6:], nil return Config{Path: cfg[6:]}, nil
} }

View file

@ -16,7 +16,7 @@ import (
// Local is a backend in a local directory. // Local is a backend in a local directory.
type Local struct { type Local struct {
p string Config
} }
var _ restic.Backend = &Local{} var _ restic.Backend = &Local{}
@ -34,28 +34,28 @@ func paths(dir string) []string {
} }
// Open opens the local backend as specified by config. // Open opens the local backend as specified by config.
func Open(dir string) (*Local, error) { func Open(cfg Config) (*Local, error) {
// test if all necessary dirs are there // test if all necessary dirs are there
for _, d := range paths(dir) { for _, d := range paths(cfg.Path) {
if _, err := fs.Stat(d); err != nil { if _, err := fs.Stat(d); err != nil {
return nil, errors.Wrap(err, "Open") return nil, errors.Wrap(err, "Open")
} }
} }
return &Local{p: dir}, nil return &Local{Config: cfg}, nil
} }
// Create creates all the necessary files and directories for a new local // Create creates all the necessary files and directories for a new local
// backend at dir. Afterwards a new config blob should be created. // backend at dir. Afterwards a new config blob should be created.
func Create(dir string) (*Local, error) { func Create(cfg Config) (*Local, error) {
// test if config file already exists // test if config file already exists
_, err := fs.Lstat(filepath.Join(dir, backend.Paths.Config)) _, err := fs.Lstat(filepath.Join(cfg.Path, backend.Paths.Config))
if err == nil { if err == nil {
return nil, errors.New("config file already exists") return nil, errors.New("config file already exists")
} }
// create paths for data, refs and temp // create paths for data, refs and temp
for _, d := range paths(dir) { for _, d := range paths(cfg.Path) {
err := fs.MkdirAll(d, backend.Modes.Dir) err := fs.MkdirAll(d, backend.Modes.Dir)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "MkdirAll") return nil, errors.Wrap(err, "MkdirAll")
@ -63,12 +63,12 @@ func Create(dir string) (*Local, error) {
} }
// open backend // open backend
return Open(dir) return Open(cfg)
} }
// Location returns this backend's location (the directory name). // Location returns this backend's location (the directory name).
func (b *Local) Location() string { func (b *Local) Location() string {
return b.p return b.Path
} }
// Construct path for given Type and name. // Construct path for given Type and name.
@ -132,13 +132,13 @@ func (b *Local) Save(h restic.Handle, rd io.Reader) (err error) {
return err return err
} }
tmpfile, err := copyToTempfile(filepath.Join(b.p, backend.Paths.Temp), rd) tmpfile, err := copyToTempfile(filepath.Join(b.Path, backend.Paths.Temp), rd)
debug.Log("saved %v to %v", h, tmpfile) debug.Log("saved %v to %v", h, tmpfile)
if err != nil { if err != nil {
return err return err
} }
filename := filename(b.p, h.Type, h.Name) filename := filename(b.Path, h.Type, h.Name)
// test if new path already exists // test if new path already exists
if _, err := fs.Stat(filename); err == nil { if _, err := fs.Stat(filename); err == nil {
@ -183,7 +183,7 @@ func (b *Local) Load(h restic.Handle, length int, offset int64) (io.ReadCloser,
return nil, errors.New("offset is negative") return nil, errors.New("offset is negative")
} }
f, err := os.Open(filename(b.p, h.Type, h.Name)) f, err := os.Open(filename(b.Path, h.Type, h.Name))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -210,7 +210,7 @@ func (b *Local) Stat(h restic.Handle) (restic.FileInfo, error) {
return restic.FileInfo{}, err return restic.FileInfo{}, err
} }
fi, err := fs.Stat(filename(b.p, h.Type, h.Name)) fi, err := fs.Stat(filename(b.Path, h.Type, h.Name))
if err != nil { if err != nil {
return restic.FileInfo{}, errors.Wrap(err, "Stat") return restic.FileInfo{}, errors.Wrap(err, "Stat")
} }
@ -221,7 +221,7 @@ func (b *Local) Stat(h restic.Handle) (restic.FileInfo, error) {
// Test returns true if a blob of the given type and name exists in the backend. // Test returns true if a blob of the given type and name exists in the backend.
func (b *Local) Test(h restic.Handle) (bool, error) { func (b *Local) Test(h restic.Handle) (bool, error) {
debug.Log("Test %v", h) debug.Log("Test %v", h)
_, err := fs.Stat(filename(b.p, h.Type, h.Name)) _, err := fs.Stat(filename(b.Path, h.Type, h.Name))
if err != nil { if err != nil {
if os.IsNotExist(errors.Cause(err)) { if os.IsNotExist(errors.Cause(err)) {
return false, nil return false, nil
@ -235,7 +235,7 @@ func (b *Local) Test(h restic.Handle) (bool, error) {
// Remove removes the blob with the given name and type. // Remove removes the blob with the given name and type.
func (b *Local) Remove(h restic.Handle) error { func (b *Local) Remove(h restic.Handle) error {
debug.Log("Remove %v", h) debug.Log("Remove %v", h)
fn := filename(b.p, h.Type, h.Name) fn := filename(b.Path, h.Type, h.Name)
// reset read-only flag // reset read-only flag
err := fs.Chmod(fn, 0666) err := fs.Chmod(fn, 0666)
@ -316,7 +316,7 @@ func (b *Local) List(t restic.FileType, done <-chan struct{}) <-chan string {
} }
ch := make(chan string) ch := make(chan string)
items, err := lister(filepath.Join(dirname(b.p, t, ""))) items, err := lister(filepath.Join(dirname(b.Path, t, "")))
if err != nil { if err != nil {
close(ch) close(ch)
return ch return ch
@ -343,7 +343,7 @@ func (b *Local) List(t restic.FileType, done <-chan struct{}) <-chan string {
// Delete removes the repository and all files. // Delete removes the repository and all files.
func (b *Local) Delete() error { func (b *Local) Delete() error {
debug.Log("Delete()") debug.Log("Delete()")
return fs.RemoveAll(b.p) return fs.RemoveAll(b.Path)
} }
// Close closes all open files. // Close closes all open files.

View file

@ -35,7 +35,7 @@ func init() {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return local.Create(tempBackendDir) return local.Create(local.Config{Path: tempBackendDir})
} }
test.OpenFn = func() (restic.Backend, error) { test.OpenFn = func() (restic.Backend, error) {
@ -43,7 +43,7 @@ func init() {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return local.Open(tempBackendDir) return local.Open(local.Config{Path: tempBackendDir})
} }
test.CleanupFn = func() error { test.CleanupFn = func() error {

View file

@ -5,6 +5,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"restic/backend/local"
"restic/backend/rest" "restic/backend/rest"
"restic/backend/s3" "restic/backend/s3"
"restic/backend/sftp" "restic/backend/sftp"
@ -23,12 +24,30 @@ var parseTests = []struct {
s string s string
u Location u Location
}{ }{
{"local:/srv/repo", Location{Scheme: "local", Config: "/srv/repo"}}, {"local:/srv/repo", Location{Scheme: "local",
{"local:dir1/dir2", Location{Scheme: "local", Config: "dir1/dir2"}}, Config: local.Config{
{"local:dir1/dir2", Location{Scheme: "local", Config: "dir1/dir2"}}, Path: "/srv/repo",
{"dir1/dir2", Location{Scheme: "local", Config: "dir1/dir2"}}, }}},
{"local:../dir1/dir2", Location{Scheme: "local", Config: "../dir1/dir2"}}, {"local:dir1/dir2", Location{Scheme: "local",
{"/dir1/dir2", Location{Scheme: "local", Config: "/dir1/dir2"}}, Config: local.Config{
Path: "dir1/dir2",
}}},
{"local:dir1/dir2", Location{Scheme: "local",
Config: local.Config{
Path: "dir1/dir2",
}}},
{"dir1/dir2", Location{Scheme: "local",
Config: local.Config{
Path: "dir1/dir2",
}}},
{"local:../dir1/dir2", Location{Scheme: "local",
Config: local.Config{
Path: "../dir1/dir2",
}}},
{"/dir1/dir2", Location{Scheme: "local",
Config: local.Config{
Path: "/dir1/dir2",
}}},
{"sftp:user@host:/srv/repo", Location{Scheme: "sftp", {"sftp:user@host:/srv/repo", Location{Scheme: "sftp",
Config: sftp.Config{ Config: sftp.Config{

View file

@ -67,7 +67,7 @@ func TestRepository(t testing.TB) (r restic.Repository, cleanup func()) {
if dir != "" { if dir != "" {
_, err := os.Stat(dir) _, err := os.Stat(dir)
if err != nil { if err != nil {
be, err := local.Create(dir) be, err := local.Create(local.Config{Path: dir})
if err != nil { if err != nil {
t.Fatalf("error creating local backend at %v: %v", dir, err) t.Fatalf("error creating local backend at %v: %v", dir, err)
} }
@ -84,7 +84,7 @@ func TestRepository(t testing.TB) (r restic.Repository, cleanup func()) {
// TestOpenLocal opens a local repository. // TestOpenLocal opens a local repository.
func TestOpenLocal(t testing.TB, dir string) (r restic.Repository) { func TestOpenLocal(t testing.TB, dir string) (r restic.Repository) {
be, err := local.Open(dir) be, err := local.Open(local.Config{Path: dir})
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }