2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-25 06:07:44 +00:00

local/sftp: Create repo dirs on demand in Save()

This commit is contained in:
Alexander Neumann 2018-01-05 17:51:09 +01:00
parent aabc0ccaa7
commit b45fc89512
2 changed files with 27 additions and 76 deletions

View File

@ -52,27 +52,7 @@ func Open(cfg Config) (*Local, error) {
return nil, err return nil, err
} }
be := &Local{Config: cfg, Layout: l} return &Local{Config: cfg, Layout: l}, nil
// if data dir exists, make sure that all subdirs also exist
datadir := be.Dirname(restic.Handle{Type: restic.DataFile})
if dirExists(datadir) {
debug.Log("datadir %v exists", datadir)
for _, d := range be.Paths() {
if !fs.HasPathPrefix(datadir, d) {
debug.Log("%v is not subdir of datadir %v", d, datadir)
continue
}
debug.Log("MkdirAll %v", d)
err := fs.MkdirAll(d, backend.Modes.Dir)
if err != nil {
return nil, errors.Wrap(err, "MkdirAll")
}
}
}
return be, 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
@ -124,20 +104,24 @@ func (b *Local) Save(ctx context.Context, h restic.Handle, rd io.Reader) error {
return err return err
} }
if h.Type == restic.LockFile {
lockDir := b.Dirname(h)
if !dirExists(lockDir) {
debug.Log("locks/ does not exist yet, creating now.")
if err := fs.MkdirAll(lockDir, backend.Modes.Dir); err != nil {
return errors.Wrap(err, "MkdirAll")
}
}
}
filename := b.Filename(h) filename := b.Filename(h)
// create new file // create new file
f, err := fs.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, backend.Modes.File) f, err := fs.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, backend.Modes.File)
if b.IsNotExist(err) {
debug.Log("error %v: creating dir", err)
// error is caused by a missing directory, try to create it
mkdirErr := os.MkdirAll(filepath.Dir(filename), backend.Modes.Dir)
if mkdirErr != nil {
debug.Log("error creating dir %v: %v", filepath.Dir(filename), mkdirErr)
} else {
// try again
f, err = fs.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, backend.Modes.File)
}
}
if err != nil { if err != nil {
return errors.Wrap(err, "OpenFile") return errors.Wrap(err, "OpenFile")
} }
@ -254,7 +238,7 @@ func (b *Local) List(ctx context.Context, t restic.FileType) <-chan string {
basedir, subdirs := b.Basedir(t) basedir, subdirs := b.Basedir(t)
err := fs.Walk(basedir, func(path string, fi os.FileInfo, err error) error { err := fs.Walk(basedir, func(path string, fi os.FileInfo, err error) error {
debug.Log("walk on %v, %v\n", path, fi.IsDir()) debug.Log("walk on %v\n", path)
if err != nil { if err != nil {
return err return err
} }

View File

@ -132,48 +132,11 @@ func Open(cfg Config, preExec, postExec func()) (*SFTP, error) {
debug.Log("layout: %v\n", sftp.Layout) debug.Log("layout: %v\n", sftp.Layout)
if err := sftp.checkDataSubdirs(); err != nil {
debug.Log("checkDataSubdirs returned %v", err)
return nil, err
}
sftp.Config = cfg sftp.Config = cfg
sftp.p = cfg.Path sftp.p = cfg.Path
return sftp, nil return sftp, nil
} }
func (r *SFTP) checkDataSubdirs() error {
datadir := r.Dirname(restic.Handle{Type: restic.DataFile})
// check if all paths for data/ exist
entries, err := r.ReadDir(datadir)
if r.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
subdirs := make(map[string]struct{}, len(entries))
for _, entry := range entries {
subdirs[entry.Name()] = struct{}{}
}
for i := 0; i < 256; i++ {
subdir := fmt.Sprintf("%02x", i)
if _, ok := subdirs[subdir]; !ok {
debug.Log("subdir %v is missing, creating", subdir)
err := r.mkdirAll(path.Join(datadir, subdir), backend.Modes.Dir)
if err != nil {
return err
}
}
}
return nil
}
func (r *SFTP) mkdirAllDataSubdirs() error { func (r *SFTP) mkdirAllDataSubdirs() error {
for _, d := range r.Paths() { for _, d := range r.Paths() {
err := r.mkdirAll(d, backend.Modes.Dir) err := r.mkdirAll(d, backend.Modes.Dir)
@ -203,6 +166,8 @@ func (r *SFTP) ReadDir(dir string) ([]os.FileInfo, error) {
// IsNotExist returns true if the error is caused by a not existing file. // IsNotExist returns true if the error is caused by a not existing file.
func (r *SFTP) IsNotExist(err error) bool { func (r *SFTP) IsNotExist(err error) bool {
err = errors.Cause(err)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return true return true
} }
@ -334,14 +299,16 @@ func (r *SFTP) Save(ctx context.Context, h restic.Handle, rd io.Reader) (err err
// create new file // create new file
f, err := r.c.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY) f, err := r.c.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY)
if r.IsNotExist(errors.Cause(err)) {
// create the locks dir, then try again
err = r.mkdirAll(r.Dirname(h), backend.Modes.Dir)
if err != nil {
return errors.Wrap(err, "MkdirAll")
}
return r.Save(ctx, h, rd) if r.IsNotExist(err) {
// error is caused by a missing directory, try to create it
mkdirErr := r.mkdirAll(r.Dirname(h), backend.Modes.Dir)
if mkdirErr != nil {
debug.Log("error creating dir %v: %v", r.Dirname(h), mkdirErr)
} else {
// try again
f, err = r.c.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY)
}
} }
if err != nil { if err != nil {