summaryrefslogtreecommitdiff
path: root/lisp/filenotify.el
diff options
context:
space:
mode:
authorMichael Albinus <michael.albinus@gmx.de>2015-10-25 14:18:17 +0100
committerMichael Albinus <michael.albinus@gmx.de>2015-10-25 14:18:17 +0100
commitab116b19eda6bf42b11f7b902c749a77d7cb7683 (patch)
treeb0b5cfb9181ff9000d4d4c93d714df02d92c27b4 /lisp/filenotify.el
parent92c63c6552fc71961f0bb941d651ac359b9e1edc (diff)
downloademacs-ab116b19eda6bf42b11f7b902c749a77d7cb7683.tar.gz
Introduce `stopped' event in file notification
* lisp/filenotify.el (file-notify--rm-descriptor): New defun. (file-notify-rm-watch): Use it. (file-notify-callback): Implement `stopped' event. (file-notify-add-watch): Mention `stopped' in the docstring. Check, that upper directory exists. * test/automated/file-notify-tests.el (file-notify-test01-add-watch): Add two test cases. (file-notify-test02-events): Handle also `stopped' event. (file-notify-test04-file-validity): Add another test case.
Diffstat (limited to 'lisp/filenotify.el')
-rw-r--r--lisp/filenotify.el73
1 files changed, 57 insertions, 16 deletions
diff --git a/lisp/filenotify.el b/lisp/filenotify.el
index b9f59dedfde..55d9028f252 100644
--- a/lisp/filenotify.el
+++ b/lisp/filenotify.el
@@ -48,6 +48,33 @@ The value in the hash table is a list
Several values for a given DIR happen only for `inotify', when
different files from the same directory are watched.")
+(defun file-notify--rm-descriptor (descriptor)
+ "Remove DESCRIPTOR from `file-notify-descriptors'.
+DESCRIPTOR should be an object returned by `file-notify-add-watch'.
+If it is registered in `file-notify-descriptors', a stopped event is sent."
+ (let* ((desc (if (consp descriptor) (car descriptor) descriptor))
+ (file (if (consp descriptor) (cdr descriptor)))
+ (registered (gethash desc file-notify-descriptors))
+ (dir (car registered)))
+
+ (when (consp registered)
+ ;; Send `stopped' event.
+ (dolist (entry (cdr registered))
+ (funcall (cdr entry)
+ `(,(file-notify--descriptor desc) stopped
+ ,(or (and (stringp (car entry))
+ (expand-file-name (car entry) dir))
+ dir))))
+
+ ;; Modify `file-notify-descriptors'.
+ (if (not file)
+ (remhash desc file-notify-descriptors)
+ (setcdr registered
+ (delete (assoc file (cdr registered)) (cdr registered)))
+ (if (null (cdr registered))
+ (remhash desc file-notify-descriptors)
+ (puthash desc registered file-notify-descriptors))))))
+
;; This function is used by `gfilenotify', `inotify' and `w32notify' events.
;;;###autoload
(defun file-notify-handle-event (event)
@@ -111,7 +138,7 @@ EVENT is the cadr of the event in `file-notify-handle-event'
(registered (gethash desc file-notify-descriptors))
(actions (nth 1 event))
(file (file-notify--event-file-name event))
- file1 callback pending-event)
+ file1 callback pending-event stopped)
;; Make actions a list.
(unless (consp actions) (setq actions (cons actions nil)))
@@ -158,6 +185,8 @@ EVENT is the cadr of the event in `file-notify-handle-event'
'renamed)
;; inotify, w32notify.
+ ((eq action 'ignored)
+ (setq stopped t actions nil))
((eq action 'attrib) 'attribute-changed)
((memq action '(create added)) 'created)
((memq action '(modify modified)) 'changed)
@@ -194,6 +223,17 @@ EVENT is the cadr of the event in `file-notify-handle-event'
(funcall (cadr pending-event) (car pending-event))
(setq pending-event nil))
+ ;; Check for stopped.
+ (setq
+ stopped
+ (or
+ stopped
+ (and
+ (memq action '(deleted renamed))
+ (= (length (cdr registered)) 1)
+ (string-equal
+ (or (file-name-nondirectory file) "") (car (cadr registered))))))
+
;; Apply callback.
(when (and action
(or
@@ -213,7 +253,11 @@ EVENT is the cadr of the event in `file-notify-handle-event'
`(,(file-notify--descriptor desc) ,action ,file ,file1))
(funcall
callback
- `(,(file-notify--descriptor desc) ,action ,file))))))))
+ `(,(file-notify--descriptor desc) ,action ,file)))))
+
+ ;; Modify `file-notify-descriptors'.
+ (when stopped
+ (file-notify--rm-descriptor (file-notify--descriptor desc))))))
;; `gfilenotify' and `w32notify' return a unique descriptor for every
;; `file-notify-add-watch', while `inotify' returns a unique
@@ -251,17 +295,18 @@ following:
`changed' -- FILE has changed
`renamed' -- FILE has been renamed to FILE1
`attribute-changed' -- a FILE attribute was changed
+ `stopped' -- watching FILE has been stopped
FILE is the name of the file whose event is being reported."
;; Check arguments.
(unless (stringp file)
- (signal 'wrong-type-argument (list file)))
+ (signal 'wrong-type-argument `(,file)))
(setq file (expand-file-name file))
(unless (and (consp flags)
(null (delq 'change (delq 'attribute-change (copy-tree flags)))))
- (signal 'wrong-type-argument (list flags)))
+ (signal 'wrong-type-argument `(,flags)))
(unless (functionp callback)
- (signal 'wrong-type-argument (list callback)))
+ (signal 'wrong-type-argument `(,callback)))
(let* ((handler (find-file-name-handler file 'file-notify-add-watch))
(dir (directory-file-name
@@ -270,6 +315,9 @@ FILE is the name of the file whose event is being reported."
(file-name-directory file))))
desc func l-flags registered)
+ (unless (file-directory-p dir)
+ (signal 'file-notify-error `("Directory does not exist" ,dir)))
+
(if handler
;; A file name handler could exist even if there is no local
;; file notification support.
@@ -326,10 +374,10 @@ FILE is the name of the file whose event is being reported."
DESCRIPTOR should be an object returned by `file-notify-add-watch'."
(let* ((desc (if (consp descriptor) (car descriptor) descriptor))
(file (if (consp descriptor) (cdr descriptor)))
- (dir (car (gethash desc file-notify-descriptors)))
+ (registered (gethash desc file-notify-descriptors))
+ (dir (car registered))
(handler (and (stringp dir)
- (find-file-name-handler dir 'file-notify-rm-watch)))
- (registered (gethash desc file-notify-descriptors)))
+ (find-file-name-handler dir 'file-notify-rm-watch))))
(when (stringp dir)
;; Call low-level function.
@@ -351,14 +399,7 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'."
(file-notify-error nil)))
;; Modify `file-notify-descriptors'.
- (if (not file)
- (remhash desc file-notify-descriptors)
-
- (setcdr registered
- (delete (assoc file (cdr registered)) (cdr registered)))
- (if (null (cdr registered))
- (remhash desc file-notify-descriptors)
- (puthash desc registered file-notify-descriptors))))))
+ (file-notify--rm-descriptor descriptor))))
(defun file-notify-valid-p (descriptor)
"Check a watch specified by its DESCRIPTOR.