diff options
| author | Shulhan <ms@kilabit.info> | 2021-09-25 21:12:31 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2021-09-25 21:12:31 +0700 |
| commit | 81f4c4593f5481b95f104f69c9843d6841f6fc1b (patch) | |
| tree | 685a14175165bafdd906147fe4be9ae56b5359b9 | |
| parent | 607afa0831bad87befbe3f3896c487cacadc969b (diff) | |
| download | pakakeh.go-81f4c4593f5481b95f104f69c9843d6841f6fc1b.tar.xz | |
lib/io: fix NewWatcher when called DirWatcher
When NewWatcher called from DirWatcher's Start(), it will called NewNode
with nil parent parameter. If the parent parameter is nil on NewNode
the SysPath of new node will be set to the FileInfo.Name() instead of
full or relative path based on current working directory.
Any operation using new node SysPath will failed because the path
does not exist or reachable from current directory.
For example, let say we have the following directory tree,
testdata
|
+--- A
|
+--- B
We then set DirWatcher Root to "testdata" from current directory.
The DirWatcher Start then iterate over all child of "testdata" directory,
and call NewWatcher("testdata/A", ...). On the NewWatcher, it will
call NewNode(nil, FileInfo, -1). Now since the parent is nil,
the Node.SysPath will be set to FileInfo.Name() or base name of the file,
which is "A".
Later, when node content need to be read, ioutil.ReadFile("A") will
fail because the path to "A" does not exist on current directory.
This fix require to force the parameter "parent" on NewNode to be
required.
| -rw-r--r-- | lib/io/dirwatcher_test.go | 6 | ||||
| -rw-r--r-- | lib/io/watcher.go | 28 | ||||
| -rw-r--r-- | lib/memfs/node.go | 13 |
3 files changed, 27 insertions, 20 deletions
diff --git a/lib/io/dirwatcher_test.go b/lib/io/dirwatcher_test.go index 018fd524..b5546683 100644 --- a/lib/io/dirwatcher_test.go +++ b/lib/io/dirwatcher_test.go @@ -46,7 +46,7 @@ func TestDirWatcher(t *testing.T) { path: "/new.adoc", }, { state: FileStateDeleted, - path: filepath.Join(dir, "/new.adoc"), + path: filepath.Join(filepath.Base(dir), "/new.adoc"), }, { state: FileStateCreated, path: "/sub", @@ -55,13 +55,13 @@ func TestDirWatcher(t *testing.T) { path: "/sub/new.adoc", }, { state: FileStateDeleted, - path: filepath.Join(dir, "/sub/new.adoc"), + path: "sub/new.adoc", }, { state: FileStateCreated, path: "/assets/new", }, { state: FileStateDeleted, - path: filepath.Join(dir, "/assets/new"), + path: "assets/new", }} var x int32 diff --git a/lib/io/watcher.go b/lib/io/watcher.go index e1d3669c..88f16546 100644 --- a/lib/io/watcher.go +++ b/lib/io/watcher.go @@ -8,6 +8,7 @@ import ( "fmt" "log" "os" + "path/filepath" "time" "github.com/shuLhan/share/lib/debug" @@ -43,34 +44,41 @@ type Watcher struct { // duration (5 seconds). // func NewWatcher(path string, d time.Duration, cb WatchCallback) (w *Watcher, err error) { + logp := "NewWatcher" + if len(path) == 0 { - return nil, fmt.Errorf("lib/io: NewWatcher: path is empty") + return nil, fmt.Errorf("%s: path is empty", logp) } if cb == nil { - return nil, fmt.Errorf("lib/io: NewWatcher: callback is not defined") + return nil, fmt.Errorf("%s: callback is not defined", logp) } fi, err := os.Stat(path) if err != nil { - return nil, fmt.Errorf("lib/io: NewWatcher: " + err.Error()) + return nil, fmt.Errorf("%s: %w", logp, err) } if fi.IsDir() { - return nil, fmt.Errorf("lib/io: NewWatcher: path is directory") + return nil, fmt.Errorf("%s: path is directory", logp) + } + + absPath, err := filepath.Abs(path) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } + dummyParent := &memfs.Node{ + SysPath: filepath.Dir(absPath), } + dummyParent.Path = filepath.Base(dummyParent.SysPath) - node, err := memfs.NewNode(nil, fi, -1) + node, err := memfs.NewNode(dummyParent, fi, -1) if err != nil { - log.Printf("lib/io: NewWatcher %s: %s", fi.Name(), err.Error()) - return nil, nil + return nil, fmt.Errorf("%s: %w", logp, err) } if d < 100*time.Millisecond { d = time.Second * 5 } - node.SysPath = path - node.Path = path - w = &Watcher{ path: path, delay: d, diff --git a/lib/memfs/node.go b/lib/memfs/node.go index 5383761b..561c2c50 100644 --- a/lib/memfs/node.go +++ b/lib/memfs/node.go @@ -54,6 +54,10 @@ type Node struct { // // NewNode create a new node based on file information "fi". +// +// The parent parameter is required to allow valid system path generated for +// new node. +// // If maxFileSize is greater than zero, the file content and its type will be // saved in node as V and ContentType. // @@ -68,13 +72,8 @@ func NewNode(parent *Node, fi os.FileInfo, maxFileSize int64) (node *Node, err e absPath string ) - if parent != nil { - sysPath = filepath.Join(parent.SysPath, fi.Name()) - absPath = path.Join(parent.Path, fi.Name()) - } else { - sysPath = fi.Name() - absPath = fi.Name() - } + sysPath = filepath.Join(parent.SysPath, fi.Name()) + absPath = path.Join(parent.Path, fi.Name()) node = &Node{ SysPath: sysPath, |
