diff --git a/src/cmds/restic/global.go b/src/cmds/restic/global.go index ae3b59ecb..a41194a1c 100644 --- a/src/cmds/restic/global.go +++ b/src/cmds/restic/global.go @@ -322,7 +322,7 @@ func open(s string) (restic.Backend, error) { switch loc.Scheme { case "local": 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": debug.Log("opening sftp repository at %#v", loc.Config) be, err = sftp.OpenWithConfig(loc.Config.(sftp.Config)) @@ -362,7 +362,7 @@ func create(s string) (restic.Backend, error) { switch loc.Scheme { case "local": debug.Log("create local repository at %#v", loc.Config) - return local.Create(loc.Config.(string)) + return local.Create(loc.Config.(local.Config)) case "sftp": debug.Log("create sftp repository at %#v", loc.Config) return sftp.CreateWithConfig(loc.Config.(sftp.Config)) diff --git a/src/restic/backend/local/config.go b/src/restic/backend/local/config.go index 8a5c67a2c..746accd27 100644 --- a/src/restic/backend/local/config.go +++ b/src/restic/backend/local/config.go @@ -6,11 +6,16 @@ import ( "restic/errors" ) +// Config holds all information needed to open a local repository. +type Config struct { + Path string +} + // ParseConfig parses a local backend config. func ParseConfig(cfg string) (interface{}, error) { if !strings.HasPrefix(cfg, "local:") { return nil, errors.New(`invalid format, prefix "local" not found`) } - return cfg[6:], nil + return Config{Path: cfg[6:]}, nil } diff --git a/src/restic/backend/local/local.go b/src/restic/backend/local/local.go index 03d812d99..510569654 100644 --- a/src/restic/backend/local/local.go +++ b/src/restic/backend/local/local.go @@ -16,7 +16,7 @@ import ( // Local is a backend in a local directory. type Local struct { - p string + Config } var _ restic.Backend = &Local{} @@ -34,28 +34,28 @@ func paths(dir string) []string { } // 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 - for _, d := range paths(dir) { + for _, d := range paths(cfg.Path) { if _, err := fs.Stat(d); err != nil { 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 // 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 - _, err := fs.Lstat(filepath.Join(dir, backend.Paths.Config)) + _, err := fs.Lstat(filepath.Join(cfg.Path, backend.Paths.Config)) if err == nil { return nil, errors.New("config file already exists") } // 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) if err != nil { return nil, errors.Wrap(err, "MkdirAll") @@ -63,12 +63,12 @@ func Create(dir string) (*Local, error) { } // open backend - return Open(dir) + return Open(cfg) } // Location returns this backend's location (the directory name). func (b *Local) Location() string { - return b.p + return b.Path } // 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 } - 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) if err != nil { return err } - filename := filename(b.p, h.Type, h.Name) + filename := filename(b.Path, h.Type, h.Name) // test if new path already exists 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") } - 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 { return nil, err } @@ -210,7 +210,7 @@ func (b *Local) Stat(h restic.Handle) (restic.FileInfo, error) { 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 { 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. func (b *Local) Test(h restic.Handle) (bool, error) { 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 os.IsNotExist(errors.Cause(err)) { 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. func (b *Local) Remove(h restic.Handle) error { 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 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) - items, err := lister(filepath.Join(dirname(b.p, t, ""))) + items, err := lister(filepath.Join(dirname(b.Path, t, ""))) if err != nil { close(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. func (b *Local) Delete() error { debug.Log("Delete()") - return fs.RemoveAll(b.p) + return fs.RemoveAll(b.Path) } // Close closes all open files. diff --git a/src/restic/backend/local/local_test.go b/src/restic/backend/local/local_test.go index 3bae88753..7e7440561 100644 --- a/src/restic/backend/local/local_test.go +++ b/src/restic/backend/local/local_test.go @@ -35,7 +35,7 @@ func init() { if err != nil { return nil, err } - return local.Create(tempBackendDir) + return local.Create(local.Config{Path: tempBackendDir}) } test.OpenFn = func() (restic.Backend, error) { @@ -43,7 +43,7 @@ func init() { if err != nil { return nil, err } - return local.Open(tempBackendDir) + return local.Open(local.Config{Path: tempBackendDir}) } test.CleanupFn = func() error { diff --git a/src/restic/location/location_test.go b/src/restic/location/location_test.go index bb4ac64c9..2961ecd54 100644 --- a/src/restic/location/location_test.go +++ b/src/restic/location/location_test.go @@ -5,6 +5,7 @@ import ( "reflect" "testing" + "restic/backend/local" "restic/backend/rest" "restic/backend/s3" "restic/backend/sftp" @@ -23,12 +24,30 @@ var parseTests = []struct { s string u Location }{ - {"local:/srv/repo", Location{Scheme: "local", Config: "/srv/repo"}}, - {"local:dir1/dir2", Location{Scheme: "local", Config: "dir1/dir2"}}, - {"local:dir1/dir2", Location{Scheme: "local", Config: "dir1/dir2"}}, - {"dir1/dir2", Location{Scheme: "local", Config: "dir1/dir2"}}, - {"local:../dir1/dir2", Location{Scheme: "local", Config: "../dir1/dir2"}}, - {"/dir1/dir2", Location{Scheme: "local", Config: "/dir1/dir2"}}, + {"local:/srv/repo", Location{Scheme: "local", + Config: local.Config{ + Path: "/srv/repo", + }}}, + {"local: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", + }}}, + {"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", Config: sftp.Config{ diff --git a/src/restic/repository/testing.go b/src/restic/repository/testing.go index 7650ad8b9..6f590e13a 100644 --- a/src/restic/repository/testing.go +++ b/src/restic/repository/testing.go @@ -67,7 +67,7 @@ func TestRepository(t testing.TB) (r restic.Repository, cleanup func()) { if dir != "" { _, err := os.Stat(dir) if err != nil { - be, err := local.Create(dir) + be, err := local.Create(local.Config{Path: dir}) if err != nil { 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. 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 { t.Fatal(err) }