Open lsegal opened 6 years ago
After digging through some internals, I figured it out.
Pro tip: to watch a full drive, the watch path should be in the form C:...
, not C:\...
. The \
breaks everything. This might be something worth documenting (or explicitly handling do people can't make this mistake).
@lsegal Actually it is a bug in this case. However unusual, to watch the whole drive, it should be working. Thanks for debugging this!
@lsegal Thanks for reporting this. It definitely looks like a bug since there shouldn't be any difference between watching root directory and any other path.
Not sure what happened on this since my last tests but it seems like the C:...
trick no longer works. Wondering if there's been any movement on this?
I should point out that it may seem odd to watch a full drive like C:\
, but consider that this is also broken for secondary drives like small removable ones that get mounted to D:, E:, etc., where watching a full drive would be much more sensible.
FYI I was doing some more digging on this and found debug logging, which is great. I've managed to reproduce a potential issue with the following minimal case:
package main
import (
"fmt"
"github.com/rjeczalik/notify"
)
func main() {
ch := make(chan notify.EventInfo)
err := notify.Watch(`D:...`, ch, notify.All)
if err != nil {
panic(err)
}
for {
fmt.Println(<-ch)
}
}
If I then go run -tags debug main.go
and create a new folder or file in the root of D:\
followed by a subdirectory of D:\
, I see the following debug info with no printed event on the latter dir creation:
[D] dispatching notify.Create on "D:\\New folder"
notify.Create: "D:\New folder"
[D] dispatching notify.Remove on "D:\\New folder"
notify.Remove: "D:\New folder"
[D] dispatching notify.Create on "D:\\Code\\New folder"
[D] dispatch did not reach leaf:Node D:\Code: file does not exist
Digging further, it seems like the error is returned from node.go#L222 because r.nd.Child
does not contain child directories for the root D:
volume. Printing the contents of that map shows:
map[D::{D: map[] map[:{D:\ map[0xc042014300:notify.Write|notify.Rename|recursive|notify.Create|notify.Remove <nil>:notify.Create|notify.Remove|notify.Write|notify.Rename|recursive] map[]}]}]
I'd expect to see other root folders in that list.
Another update: I've also noticed that this same behavioral bug is present on macOS, so it seems like related to the recursive watcher not correctly initializing r.nd.Child
map when given a root path.
Thank you @lsegal for this thoughtful investigation! Indeed, this isn't a problem with Windows watcher itself.
If
notify.Watch()
is called on the root of a drive on Windows using recursive syntax ("..."), events don't seem to trigger.Minimal repro using a slightly modified version of the Recursive example in docs:
Trying to watch for events on
C:\
doesn't seem to fire when changes are made inside my user dir. Only changes directly inC:\
trigger. On the other hand, if I use the commented out HOMEPATH version, I see changes in subdirectories (like Chrome touching files in AppData, for example).If this is intended behavior or some known limitation, are there any workarounds for this?