forked from TrueCloudLab/restic
Merge pull request #1182 from restic/fix-1167
local: do not create dirs below data/ for non-existing dir
This commit is contained in:
commit
48b1ab5aaf
3 changed files with 91 additions and 5 deletions
internal/backend
|
@ -25,6 +25,25 @@ var _ restic.Backend = &Local{}
|
||||||
|
|
||||||
const defaultLayout = "default"
|
const defaultLayout = "default"
|
||||||
|
|
||||||
|
// dirExists returns true if the name exists and is a directory.
|
||||||
|
func dirExists(name string) bool {
|
||||||
|
f, err := fs.Open(name)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fi, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Close(); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return fi.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
debug.Log("open local backend at %v (layout %q)", cfg.Path, cfg.Layout)
|
debug.Log("open local backend at %v (layout %q)", cfg.Path, cfg.Layout)
|
||||||
|
@ -35,11 +54,18 @@ func Open(cfg Config) (*Local, error) {
|
||||||
|
|
||||||
be := &Local{Config: cfg, Layout: l}
|
be := &Local{Config: cfg, Layout: l}
|
||||||
|
|
||||||
// create paths for data and refs. MkdirAll does nothing if the directory already exists.
|
// if data dir exists, make sure that all subdirs also exist
|
||||||
for _, d := range be.Paths() {
|
datadir := be.Dirname(restic.Handle{Type: restic.DataFile})
|
||||||
err := fs.MkdirAll(d, backend.Modes.Dir)
|
if dirExists(datadir) {
|
||||||
if err != nil {
|
for _, d := range be.Paths() {
|
||||||
return nil, errors.Wrap(err, "MkdirAll")
|
if _, err := filepath.Rel(datadir, d); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err := fs.MkdirAll(d, backend.Modes.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "MkdirAll")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ package local_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/restic/restic/internal/backend/local"
|
"github.com/restic/restic/internal/backend/local"
|
||||||
|
@ -59,3 +61,57 @@ func TestBackend(t *testing.T) {
|
||||||
func BenchmarkBackend(t *testing.B) {
|
func BenchmarkBackend(t *testing.B) {
|
||||||
newTestSuite(t).RunBenchmarks(t)
|
newTestSuite(t).RunBenchmarks(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readdirnames(t testing.TB, dir string) []string {
|
||||||
|
f, err := os.Open(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := f.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
func empty(t testing.TB, dir string) {
|
||||||
|
entries := readdirnames(t, dir)
|
||||||
|
if len(entries) != 0 {
|
||||||
|
t.Fatalf("directory %v is not empty, contains: %v", dir, entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func openclose(t testing.TB, dir string) {
|
||||||
|
cfg := local.Config{Path: dir}
|
||||||
|
|
||||||
|
be, err := local.Open(cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Open returned error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if be != nil {
|
||||||
|
err = be.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Close returned error %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpenNotExistingDirectory(t *testing.T) {
|
||||||
|
dir, cleanup := TempDir(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
// local.Open must not create any files dirs in the repo
|
||||||
|
openclose(t, filepath.Join(dir, "repo"))
|
||||||
|
empty(t, dir)
|
||||||
|
|
||||||
|
openclose(t, dir)
|
||||||
|
empty(t, dir)
|
||||||
|
}
|
||||||
|
|
|
@ -141,6 +141,10 @@ func (r *SFTP) checkDataSubdirs() error {
|
||||||
|
|
||||||
// check if all paths for data/ exist
|
// check if all paths for data/ exist
|
||||||
entries, err := r.c.ReadDir(datadir)
|
entries, err := r.c.ReadDir(datadir)
|
||||||
|
if r.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue