mirror of
https://github.com/octoleo/restic.git
synced 2024-11-26 06:46:34 +00:00
Merge pull request #3065 from greatroar/local-subdirs
Don't recurse in local backend's List if not required
This commit is contained in:
commit
f2959127b6
@ -220,52 +220,17 @@ func (b *Local) Remove(ctx context.Context, h restic.Handle) error {
|
|||||||
return fs.Remove(fn)
|
return fs.Remove(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isFile(fi os.FileInfo) bool {
|
|
||||||
return fi.Mode()&(os.ModeType|os.ModeCharDevice) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// List runs fn for each file in the backend which has the type t. When an
|
// List runs fn for each file in the backend which has the type t. When an
|
||||||
// error occurs (or fn returns an error), List stops and returns it.
|
// error occurs (or fn returns an error), List stops and returns it.
|
||||||
func (b *Local) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) error {
|
func (b *Local) List(ctx context.Context, t restic.FileType, fn func(restic.FileInfo) error) (err error) {
|
||||||
debug.Log("List %v", t)
|
debug.Log("List %v", t)
|
||||||
|
|
||||||
basedir, subdirs := b.Basedir(t)
|
basedir, subdirs := b.Basedir(t)
|
||||||
err := fs.Walk(basedir, func(path string, fi os.FileInfo, err error) error {
|
if subdirs {
|
||||||
debug.Log("walk on %v\n", path)
|
err = visitDirs(ctx, basedir, fn)
|
||||||
if err != nil {
|
} else {
|
||||||
return err
|
err = visitFiles(ctx, basedir, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if path == basedir {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isFile(fi) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if fi.IsDir() && !subdirs {
|
|
||||||
return filepath.SkipDir
|
|
||||||
}
|
|
||||||
|
|
||||||
debug.Log("send %v\n", filepath.Base(path))
|
|
||||||
|
|
||||||
rfi := restic.FileInfo{
|
|
||||||
Name: filepath.Base(path),
|
|
||||||
Size: fi.Size(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.Err() != nil {
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
err = fn(rfi)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.Err()
|
|
||||||
})
|
|
||||||
|
|
||||||
if b.IsNotExist(err) {
|
if b.IsNotExist(err) {
|
||||||
debug.Log("ignoring non-existing directory")
|
debug.Log("ignoring non-existing directory")
|
||||||
@ -275,6 +240,61 @@ func (b *Local) List(ctx context.Context, t restic.FileType, fn func(restic.File
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following two functions are like filepath.Walk, but visit only one or
|
||||||
|
// two levels of directory structure (including dir itself as the first level).
|
||||||
|
// Also, visitDirs assumes it sees a directory full of directories, while
|
||||||
|
// visitFiles wants a directory full or regular files.
|
||||||
|
func visitDirs(ctx context.Context, dir string, fn func(restic.FileInfo) error) error {
|
||||||
|
d, err := fs.Open(dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
|
||||||
|
sub, err := d.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range sub {
|
||||||
|
err = visitFiles(ctx, filepath.Join(dir, f), fn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func visitFiles(ctx context.Context, dir string, fn func(restic.FileInfo) error) error {
|
||||||
|
d, err := fs.Open(dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
|
||||||
|
sub, err := d.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, fi := range sub {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
err := fn(restic.FileInfo{
|
||||||
|
Name: fi.Name(),
|
||||||
|
Size: fi.Size(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Delete removes the repository and all files.
|
// Delete removes the repository and all files.
|
||||||
func (b *Local) Delete(ctx context.Context) error {
|
func (b *Local) Delete(ctx context.Context) error {
|
||||||
debug.Log("Delete()")
|
debug.Log("Delete()")
|
||||||
|
Loading…
Reference in New Issue
Block a user