diff options
| author | Shulhan <ms@kilabit.info> | 2023-11-22 13:00:51 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2023-11-22 13:05:57 +0700 |
| commit | a23642f407b380693f38d9be647f1d2e60b428d4 (patch) | |
| tree | bb8a4ad825d3cca136ddc7ddea7d0bdbeca89638 | |
| parent | b6f055e1a1612a99cba3fd11a1060b41a730ec91 (diff) | |
| download | pakakeh.go-a23642f407b380693f38d9be647f1d2e60b428d4.tar.xz | |
lib/memfs: add sub file system
This implemented simplified version of merging multiple MemFS instances.
The sub file system (subfs) can be added to the parent MemFS instance
by calling new method "Merge".
parent.Merge(other *MemfS)
When Get method called, each subfs will be evaluated in order of Merge
called.
This deprecated the function Merge.
| -rw-r--r-- | lib/memfs/internal/test/embed/memfs_embed_test.go | 2 | ||||
| -rw-r--r-- | lib/memfs/internal/test/embed_disable_modtime/memfs_embed_test.go | 2 | ||||
| -rw-r--r-- | lib/memfs/memfs.go | 82 | ||||
| -rw-r--r-- | lib/memfs/memfs_example_test.go | 4 |
4 files changed, 68 insertions, 22 deletions
diff --git a/lib/memfs/internal/test/embed/memfs_embed_test.go b/lib/memfs/internal/test/embed/memfs_embed_test.go index a7a5d789..4f6fcd55 100644 --- a/lib/memfs/internal/test/embed/memfs_embed_test.go +++ b/lib/memfs/internal/test/embed/memfs_embed_test.go @@ -46,7 +46,7 @@ func TestGeneratePathNode(t *testing.T) { expError string }{{ path: "/gen_test.go", - expError: "file does not exist", + expError: `Get "/gen_test.go": file does not exist`, }, { path: "/", exp: expRoot, diff --git a/lib/memfs/internal/test/embed_disable_modtime/memfs_embed_test.go b/lib/memfs/internal/test/embed_disable_modtime/memfs_embed_test.go index a7a5d789..4f6fcd55 100644 --- a/lib/memfs/internal/test/embed_disable_modtime/memfs_embed_test.go +++ b/lib/memfs/internal/test/embed_disable_modtime/memfs_embed_test.go @@ -46,7 +46,7 @@ func TestGeneratePathNode(t *testing.T) { expError string }{{ path: "/gen_test.go", - expError: "file does not exist", + expError: `Get "/gen_test.go": file does not exist`, }, { path: "/", exp: expRoot, diff --git a/lib/memfs/memfs.go b/lib/memfs/memfs.go index a40b7ee1..4c80bcce 100644 --- a/lib/memfs/memfs.go +++ b/lib/memfs/memfs.go @@ -40,6 +40,10 @@ type MemFS struct { watchRE []*regexp.Regexp incRE []*regexp.Regexp excRE []*regexp.Regexp + + // subfs contains another MemFS instances. + // During Get, it will evaluated in order. + subfs []*MemFS } // Merge one or more instances of MemFS into single hierarchy. @@ -49,6 +53,9 @@ type MemFS struct { // // If there are two instance of Node that have the same path, the last // instance will be ignored. +// +// DEPRECATED: use [MemFS.Merge] instead. +// TODO: Remove in the next three release cycles, v0.53.0. func Merge(params ...*MemFS) (merged *MemFS) { merged = &MemFS{ PathNodes: NewPathNode(), @@ -240,12 +247,12 @@ func (mfs *MemFS) AddFile(internalPath, externalPath string) (node *Node, err er } // Get the node representation of file in memory. If path is not exist it -// will return os.ErrNotExist. +// will return fs.ErrNotExist. func (mfs *MemFS) Get(path string) (node *Node, err error) { logp := "Get" if mfs == nil || mfs.PathNodes == nil { - return nil, fmt.Errorf("%s %s: %w", logp, path, os.ErrNotExist) + return nil, fmt.Errorf("%s %s: %w", logp, path, fs.ErrNotExist) } path = strings.TrimSpace(path) if len(path) == 0 { @@ -253,29 +260,58 @@ func (mfs *MemFS) Get(path string) (node *Node, err error) { } node = mfs.PathNodes.Get(path) - if node == nil { - if !mfs.Opts.TryDirect { - return nil, os.ErrNotExist + if node != nil { + if mfs.Opts.TryDirect { + _ = node.Update(nil, mfs.Opts.MaxFileSize) + + // Ignore error if the file is not exist in storage. + // Use case: the node maybe have been result of embed and the + // merged with other MemFS instance that use TryDirect flag. + } + return node, nil + } + + // Get node from sub. + var sub *MemFS + for _, sub = range mfs.subfs { + node, _ = sub.Get(path) + if node != nil { + return node, nil } + } + // Refresh the root FS first. + + if mfs.Opts.TryDirect { node, err = mfs.refresh(path) if err != nil { - if errors.Is(err, fs.ErrNotExist) { - err = fmt.Errorf(`%s %q: %w`, logp, path, fs.ErrNotExist) - } else { - err = fmt.Errorf(`%s %q: %w`, logp, path, err) + if !errors.Is(err, fs.ErrNotExist) { + return nil, fmt.Errorf(`%s %q: %w`, logp, path, err) } - return nil, err } - } else if mfs.Opts.TryDirect { - _ = node.Update(nil, mfs.Opts.MaxFileSize) + if node != nil { + return node, nil + } + } - // Ignore error if the file is not exist in storage. - // Use case: the node maybe have been result of embed and the - // merged with other MemFS instance that use TryDirect flag. + // Refresh the subfs. + + for _, sub = range mfs.subfs { + if !sub.Opts.TryDirect { + continue + } + node, err = sub.refresh(path) + if err != nil { + if !errors.Is(err, fs.ErrNotExist) { + return nil, fmt.Errorf(`%s %q: %w`, logp, path, err) + } + } + if node != nil { + return node, nil + } } - return node, nil + return nil, fmt.Errorf(`%s %q: %w`, logp, path, fs.ErrNotExist) } // Init initialize the MemFS instance. @@ -335,6 +371,16 @@ func (mfs *MemFS) MarshalJSON() ([]byte, error) { return buf.Bytes(), nil } +// Merge other MemFS instance as sub file system. +// +// When Get method called, each sub fs will be evaluated in order of Merge. +func (mfs *MemFS) Merge(sub *MemFS) { + if sub == nil { + return + } + mfs.subfs = append(mfs.subfs, sub) +} + // MustGet return the Node representation of file in memory by its path if its // exist or nil the path is not exist. func (mfs *MemFS) MustGet(path string) (node *Node) { @@ -643,7 +689,7 @@ func (mfs *MemFS) refresh(url string) (node *Node, err error) { syspath := filepath.Join(mfs.Root.SysPath, url) if !strings.HasPrefix(syspath, mfs.Root.SysPath) { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } _, err = os.Stat(syspath) @@ -670,7 +716,7 @@ func (mfs *MemFS) refresh(url string) (node *Node, err error) { node = mfs.PathNodes.Get(url) if node == nil { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } return node, nil diff --git a/lib/memfs/memfs_example_test.go b/lib/memfs/memfs_example_test.go index c064460f..8fc993bd 100644 --- a/lib/memfs/memfs_example_test.go +++ b/lib/memfs/memfs_example_test.go @@ -63,13 +63,13 @@ func ExampleNew() { _, err = mfs.Get("/exclude/index.html") if err != nil { - fmt.Println(`Error on Get /exclude/index.html:`, err) + fmt.Println(`Error:`, err) } // Output: // Content of /index.html: <html></html> // List of embedded files: [/ /direct /direct/add /include /include/dir /include/index.css /include/index.html /include/index.js /index.css /index.html /index.js] - // Error on Get /exclude/index.html: file does not exist + // Error: Get "/exclude/index.html": file does not exist } func ExampleMemFS_Search() { |
