aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2021-06-03 08:15:00 +0700
committerShulhan <ms@kilabit.info>2021-06-03 08:15:00 +0700
commitf16f0c87bc6ed4d912528710eef4473b86064153 (patch)
treeb98bf3ac6016c15856d7eec34b7e4fe0014a02bc /lib
parent72d3515006e58d842fb76c5f3d49bb5aaff02e65 (diff)
downloadpakakeh.go-f16f0c87bc6ed4d912528710eef4473b86064153.tar.xz
memfs: add function to Merge one or more instance of MemFS
The Merge function merge one or more instance of MemFS into single MemFS instance. If there are two instance of Node that have the same path, the last instance will be ignored.
Diffstat (limited to 'lib')
-rw-r--r--lib/memfs/memfs.go49
-rw-r--r--lib/memfs/memfs_test.go74
2 files changed, 123 insertions, 0 deletions
diff --git a/lib/memfs/memfs.go b/lib/memfs/memfs.go
index e62b1ccf..29f6ea09 100644
--- a/lib/memfs/memfs.go
+++ b/lib/memfs/memfs.go
@@ -44,6 +44,46 @@ type MemFS struct {
}
//
+// Merge one or more instances of MemFS into single hierarchy.
+//
+// If there are two instance of Node that have the same path, the last
+// instance will be ignored.
+//
+func Merge(params ...*MemFS) (merged *MemFS) {
+ merged = &MemFS{
+ PathNodes: &PathNode{
+ v: make(map[string]*Node),
+ },
+ Root: &Node{
+ SysPath: "..",
+ Path: "/",
+ },
+ }
+
+ merged.PathNodes.v["/"] = merged.Root
+
+ for _, mfs := range params {
+ for _, child := range mfs.Root.Childs {
+ _, exist := merged.PathNodes.v[child.Path]
+ if exist {
+ continue
+ }
+ merged.Root.AddChild(child)
+ }
+ for path, node := range mfs.PathNodes.v {
+ if path == "/" {
+ continue
+ }
+ _, exist := merged.PathNodes.v[path]
+ if !exist {
+ merged.PathNodes.v[path] = node
+ }
+ }
+ }
+ return merged
+}
+
+//
// New create and initialize new memory file system from directory Root using
// list of regular expresssion for Including or Excluding files.
//
@@ -253,6 +293,15 @@ func (mfs *MemFS) Get(path string) (node *Node, err error) {
}
//
+// 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) {
+ node, _ = mfs.Get(path)
+ return node
+}
+
+//
// Open the named file for reading.
// This is an alias to Get() method, to make it implement http.FileSystem.
//
diff --git a/lib/memfs/memfs_test.go b/lib/memfs/memfs_test.go
index fc680401..8a130e42 100644
--- a/lib/memfs/memfs_test.go
+++ b/lib/memfs/memfs_test.go
@@ -478,3 +478,77 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
+
+func TestMerge(t *testing.T) {
+ optsDirect := &Options{
+ Root: "testdata/direct",
+ }
+ mfsDirect, err := New(optsDirect)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ optsInclude := &Options{
+ Root: "testdata/include",
+ }
+ mfsInclude, err := New(optsInclude)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cases := []struct {
+ desc string
+ params []*MemFS
+ exp *MemFS
+ }{{
+ desc: "with the same instance",
+ params: []*MemFS{mfsDirect, mfsDirect},
+ exp: &MemFS{
+ PathNodes: &PathNode{
+ v: map[string]*Node{
+ "/": &Node{
+ SysPath: "..",
+ Path: "/",
+ Childs: []*Node{
+ mfsDirect.MustGet("/add"),
+ },
+ },
+ "/add": mfsDirect.MustGet("/add"),
+ "/add/file": mfsDirect.MustGet("/add/file"),
+ "/add/file2": mfsDirect.MustGet("/add/file2"),
+ },
+ },
+ },
+ }, {
+ desc: "with different instances",
+ params: []*MemFS{mfsDirect, mfsInclude},
+ exp: &MemFS{
+ PathNodes: &PathNode{
+ v: map[string]*Node{
+ "/": &Node{
+ SysPath: "..",
+ Path: "/",
+ Childs: []*Node{
+ mfsDirect.MustGet("/add"),
+ mfsInclude.MustGet("/index.css"),
+ mfsInclude.MustGet("/index.html"),
+ mfsInclude.MustGet("/index.js"),
+ },
+ },
+ "/add": mfsDirect.MustGet("/add"),
+ "/add/file": mfsDirect.MustGet("/add/file"),
+ "/add/file2": mfsDirect.MustGet("/add/file2"),
+ "/index.css": mfsInclude.MustGet("/index.css"),
+ "/index.html": mfsInclude.MustGet("/index.html"),
+ "/index.js": mfsInclude.MustGet("/index.js"),
+ },
+ },
+ },
+ }}
+
+ for _, c := range cases {
+ got := Merge(c.params...)
+
+ test.Assert(t, c.desc, c.exp.PathNodes.v, got.PathNodes.v)
+ }
+}