diff options
| author | Shulhan <ms@kilabit.info> | 2021-08-22 23:52:33 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2021-08-22 23:52:33 +0700 |
| commit | a049bbc175338d591873f73028e728ed480447d7 (patch) | |
| tree | 2884e80ba4985f040390a4a20dd948e994dd430d /lib | |
| parent | c1bd3574758c7070eb405922b56f0dfa056cad01 (diff) | |
| download | pakakeh.go-a049bbc175338d591873f73028e728ed480447d7.tar.xz | |
lib/memfs: add method Save and Encode
The Save method will write the new content to file system and update
the content of Node using Encode().
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/memfs/generate_test.go | 1 | ||||
| -rw-r--r-- | lib/memfs/generate_test/gen_test.go | 1 | ||||
| -rw-r--r-- | lib/memfs/memfs_test.go | 3 | ||||
| -rw-r--r-- | lib/memfs/node.go | 63 | ||||
| -rw-r--r-- | lib/memfs/node_test.go | 51 |
5 files changed, 119 insertions, 0 deletions
diff --git a/lib/memfs/generate_test.go b/lib/memfs/generate_test.go index 61dad660..8d1bb939 100644 --- a/lib/memfs/generate_test.go +++ b/lib/memfs/generate_test.go @@ -11,6 +11,7 @@ func TestGenerate(t *testing.T) { Root: "testdata", Excludes: []string{ `^\..*`, + ".*/node_save$", }, } mfs, err := New(opts) diff --git a/lib/memfs/generate_test/gen_test.go b/lib/memfs/generate_test/gen_test.go index be1ddb44..d9d19a41 100644 --- a/lib/memfs/generate_test/gen_test.go +++ b/lib/memfs/generate_test/gen_test.go @@ -277,6 +277,7 @@ func init() { }, Excludes: []string{ `^\..*`, + `.*/node_save$`, }, }, } diff --git a/lib/memfs/memfs_test.go b/lib/memfs/memfs_test.go index 18dc1eab..4739df99 100644 --- a/lib/memfs/memfs_test.go +++ b/lib/memfs/memfs_test.go @@ -74,6 +74,7 @@ func TestNew(t *testing.T) { Excludes: []string{ "memfs_generate.go$", "direct$", + "node_save$", }, }, expMapKeys: []string{ @@ -99,6 +100,7 @@ func TestNew(t *testing.T) { `.*\.js$`, "memfs_generate.go$", "direct$", + "node_save$", }, }, expMapKeys: []string{ @@ -123,6 +125,7 @@ func TestNew(t *testing.T) { Excludes: []string{ "memfs_generate.go$", "direct$", + "node_save$", }, }, expMapKeys: []string{ diff --git a/lib/memfs/node.go b/lib/memfs/node.go index c958ea90..849a3d33 100644 --- a/lib/memfs/node.go +++ b/lib/memfs/node.go @@ -176,6 +176,39 @@ func (leaf *Node) Decode() ([]byte, error) { return leaf.plainv, nil } +// +// Encode compress and set the content of Node. +// +func (leaf *Node) Encode(content []byte) (err error) { + logp := "Node.Encode" + + leaf.plainv = content + leaf.lowerv = bytes.ToLower(content) + + switch leaf.ContentEncoding { + case EncodingGzip: + var buf bytes.Buffer + gz := gzip.NewWriter(&buf) + + _, err = gz.Write(content) + if err != nil { + _ = gz.Close() + return fmt.Errorf("%s: %w", logp, err) + } + + err = gz.Close() + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } + + leaf.V = libbytes.Copy(buf.Bytes()) + + default: + leaf.V = content + } + return nil +} + func (leaf *Node) IsDir() bool { return leaf.mode.IsDir() } @@ -257,6 +290,36 @@ func (leaf *Node) Readdir(count int) (fis []os.FileInfo, err error) { } // +// Save the content to file system and update the content of Node. +// +func (leaf *Node) Save(content []byte) (err error) { + var ( + logp = "Node.Save" + f *os.File + ) + f, err = os.OpenFile(leaf.SysPath, os.O_WRONLY|os.O_TRUNC, leaf.mode.Perm()) + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } + _, err = f.Write(content) + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } + err = f.Close() + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } + err = leaf.Encode(content) + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } + + leaf.modTime = time.Now() + leaf.size = int64(len(content)) + return nil +} + +// // Seek sets the offset for the next Read offset, interpreted according to // whence: SeekStart means relative to the start of the file, SeekCurrent // means relative to the current offset, and SeekEnd means relative to the diff --git a/lib/memfs/node_test.go b/lib/memfs/node_test.go index 5b6375e7..29198055 100644 --- a/lib/memfs/node_test.go +++ b/lib/memfs/node_test.go @@ -84,6 +84,7 @@ func TestNode_Readdir(t *testing.T) { "index.css", "index.html", "index.js", + "node_save", "plain", } @@ -116,6 +117,56 @@ func gotFileNames(fis []os.FileInfo) (names []string) { return } +func TestNode_Save(t *testing.T) { + node := &Node{ + SysPath: "testdata/node_save", + mode: 0600, + } + + err := os.WriteFile(node.SysPath, []byte{}, node.mode.Perm()) + if err != nil { + t.Fatal(err) + } + + cases := []struct { + desc string + content []byte + contentEncoding string + expContent []byte + }{{ + desc: "Without content encoding", + content: []byte("ABC"), + expContent: []byte("ABC"), + }, { + desc: "With content encoding is gzip", + contentEncoding: EncodingGzip, + content: []byte("ABC"), + expContent: []byte{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x72, 0x74, 0x72, 0x06, 0x04, 0x00, + 0x00, 0xff, 0xff, 0x48, 0x03, 0x83, 0xa3, 0x03, + 0x00, 0x00, 0x00, + }, + }} + + for _, c := range cases { + node.ContentEncoding = c.contentEncoding + + err = node.Save(c.content) + if err != nil { + t.Fatal(err) + } + + got, err := os.ReadFile(node.SysPath) + if err != nil { + t.Fatal(err) + } + + test.Assert(t, c.desc+": file content", c.content, got) + test.Assert(t, c.desc+": node content", c.expContent, node.V) + } +} + func TestNode_Seek(t *testing.T) { node := &Node{ size: 3, |
