From ddb1356452546ec2b37e790ecc460db973d7a892 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Sun, 29 Oct 2023 16:09:23 +0100 Subject: [PATCH] fix: Same path added with and without slashes are handled differently #5 --- devenv.lock | 12 ++++++------ error.go | 8 ++++++++ lighthouse.go | 49 ++++++++++++++++++++++++++++++++++++++++++++-- lighthouse_test.go | 2 +- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/devenv.lock b/devenv.lock index a9b3b22..3c26d26 100644 --- a/devenv.lock +++ b/devenv.lock @@ -74,11 +74,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1698288402, - "narHash": "sha256-jIIjApPdm+4yt8PglX8pUOexAdEiAax/DXW3S/Mb21E=", + "lastModified": 1698434055, + "narHash": "sha256-Phxi5mUKSoL7A0IYUiYtkI9e8NcGaaV5PJEaJApU1Ko=", "owner": "nixos", "repo": "nixpkgs", - "rev": "60b9db998f71ea49e1a9c41824d09aa274be1344", + "rev": "1a3c95e3b23b3cdb26750621c08cc2f1560cb883", "type": "github" }, "original": { @@ -106,11 +106,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1698288402, - "narHash": "sha256-jIIjApPdm+4yt8PglX8pUOexAdEiAax/DXW3S/Mb21E=", + "lastModified": 1698434055, + "narHash": "sha256-Phxi5mUKSoL7A0IYUiYtkI9e8NcGaaV5PJEaJApU1Ko=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "60b9db998f71ea49e1a9c41824d09aa274be1344", + "rev": "1a3c95e3b23b3cdb26750621c08cc2f1560cb883", "type": "github" }, "original": { diff --git a/error.go b/error.go index c5cea17..5f58a7f 100644 --- a/error.go +++ b/error.go @@ -56,3 +56,11 @@ type WatcherAlreadyActiveError struct{} func (e WatcherAlreadyActiveError) Error() string { return "Watcher is already active" } + +type PathNotExistingError struct { + Path string +} + +func (e PathNotExistingError) Error() string { + return fmt.Sprintf("Path %s does not exist", e.Path) +} diff --git a/lighthouse.go b/lighthouse.go index 40580fd..723cbea 100644 --- a/lighthouse.go +++ b/lighthouse.go @@ -3,6 +3,7 @@ package watch import ( "fmt" "github.com/fsnotify/fsnotify" + "os" "path/filepath" "sync" "time" @@ -183,12 +184,38 @@ func (l *lighthouse) IsActive() bool { return l.active } +// normalizePath returns the normalized path. If the path is a directory, a +// trailing slash is added. +// If the path does not exist, an error is returned. +// If the path is a directory, the second return value is true. +func normalizePath(path string) (string, bool, error) { + + isDir := false + + fi, err := os.Stat(path) + if err != nil { + return "", isDir, err + } + + // normalize is path is directory + if fi.IsDir() { + path = filepath.Clean(path) + isDir = true + } + + return path, isDir, nil + +} + // Add adds a path to the watcher. If the path is already being watched or the // watcher is not active, an error is returned. func (l *lighthouse) Add(watch *Watch) error { + l.mutex.Lock() defer l.mutex.Unlock() + var err error + if !l.active { return LighthouseNotActiveError{} } @@ -197,8 +224,13 @@ func (l *lighthouse) Add(watch *Watch) error { return AlreadyWatchedPathError{AlreadyWatched: watch.Path} } + watch.Path, _, err = normalizePath(watch.Path) + if err != nil { + return err + } + l.watchers[watch.Path] = watch - err := l.fsnotify.Add(watch.Path) + err = l.fsnotify.Add(watch.Path) if err != nil { return err } @@ -216,6 +248,8 @@ func (l *lighthouse) Remove(path string) error { return LighthouseNotActiveError{} } + path, _, _ = normalizePath(path) + if _, ok := l.watchers[path]; !ok { return UnwatchedPathError{UnwatchedPath: path} } @@ -249,6 +283,8 @@ func (l *lighthouse) IsWatched(path string) bool { return false } + path, _, _ = normalizePath(path) + if _, ok := l.watchers[path]; !ok { return false } @@ -268,10 +304,17 @@ func (l *lighthouse) Get(path string) (*Watch, error) { var watch *Watch var ok bool + var isDir bool + + path, isDir, _ = normalizePath(path) if watch, ok = l.watchers[path]; !ok { + if isDir { + return nil, UnwatchedPathError{UnwatchedPath: path} + } - if watch, ok = l.watchers[filepath.Dir(path)]; !ok { + dir := filepath.Dir(path) + if watch, ok = l.watchers[dir]; !ok { return nil, UnwatchedPathError{UnwatchedPath: path} } @@ -292,6 +335,8 @@ func (l *lighthouse) IsActiveWatched(path string) bool { l.mutex.Lock() defer l.mutex.Unlock() + path, _, _ = normalizePath(path) + // check fsnotify for _, fsPath := range l.fsnotify.WatchList() { if fsPath == path { diff --git a/lighthouse_test.go b/lighthouse_test.go index e36aa6c..f9118fd 100644 --- a/lighthouse_test.go +++ b/lighthouse_test.go @@ -102,7 +102,7 @@ func TestWatchList(t *testing.T) { assert.Equal(t, tempDir, l.WatchList()[0]) } -// test isinsync +// Test IsInSync with a file that is not watched by fsnotify func TestIsInSync(t *testing.T) { tempDir, err := os.MkdirTemp("", "watchtest") assert.Nil(t, err) -- GitLab