Files
kopia/fs/cachefs/cachefs.go
ashmrtn ef8828a072 refactor(snapshots): Remove remaining internal uses of Readdir (#1986)
* Remove remaining internal uses of Readdir

* Remove old helpers and interface functions.

* Update tests for updated fs.Directory interface

* Fix index out of range error in snapshot walker

Record one error if an error occurred and it's not limiting errors

* Use helper functions more; exit loops early

Follow up on reviewer comments and reduce code duplication, use more
targetted functions like Directory.Child, and exit directory iteration
early if possible.

* Remove fs.Entries type and unused functions

Leave some functions dealing with sorting and finding entries in fs
package. This retains tests for those functions while still allowing
mockfs to access them.

* Simplify function return
2022-06-04 06:36:25 -07:00

83 lines
1.7 KiB
Go

// Package cachefs implements a wrapper that caches filesystem actions.
package cachefs
import (
"context"
"github.com/kopia/kopia/fs"
)
// DirectoryCacher reads and potentially caches directory entries for a given directory.
type DirectoryCacher interface {
IterateEntries(ctx context.Context, d fs.Directory, w EntryWrapper, callback func(context.Context, fs.Entry) error) error
}
type cacheContext struct {
cacher DirectoryCacher
}
type directory struct {
ctx *cacheContext
fs.Directory
}
func (d *directory) Child(ctx context.Context, name string) (fs.Entry, error) {
e, err := d.Directory.Child(ctx, name)
if err != nil {
// nolint:wrapcheck
return nil, err
}
return wrapWithContext(e, d.ctx), nil
}
func (d *directory) IterateEntries(ctx context.Context, callback func(context.Context, fs.Entry) error) error {
err := d.ctx.cacher.IterateEntries(
ctx,
d.Directory,
func(e fs.Entry) fs.Entry {
return wrapWithContext(e, d.ctx)
},
callback,
)
return err // nolint:wrapcheck
}
type file struct {
ctx *cacheContext
fs.File
}
type symlink struct {
ctx *cacheContext
fs.Symlink
}
// Wrap returns an Entry that wraps another Entry and caches directory reads.
func Wrap(e fs.Entry, cacher DirectoryCacher) fs.Entry {
return wrapWithContext(e, &cacheContext{cacher})
}
func wrapWithContext(e fs.Entry, opts *cacheContext) fs.Entry {
switch e := e.(type) {
case fs.Directory:
return fs.Directory(&directory{opts, e})
case fs.File:
return fs.File(&file{opts, e})
case fs.Symlink:
return fs.Symlink(&symlink{opts, e})
default:
return e
}
}
var (
_ fs.Directory = &directory{}
_ fs.File = &file{}
_ fs.Symlink = &symlink{}
)