From 41294ceedd738cc44fe01dd0011ba7087a5d37fb Mon Sep 17 00:00:00 2001 From: Shulhan Date: Fri, 27 Sep 2019 00:24:56 +0700 Subject: memfs: add method to add file directly as child of root --- CHANGELOG.adoc | 2 + CHANGELOG.html | 3 ++ lib/memfs/memfs.go | 48 +++++++++++++++++++++ lib/memfs/memfs_test.go | 86 +++++++++++++++++++++++++++++++++++++ lib/memfs/testdata/direct/add/file | 1 + lib/memfs/testdata/direct/add/file2 | 1 + 6 files changed, 141 insertions(+) create mode 100644 lib/memfs/testdata/direct/add/file create mode 100644 lib/memfs/testdata/direct/add/file2 diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index c5a34b05..8e24d10c 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -15,6 +15,8 @@ This library is released each month, usually at the first week of month. * ints: add function to merge two slices by distance +* memfs: add method to add file directly as child of root + * memfs: add method to Search content of files * sanitize: new package to sanitize markup document into plain text diff --git a/CHANGELOG.html b/CHANGELOG.html index 6c14f8b7..b4795591 100644 --- a/CHANGELOG.html +++ b/CHANGELOG.html @@ -124,6 +124,9 @@

ints: add function to merge two slices by distance

  • +

    memfs: add method to add file directly as child of root

    +
  • +
  • memfs: add method to Search content of files

  • diff --git a/lib/memfs/memfs.go b/lib/memfs/memfs.go index 68d100a3..53bccc05 100644 --- a/lib/memfs/memfs.go +++ b/lib/memfs/memfs.go @@ -108,6 +108,54 @@ func New(includes, excludes []string, withContent bool) (mfs *MemFS, err error) return mfs, nil } +// +// AddFile add the file directly as child of root. +// The directory and subdirectories in the path will be keep as separated +// nodes, +// +func (mfs *MemFS) AddFile(path string) (*Node, error) { + if len(path) == 0 { + return nil, nil + } + + var parent *Node + + path = filepath.ToSlash(filepath.Clean(path)) + paths := strings.Split(path, "/") + path = "" + + for _, p := range paths { + path = filepath.Join(path, p) + node, _ := mfs.Get(path) + if node != nil { + parent = node + continue + } + + fi, err := os.Stat(path) + if err != nil { + return nil, fmt.Errorf("memfs.AddFile: " + err.Error()) + } + + node, err = NewNode(parent, fi, mfs.withContent) + if err != nil { + return nil, fmt.Errorf("memfs.AddFile: " + err.Error()) + } + + if parent == nil { + mfs.root.Childs = append(mfs.root.Childs, node) + } else { + parent.Childs = append(parent.Childs, node) + } + + mfs.pn.v[node.Path] = node + + parent = node + } + + return parent, nil +} + // // ContentEncode encode each node's content into specific encoding, in other // words this method can be used to compress the content of file in memory diff --git a/lib/memfs/memfs_test.go b/lib/memfs/memfs_test.go index 778e2529..a289ef32 100644 --- a/lib/memfs/memfs_test.go +++ b/lib/memfs/memfs_test.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" "testing" + "time" "github.com/shuLhan/share/lib/test" ) @@ -14,6 +15,88 @@ var ( _testWD string ) +func TestAddFile(t *testing.T) { + cases := []struct { + desc string + path string + exp *Node + expError string + }{{ + desc: "With empty path", + }, { + desc: "With path is not exist", + path: "is/not/exist", + expError: "memfs.AddFile: stat is: no such file or directory", + }, { + desc: "With file exist", + path: "testdata/direct/add/file", + exp: &Node{ + SysPath: "testdata/direct/add/file", + Path: "testdata/direct/add/file", + Name: "file", + ContentType: "text/plain; charset=utf-8", + Size: 22, + V: []byte("Test direct add file.\n"), + }, + }, { + desc: "With directories exist", + path: "testdata/direct/add/file2", + exp: &Node{ + SysPath: "testdata/direct/add/file2", + Path: "testdata/direct/add/file2", + Name: "file2", + ContentType: "text/plain; charset=utf-8", + Size: 24, + V: []byte("Test direct add file 2.\n"), + }, + }} + + mfs, err := New(nil, nil, true) + if err != nil { + t.Fatal(err) + } + + err = mfs.Mount("testdata") + if err != nil { + t.Fatal(err) + } + + for _, c := range cases { + t.Log(c.desc) + + got, err := mfs.AddFile(c.path) + if err != nil { + test.Assert(t, "error", c.expError, err.Error(), true) + continue + } + + if got != nil { + got.ModTime = time.Time{} + got.Mode = 0 + got.Parent = nil + got.Childs = nil + } + + test.Assert(t, "AddFile", c.exp, got, true) + + if c.exp != nil { + got, err := mfs.Get(c.path) + if err != nil { + t.Fatal(err) + } + + if got != nil { + got.ModTime = time.Time{} + got.Mode = 0 + got.Parent = nil + got.Childs = nil + } + + test.Assert(t, "Get", c.exp, got, true) + } + } +} + func TestGet(t *testing.T) { // Limit file size to allow testing Get from disk on file "index.js". MaxFileSize = 15 @@ -121,6 +204,7 @@ func TestMount(t *testing.T) { desc: "With directory", excs: []string{ "memfs_generate.go$", + "direct$", }, dir: filepath.Join(_testWD, "testdata"), expMapKeys: []string{ @@ -143,6 +227,7 @@ func TestMount(t *testing.T) { excs: []string{ `.*\.js$`, "memfs_generate.go$", + "direct$", }, dir: filepath.Join(_testWD, "testdata"), expMapKeys: []string{ @@ -164,6 +249,7 @@ func TestMount(t *testing.T) { }, excs: []string{ "memfs_generate.go$", + "direct$", }, dir: filepath.Join(_testWD, "testdata"), expMapKeys: []string{ diff --git a/lib/memfs/testdata/direct/add/file b/lib/memfs/testdata/direct/add/file new file mode 100644 index 00000000..9271a628 --- /dev/null +++ b/lib/memfs/testdata/direct/add/file @@ -0,0 +1 @@ +Test direct add file. diff --git a/lib/memfs/testdata/direct/add/file2 b/lib/memfs/testdata/direct/add/file2 new file mode 100644 index 00000000..1ecf20bb --- /dev/null +++ b/lib/memfs/testdata/direct/add/file2 @@ -0,0 +1 @@ +Test direct add file 2. -- cgit v1.3