diff --git a/devenv.lock b/devenv.lock index a9b3b229863f84225ad9b061845a54d8a07b7718..3c26d26325f30d327cc38c159a4b7e2a5ab152fb 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 c5cea17d9a5da5f5d3781ee620944287ffa52a50..5f58a7f7bd6df6672d2bfa2e656a2fd4c5575472 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 40580fd66a24d0af1cc2976bc594341e7d247ecb..723cbea3ae3cc80cd949fd0510df1bc78e81150f 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 e36aa6c8bc8f1be31cbe60b9105612df6a4f8579..f9118fd3938bc6a5d12995ae88dfaa0fda8dcc05 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)