Skip to content

Commit e545940

Browse files
authored
Merge pull request #589 from fsnotify/win-rm
Document and test removing watched directory on Windows
2 parents 68111f2 + c86f21c commit e545940

7 files changed

Lines changed: 90 additions & 60 deletions

File tree

backend_fen.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ import (
7272
// Paths can be added as "C:\path\to\dir", but forward slashes
7373
// ("C:/path/to/dir") will also work.
7474
//
75+
// When a watched directory is removed it will always send an event for the
76+
// directory itself, but may not send events for all files in that directory.
77+
// Sometimes it will send events for all times, sometimes it will send no
78+
// events, and often only for some files.
79+
//
7580
// The default buffer size is 64K, which is the largest value that is guaranteed
7681
// to work with SMB filesystems. If you have many events in quick succession
7782
// this may not be enough, and you will have to use [WithBufferSize] to increase

backend_inotify.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ import (
7575
// Paths can be added as "C:\path\to\dir", but forward slashes
7676
// ("C:/path/to/dir") will also work.
7777
//
78+
// When a watched directory is removed it will always send an event for the
79+
// directory itself, but may not send events for all files in that directory.
80+
// Sometimes it will send events for all times, sometimes it will send no
81+
// events, and often only for some files.
82+
//
7883
// The default buffer size is 64K, which is the largest value that is guaranteed
7984
// to work with SMB filesystems. If you have many events in quick succession
8085
// this may not be enough, and you will have to use [WithBufferSize] to increase

backend_kqueue.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ import (
7272
// Paths can be added as "C:\path\to\dir", but forward slashes
7373
// ("C:/path/to/dir") will also work.
7474
//
75+
// When a watched directory is removed it will always send an event for the
76+
// directory itself, but may not send events for all files in that directory.
77+
// Sometimes it will send events for all times, sometimes it will send no
78+
// events, and often only for some files.
79+
//
7580
// The default buffer size is 64K, which is the largest value that is guaranteed
7681
// to work with SMB filesystems. If you have many events in quick succession
7782
// this may not be enough, and you will have to use [WithBufferSize] to increase

backend_other.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ import "errors"
6464
// Paths can be added as "C:\path\to\dir", but forward slashes
6565
// ("C:/path/to/dir") will also work.
6666
//
67+
// When a watched directory is removed it will always send an event for the
68+
// directory itself, but may not send events for all files in that directory.
69+
// Sometimes it will send events for all times, sometimes it will send no
70+
// events, and often only for some files.
71+
//
6772
// The default buffer size is 64K, which is the largest value that is guaranteed
6873
// to work with SMB filesystems. If you have many events in quick succession
6974
// this may not be enough, and you will have to use [WithBufferSize] to increase

backend_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ import (
8080
// Paths can be added as "C:\path\to\dir", but forward slashes
8181
// ("C:/path/to/dir") will also work.
8282
//
83+
// When a watched directory is removed it will always send an event for the
84+
// directory itself, but may not send events for all files in that directory.
85+
// Sometimes it will send events for all times, sometimes it will send no
86+
// events, and often only for some files.
87+
//
8388
// The default buffer size is 64K, which is the largest value that is guaranteed
8489
// to work with SMB filesystems. If you have many events in quick succession
8590
// this may not be enough, and you will have to use [WithBufferSize] to increase

fsnotify_test.go

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -680,66 +680,6 @@ func TestWatchRemove(t *testing.T) {
680680
CHMOD "/file"
681681
`},
682682

683-
{"remove watched directory", func(t *testing.T, w *Watcher, tmp string) {
684-
touch(t, tmp, "a")
685-
touch(t, tmp, "b")
686-
touch(t, tmp, "c")
687-
touch(t, tmp, "d")
688-
touch(t, tmp, "e")
689-
touch(t, tmp, "f")
690-
touch(t, tmp, "g")
691-
mkdir(t, tmp, "h")
692-
mkdir(t, tmp, "h", "a")
693-
mkdir(t, tmp, "i")
694-
mkdir(t, tmp, "i", "a")
695-
mkdir(t, tmp, "j")
696-
mkdir(t, tmp, "j", "a")
697-
addWatch(t, w, tmp)
698-
rmAll(t, tmp)
699-
}, `
700-
remove /
701-
remove /a
702-
remove /b
703-
remove /c
704-
remove /d
705-
remove /e
706-
remove /f
707-
remove /g
708-
remove /h
709-
remove /i
710-
remove /j
711-
712-
# TODO: this is broken; I've also seen (/i and /j missing):
713-
# REMOVE "/"
714-
# REMOVE "/a"
715-
# REMOVE "/b"
716-
# REMOVE "/c"
717-
# REMOVE "/d"
718-
# REMOVE "/e"
719-
# REMOVE "/f"
720-
# REMOVE "/g"
721-
# WRITE "/h"
722-
# WRITE "/h"
723-
windows:
724-
REMOVE "/"
725-
REMOVE "/a"
726-
REMOVE "/b"
727-
REMOVE "/c"
728-
REMOVE "/d"
729-
REMOVE "/e"
730-
REMOVE "/f"
731-
REMOVE "/g"
732-
REMOVE "/h"
733-
REMOVE "/i"
734-
REMOVE "/j"
735-
WRITE "/h"
736-
WRITE "/h"
737-
WRITE "/i"
738-
WRITE "/i"
739-
WRITE "/j"
740-
WRITE "/j"
741-
`},
742-
743683
{"remove recursive", func(t *testing.T, w *Watcher, tmp string) {
744684
recurseOnly(t)
745685

@@ -778,6 +718,66 @@ func TestWatchRemove(t *testing.T) {
778718
tt := tt
779719
tt.run(t)
780720
}
721+
722+
t.Run("remove watched directory", func(t *testing.T) {
723+
t.Parallel()
724+
tmp := t.TempDir()
725+
726+
w := newCollector(t)
727+
w.collect(t)
728+
729+
touch(t, tmp, "a")
730+
touch(t, tmp, "b")
731+
touch(t, tmp, "c")
732+
touch(t, tmp, "d")
733+
touch(t, tmp, "e")
734+
touch(t, tmp, "f")
735+
touch(t, tmp, "g")
736+
mkdir(t, tmp, "h")
737+
mkdir(t, tmp, "h", "a")
738+
mkdir(t, tmp, "i")
739+
mkdir(t, tmp, "i", "a")
740+
mkdir(t, tmp, "j")
741+
mkdir(t, tmp, "j", "a")
742+
addWatch(t, w.w, tmp)
743+
rmAll(t, tmp)
744+
745+
if runtime.GOOS != "windows" {
746+
cmpEvents(t, tmp, w.stop(t), newEvents(t, `
747+
remove /
748+
remove /a
749+
remove /b
750+
remove /c
751+
remove /d
752+
remove /e
753+
remove /f
754+
remove /g
755+
remove /h
756+
remove /i
757+
remove /j`))
758+
return
759+
}
760+
761+
// ReadDirectoryChangesW gives undefined results: not all files are
762+
// always present. So test only that 1) we got the directory itself, and
763+
// 2) we don't get events for unspected files.
764+
var (
765+
events = w.stop(t)
766+
found bool
767+
)
768+
for _, e := range events {
769+
if e.Name == tmp && e.Has(Remove) {
770+
found = true
771+
continue
772+
}
773+
if filepath.Dir(e.Name) != tmp {
774+
t.Errorf("unexpected event: %s", e)
775+
}
776+
}
777+
if !found {
778+
t.Fatalf("didn't see directory in:\n%s", events)
779+
}
780+
})
781781
}
782782

783783
func TestWatchRecursive(t *testing.T) {

mkdoc.zsh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ watcher=$(<<EOF
6262
// Paths can be added as "C:\\path\\to\\dir", but forward slashes
6363
// ("C:/path/to/dir") will also work.
6464
//
65+
// When a watched directory is removed it will always send an event for the
66+
// directory itself, but may not send events for all files in that directory.
67+
// Sometimes it will send events for all times, sometimes it will send no
68+
// events, and often only for some files.
69+
//
6570
// The default buffer size is 64K, which is the largest value that is guaranteed
6671
// to work with SMB filesystems. If you have many events in quick succession
6772
// this may not be enough, and you will have to use [WithBufferSize] to increase

0 commit comments

Comments
 (0)