type Watcher … type pathInfo … // NewWatcher creates a new Watcher. func NewWatcher() (*Watcher, error) { … } // NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events // channel. // // The main use case for this is situations with a very large number of events // where the kernel buffer size can't be increased (e.g. due to lack of // permissions). An unbuffered Watcher will perform better for almost all use // cases, and whenever possible you will be better off increasing the kernel // buffers instead of adding a large userspace buffer. func NewBufferedWatcher(sz uint) (*Watcher, error) { … } // newKqueue creates a new kernel event queue and returns a descriptor. // // This registers a new event on closepipe, which will trigger an event when // it's closed. This way we can use kevent() without timeout/polling; without // the closepipe, it would block forever and we wouldn't be able to stop it at // all. func newKqueue() (kq int, closepipe [2]int, err error) { … } // Returns true if the event was sent, or false if watcher is closed. func (w *Watcher) sendEvent(e Event) bool { … } // Returns true if the error was sent, or false if watcher is closed. func (w *Watcher) sendError(err error) bool { … } // Close removes all watches and closes the Events channel. func (w *Watcher) Close() error { … } // Add starts monitoring the path for changes. // // A path can only be watched once; watching it more than once is a no-op and will // not return an error. Paths that do not yet exist on the filesystem cannot be // watched. // // A watch will be automatically removed if the watched path is deleted or // renamed. The exception is the Windows backend, which doesn't remove the // watcher on renames. // // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special // filesystems (/proc, /sys, etc.) generally don't work. // // Returns [ErrClosed] if [Watcher.Close] was called. // // See [Watcher.AddWith] for a version that allows adding options. // // # Watching directories // // All files in a directory are monitored, including new files that are created // after the watcher is started. Subdirectories are not watched (i.e. it's // non-recursive). // // # Watching files // // Watching individual files (rather than directories) is generally not // recommended as many programs (especially editors) update files atomically: it // will write to a temporary file which is then moved to to destination, // overwriting the original (or some variant thereof). The watcher on the // original file is now lost, as that no longer exists. // // The upshot of this is that a power failure or crash won't leave a // half-written file. // // Watch the parent directory and use Event.Name to filter out files you're not // interested in. There is an example of this in cmd/fsnotify/file.go. func (w *Watcher) Add(name string) error { … } // AddWith is like [Watcher.Add], but allows adding options. When using Add() // the defaults described below are used. // // Possible options are: // // - [WithBufferSize] sets the buffer size for the Windows backend; no-op on // other platforms. The default is 64K (65536 bytes). func (w *Watcher) AddWith(name string, opts ...addOpt) error { … } // Remove stops monitoring the path for changes. // // Directories are always removed non-recursively. For example, if you added // /tmp/dir and /tmp/dir/subdir then you will need to remove both. // // Removing a path that has not yet been added returns [ErrNonExistentWatch]. // // Returns nil if [Watcher.Close] was called. func (w *Watcher) Remove(name string) error { … } func (w *Watcher) remove(name string, unwatchFiles bool) error { … } // WatchList returns all paths explicitly added with [Watcher.Add] (and are not // yet removed). // // Returns nil if [Watcher.Close] was called. func (w *Watcher) WatchList() []string { … } const noteAllEvents … // addWatch adds name to the watched file set; the flags are interpreted as // described in kevent(2). // // Returns the real path to the file which was added, with symlinks resolved. func (w *Watcher) addWatch(name string, flags uint32) (string, error) { … } // readEvents reads from kqueue and converts the received kevents into // Event values that it sends down the Events channel. func (w *Watcher) readEvents() { … } // newEvent returns an platform-independent Event based on kqueue Fflags. func (w *Watcher) newEvent(name string, mask uint32) Event { … } // watchDirectoryFiles to mimic inotify when adding a watch on a directory func (w *Watcher) watchDirectoryFiles(dirPath string) error { … } // Search the directory for new files and send an event for them. // // This functionality is to have the BSD watcher match the inotify, which sends // a create event for files created in a watched directory. func (w *Watcher) sendDirectoryChangeEvents(dir string) error { … } // sendFileCreatedEvent sends a create event if the file isn't already being tracked. func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fi os.FileInfo) (err error) { … } func (w *Watcher) internalWatch(name string, fi os.FileInfo) (string, error) { … } // Register events with the queue. func (w *Watcher) register(fds []int, flags int, fflags uint32) error { … } // read retrieves pending events, or waits until an event occurs. func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { … }