- ;; Check, that event is meant for us.
- (unless (setq callback (nth 2 registered))
- (setq actions nil))
-
- ;; Loop over actions. In fact, more than one action happens only
- ;; for `inotify'.
- (dolist (action actions)
-
- ;; Send pending event, if it doesn't match.
- (when (and pending-event
- ;; The cookie doesn't match.
- (not (eq (file-notify--event-cookie pending-event)
- (file-notify--event-cookie event)))
- (or
- ;; inotify.
- (and (eq (nth 1 pending-event) 'moved-from)
- (not (eq action 'moved-to)))
- ;; w32notify.
- (and (eq (nth 1 pending-event) 'renamed-from)
- (not (eq action 'renamed-to)))))
- (funcall callback
- (list desc 'deleted
- (file-notify--event-file-name pending-event)))
- (setq file-notify--pending-events
- (delete pending-event file-notify--pending-events)))
-
- ;; Map action. We ignore all events which cannot be mapped.
- (setq action
- (cond
- ;; gfilenotify.
- ((memq action '(attribute-changed changed created deleted)) action)
- ((eq action 'moved)
- (setq file1 (file-notify--event-file1-name event))
- 'renamed)
-
- ;; inotify.
- ((eq action 'attrib) 'attribute-changed)
- ((eq action 'create) 'created)
- ((eq action 'modify) 'changed)
- ((memq action '(delete 'delete-self move-self)) 'deleted)
- ;; Make the event pending.
- ((eq action 'moved-from)
- (add-to-list 'file-notify--pending-events
- (list desc action file
- (file-notify--event-cookie event)))
- nil)
- ;; Look for pending event.
- ((eq action 'moved-to)
- (if (null pending-event)
- 'created
- (setq file1 file
- file (file-notify--event-file-name pending-event)
- file-notify--pending-events
- (delete pending-event file-notify--pending-events))
- 'renamed))
-
- ;; w32notify.
- ((eq action 'added) 'created)
- ((eq action 'modified) 'changed)
- ((eq action 'removed) 'deleted)
- ;; Make the event pending.
- ((eq 'renamed-from action)
- (add-to-list 'file-notify--pending-events
- (list desc action file
- (file-notify--event-cookie event)))
- nil)
- ;; Look for pending event.
- ((eq 'renamed-to action)
- (if (null pending-event)
- 'created
- (setq file1 file
- file (file-notify--event-file-name pending-event)
- file-notify--pending-events
- (delete pending-event file-notify--pending-events))
- 'renamed))))
-
- ;; Apply callback.
- (when (and action
- (or
- ;; If there is no relative file name for that watch,
- ;; we watch the whole directory.
- (null (nth 1 registered))
- ;; File matches.
- (string-equal
- (nth 1 registered) (file-name-nondirectory file))
- ;; File1 matches.
- (and (stringp file1)
- (string-equal
- (nth 1 registered) (file-name-nondirectory file1)))))
- (if file1
- (funcall callback (list desc action file file1))
- (funcall callback (list desc action file)))))))
-
+ ;; Loop over registered entries. In fact, more than one entry
+ ;; happens only for `inotify'.
+ (dolist (entry (cdr registered))
+
+ ;; Check, that event is meant for us.
+ (unless (setq callback (cdr entry))
+ (setq actions nil))
+
+ ;; Loop over actions. In fact, more than one action happens only
+ ;; for `inotify' and `kqueue'.
+ (dolist (action actions)
+
+ ;; Send pending event, if it doesn't match.
+ (when (and file-notify--pending-event
+ ;; The cookie doesn't match.
+ (not (eq (file-notify--event-cookie
+ (car file-notify--pending-event))
+ (file-notify--event-cookie event)))
+ (or
+ ;; inotify.
+ (and (eq (nth 1 (car file-notify--pending-event))
+ 'moved-from)
+ (not (eq action 'moved-to)))
+ ;; w32notify.
+ (and (eq (nth 1 (car file-notify--pending-event))
+ 'renamed-from)
+ (not (eq action 'renamed-to)))))
+ (setq pending-event file-notify--pending-event
+ file-notify--pending-event nil)
+ (setcar (cdar pending-event) 'deleted))
+
+ ;; Map action. We ignore all events which cannot be mapped.
+ (setq action
+ (cond
+ ((memq action
+ '(attribute-changed changed created deleted renamed))
+ action)
+ ((memq action '(moved rename))
+ ;; The kqueue rename event does not return file1 in
+ ;; case a file monitor is established.
+ (if (setq file1 (file-notify--event-file1-name event))
+ 'renamed 'deleted))
+ ((eq action 'ignored)
+ (setq stopped t actions nil))
+ ((memq action '(attrib link)) 'attribute-changed)
+ ((memq action '(create added)) 'created)
+ ((memq action '(modify modified write)) 'changed)
+ ((memq action '(delete delete-self move-self removed)) 'deleted)
+ ;; Make the event pending.
+ ((memq action '(moved-from renamed-from))
+ (setq file-notify--pending-event
+ `((,desc ,action ,file ,(file-notify--event-cookie event))
+ ,callback))
+ nil)
+ ;; Look for pending event.
+ ((memq action '(moved-to renamed-to))
+ (if (null file-notify--pending-event)
+ 'created
+ (setq file1 file
+ file (file-notify--event-file-name
+ (car file-notify--pending-event)))
+ ;; If the source is handled by another watch, we
+ ;; must fire the rename event there as well.
+ (when (not (equal (file-notify--descriptor desc file1)
+ (file-notify--descriptor
+ (caar file-notify--pending-event)
+ (file-notify--event-file-name
+ file-notify--pending-event))))
+ (setq pending-event
+ `((,(caar file-notify--pending-event)
+ renamed ,file ,file1)
+ ,(cadr file-notify--pending-event))))
+ (setq file-notify--pending-event nil)
+ 'renamed))))
+
+ ;; Apply pending callback.
+ (when pending-event
+ (setcar
+ (car pending-event)
+ (file-notify--descriptor
+ (caar pending-event)
+ (file-notify--event-file-name file-notify--pending-event)))
+ (funcall (cadr pending-event) (car pending-event))
+ (setq pending-event nil))
+
+ ;; Apply callback.
+ (when (and action
+ (or
+ ;; If there is no relative file name for that watch,
+ ;; we watch the whole directory.
+ (null (nth 0 entry))
+ ;; File matches.
+ (string-equal
+ (nth 0 entry) (file-name-nondirectory file))
+ ;; Directory matches.
+ (string-equal
+ (file-name-nondirectory file)
+ (file-name-nondirectory (car registered)))
+ ;; File1 matches.
+ (and (stringp file1)
+ (string-equal
+ (nth 0 entry) (file-name-nondirectory file1)))))
+ ;;(message
+ ;;"file-notify-callback %S %S %S %S %S"
+ ;;(file-notify--descriptor desc (car entry))
+ ;;action file file1 registered)
+ (if file1
+ (funcall
+ callback
+ `(,(file-notify--descriptor desc (car entry))
+ ,action ,file ,file1))
+ (funcall
+ callback
+ `(,(file-notify--descriptor desc (car entry)) ,action ,file))))
+
+ ;; Send `stopped' event.
+ (when (or stopped
+ (and (memq action '(deleted renamed))
+ ;; Not, when a file is backed up.
+ (not (and (stringp file1) (backup-file-name-p file1)))
+ ;; Watched file or directory is concerned.
+ (string-equal
+ file (file-notify--event-watched-file event))))
+ (file-notify-rm-watch (file-notify--descriptor desc (car entry))))))))
+
+;; `kqueue', `gfilenotify' and `w32notify' return a unique descriptor
+;; for every `file-notify-add-watch', while `inotify' returns a unique
+;; descriptor per inode only.