From bacd3658868f7ba7186feb9d741279db10d0443e Mon Sep 17 00:00:00 2001 From: Arne Groskurth Date: Fri, 25 Jun 2021 17:11:42 +0200 Subject: [PATCH 1/3] Sketched fix --- windows.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/windows.go b/windows.go index 09436f31..52619333 100644 --- a/windows.go +++ b/windows.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "sync" "syscall" "unsafe" @@ -464,6 +465,15 @@ func (w *Watcher) readEvents() { case syscall.FILE_ACTION_RENAMED_OLD_NAME: watch.rename = name case syscall.FILE_ACTION_RENAMED_NEW_NAME: + + // update saved path of all sub-watches + oldFullName := filepath.Join(watch.path, watch.rename) + for _, otherWatch := range w.watches { + if strings.HasPrefix(otherWatch.path, oldFullName) { + otherWatch.path = filepath.Join(watch.path, strings.TrimPrefix(otherWatch.path, oldFullName)) + } + } + if watch.names[watch.rename] != 0 { watch.names[name] |= watch.names[watch.rename] delete(watch.names, watch.rename) From 48f3dc2a4387ce52cb4c6bd6c3b1eb8c1d38b947 Mon Sep 17 00:00:00 2001 From: Arne Groskurth Date: Fri, 25 Jun 2021 22:47:09 +0200 Subject: [PATCH 2/3] Added test and implemented working fix --- integration_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++++ windows.go | 8 +++++--- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/integration_test.go b/integration_test.go index 7096344d..aae0662b 100644 --- a/integration_test.go +++ b/integration_test.go @@ -13,6 +13,7 @@ import ( "path" "path/filepath" "runtime" + "strings" "sync/atomic" "testing" "time" @@ -1226,6 +1227,55 @@ func TestRemoveWithClose(t *testing.T) { } } +func TestMoveWatchedDirectory(t *testing.T) { + + testDir := tempMkdir(t) + defer os.RemoveAll(testDir) + + watcher := newWatcher(t) + + // event recording + var events []Event + go func() { + for { + event, ok := <-watcher.Events + if !ok { + return + } + events = append(events, event) + } + }() + + addWatch(t, watcher, testDir) + + if err := os.Mkdir(testDir+"/dir", 0o775); err != nil { + t.Fatal(err) + } + time.Sleep(10 * time.Millisecond) + addWatch(t, watcher, testDir+"/dir") + if err := os.Rename(testDir+"/dir", testDir+"/dir2"); err != nil { + t.Fatal(err) + } + time.Sleep(10 * time.Millisecond) + if err := ioutil.WriteFile(testDir+"/dir2/file.ext", []byte(""), 0o664); err != nil { + t.Fatal(err) + } + + if err := watcher.Close(); err != nil { + t.Fatal(err) + } + time.Sleep(10 * time.Millisecond) + + if len(events) != 4 { + t.Fatalf("Expected 4 events. Got: %d", len(events)) + } + + expectedSuffix := filepath.Join("dir2", "file.ext") + if !strings.HasSuffix(events[3].Name, expectedSuffix) { + t.Fatalf("Expected suffix %s, Got: %s", expectedSuffix, events[3].Name) + } +} + func testRename(file1, file2 string) error { switch runtime.GOOS { case "windows", "plan9": diff --git a/windows.go b/windows.go index 52619333..58f34969 100644 --- a/windows.go +++ b/windows.go @@ -468,9 +468,11 @@ func (w *Watcher) readEvents() { // update saved path of all sub-watches oldFullName := filepath.Join(watch.path, watch.rename) - for _, otherWatch := range w.watches { - if strings.HasPrefix(otherWatch.path, oldFullName) { - otherWatch.path = filepath.Join(watch.path, strings.TrimPrefix(otherWatch.path, oldFullName)) + for _, watchMap := range w.watches { + for _, otherWatch := range watchMap { + if strings.HasPrefix(otherWatch.path, oldFullName) { + otherWatch.path = filepath.Join(fullname, strings.TrimPrefix(otherWatch.path, oldFullName)) + } } } From fc72e59b540e7bde4b9c973ea36af302a9487d04 Mon Sep 17 00:00:00 2001 From: Arne Groskurth Date: Fri, 25 Jun 2021 22:52:57 +0200 Subject: [PATCH 3/3] CL --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index be4d7ea2..b5da9fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +* Windows: Fixed persistence of original path-name in watches within renamed directory (#259, #243) + ## v1.4.7 / 2018-01-09 * BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine)