()
| 151 | } |
| 152 | |
| 153 | func (d *naiveNotify) loop() { //nolint:gocyclo |
| 154 | defer close(d.wrappedEvents) |
| 155 | for e := range d.events { |
| 156 | // The Windows fsnotify event stream sometimes gets events with empty names |
| 157 | // that are also sent to the error stream. Hmmmm... |
| 158 | if e.Name == "" { |
| 159 | continue |
| 160 | } |
| 161 | |
| 162 | if e.Op&fsnotify.Create != fsnotify.Create { |
| 163 | if d.shouldNotify(e.Name) { |
| 164 | d.wrappedEvents <- FileEvent(e.Name) |
| 165 | } |
| 166 | continue |
| 167 | } |
| 168 | |
| 169 | if d.isWatcherRecursive { |
| 170 | if d.shouldNotify(e.Name) { |
| 171 | d.wrappedEvents <- FileEvent(e.Name) |
| 172 | } |
| 173 | continue |
| 174 | } |
| 175 | |
| 176 | // If the watcher is not recursive, we have to walk the tree |
| 177 | // and add watches manually. We fire the event while we're walking the tree. |
| 178 | // because it's a bit more elegant that way. |
| 179 | // |
| 180 | // TODO(dbentley): if there's a delete should we call d.watcher.Remove to prevent leaking? |
| 181 | err := filepath.WalkDir(e.Name, func(path string, info fs.DirEntry, err error) error { |
| 182 | if err != nil { |
| 183 | return err |
| 184 | } |
| 185 | |
| 186 | if d.shouldNotify(path) { |
| 187 | d.wrappedEvents <- FileEvent(path) |
| 188 | } |
| 189 | |
| 190 | // TODO(dmiller): symlinks 😭 |
| 191 | |
| 192 | shouldWatch := false |
| 193 | if info.IsDir() { |
| 194 | // watch directories unless we can skip them entirely |
| 195 | if d.shouldSkipDir(path) { |
| 196 | return filepath.SkipDir |
| 197 | } |
| 198 | |
| 199 | shouldWatch = true |
| 200 | } else { |
| 201 | // watch files that are explicitly named, but don't watch others |
| 202 | _, ok := d.notifyList[path] |
| 203 | if ok { |
| 204 | shouldWatch = true |
| 205 | } |
| 206 | } |
| 207 | if shouldWatch { |
| 208 | err := d.add(path) |
| 209 | if err != nil && !os.IsNotExist(err) { |
| 210 | logrus.Infof("Error watching path %s: %s", e.Name, err) |
no test coverage detected