diff options
| author | Michael Albinus | 2015-09-20 18:44:36 +0200 |
|---|---|---|
| committer | Michael Albinus | 2015-09-20 18:44:36 +0200 |
| commit | f5bdcb3221ba28326b47210773d84c49cc9b4a1e (patch) | |
| tree | f316feaf1d548b157ef1a3cfcbb831864e50c003 | |
| parent | ab11a1cf27ebe3791df45cccde3c851affd184dd (diff) | |
| download | emacs-f5bdcb3221ba28326b47210773d84c49cc9b4a1e.tar.gz emacs-f5bdcb3221ba28326b47210773d84c49cc9b4a1e.zip | |
Improve file notifications, especially for Tramp
* doc/lispref/files.texi (Magic File Names):
Mention `file-notify-valid-p'.
* doc/lispref/os.texi (File Notifications):
Describe `file-notify-valid-p'.
* etc/NEWS: Add `file-notify-valid-p'.
* lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch):
Improve implementation.
(tramp-gvfs-monitor-file-process-filter): Rename from
`tramp-gvfs-file-gvfs-monitor-file-process-filter'. Delete
process if appropriate.
* lisp/net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch):
Improve implementation.
(tramp-sh-gvfs-monitor-dir-process-filter): Rename from
`tramp-sh-file-gvfs-monitor-dir-process-filter'. Delete process
if appropriate.
(tramp-sh-inotifywait-process-filter): Rename from
`tramp-sh-file-inotifywait-process-filter'. Delete process if
appropriate.
* lisp/net/tramp.el (tramp-handle-file-notify-rm-watch):
Use `delete-process'
(tramp-handle-file-notify-valid-p): Check also, that file or
directory to be watched still exists.
* test/automated/file-notify-tests.el (file-notify--test-timeout):
New defun. Use it at all places a timeout is needed.
(file-notify--test-cleanup): Delete directories recursively.
Cleanup also Tramp connections.
(file-notify-test02-events): Add tests for `attribute-change'.
(file-notify-test04-file-validity, file-notify-test05-dir-validity):
Add tests for `file-notify-rm-watch'.
| -rw-r--r-- | doc/lispref/files.texi | 2 | ||||
| -rw-r--r-- | doc/lispref/os.texi | 11 | ||||
| -rw-r--r-- | etc/NEWS | 13 | ||||
| -rw-r--r-- | lisp/net/tramp-gvfs.el | 49 | ||||
| -rw-r--r-- | lisp/net/tramp-sh.el | 60 | ||||
| -rw-r--r-- | lisp/net/tramp.el | 12 | ||||
| -rw-r--r-- | test/automated/file-notify-tests.el | 140 |
7 files changed, 220 insertions, 67 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index ffc7936107b..db2ecc08f95 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi | |||
| @@ -2854,6 +2854,7 @@ first, before handlers for jobs such as remote file access. | |||
| 2854 | @code{file-name-nondirectory}, | 2854 | @code{file-name-nondirectory}, |
| 2855 | @code{file-name-sans-versions}, @code{file-newer-than-file-p}, | 2855 | @code{file-name-sans-versions}, @code{file-newer-than-file-p}, |
| 2856 | @code{file-notify-add-watch}, @code{file-notify-rm-watch}, | 2856 | @code{file-notify-add-watch}, @code{file-notify-rm-watch}, |
| 2857 | @code{file-notify-valid-p}, | ||
| 2857 | @code{file-ownership-preserved-p}, | 2858 | @code{file-ownership-preserved-p}, |
| 2858 | @code{file-readable-p}, @code{file-regular-p}, | 2859 | @code{file-readable-p}, @code{file-regular-p}, |
| 2859 | @code{file-remote-p}, @code{file-selinux-context}, | 2860 | @code{file-remote-p}, @code{file-selinux-context}, |
| @@ -2907,6 +2908,7 @@ first, before handlers for jobs such as remote file access. | |||
| 2907 | @code{file-name-nondirec@discretionary{}{}{}tory}, | 2908 | @code{file-name-nondirec@discretionary{}{}{}tory}, |
| 2908 | @code{file-name-sans-versions}, @code{file-newer-than-file-p}, | 2909 | @code{file-name-sans-versions}, @code{file-newer-than-file-p}, |
| 2909 | @code{file-notify-add-watch}, @code{file-notify-rm-watch}, | 2910 | @code{file-notify-add-watch}, @code{file-notify-rm-watch}, |
| 2911 | @code{file-notify-valid-p}, | ||
| 2910 | @code{file-ownership-pre@discretionary{}{}{}served-p}, | 2912 | @code{file-ownership-pre@discretionary{}{}{}served-p}, |
| 2911 | @code{file-readable-p}, @code{file-regular-p}, | 2913 | @code{file-readable-p}, @code{file-regular-p}, |
| 2912 | @code{file-remote-p}, @code{file-selinux-context}, | 2914 | @code{file-remote-p}, @code{file-selinux-context}, |
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index cb583038979..f5eecb2d569 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi | |||
| @@ -2692,6 +2692,17 @@ Removes an existing file watch specified by its @var{descriptor}. | |||
| 2692 | @code{file-notify-add-watch}. | 2692 | @code{file-notify-add-watch}. |
| 2693 | @end defun | 2693 | @end defun |
| 2694 | 2694 | ||
| 2695 | @defun file-notify-valid-p descriptor | ||
| 2696 | Checks a watch specified by its @var{descriptor} for validity. | ||
| 2697 | @var{descriptor} should be an object returned by | ||
| 2698 | @code{file-notify-add-watch}. | ||
| 2699 | |||
| 2700 | A watch can become invalid if the file or directory it watches is | ||
| 2701 | deleted, or if the watcher thread exits abnormally for any other | ||
| 2702 | reason. Removing the watch by calling @code{file-notify-rm-watch} | ||
| 2703 | also makes it invalid. | ||
| 2704 | @end defun | ||
| 2705 | |||
| 2695 | @node Dynamic Libraries | 2706 | @node Dynamic Libraries |
| 2696 | @section Dynamically Loaded Libraries | 2707 | @section Dynamically Loaded Libraries |
| 2697 | @cindex dynamic libraries | 2708 | @cindex dynamic libraries |
| @@ -412,7 +412,6 @@ the old behavior -- *shell* buffer displays in current window -- use | |||
| 412 | (add-to-list 'display-buffer-alist | 412 | (add-to-list 'display-buffer-alist |
| 413 | '("^\\*shell\\*$" . (display-buffer-same-window))). | 413 | '("^\\*shell\\*$" . (display-buffer-same-window))). |
| 414 | 414 | ||
| 415 | |||
| 416 | ** EIEIO | 415 | ** EIEIO |
| 417 | +++ | 416 | +++ |
| 418 | *** The `:protection' slot option is not obeyed any more. | 417 | *** The `:protection' slot option is not obeyed any more. |
| @@ -657,11 +656,17 @@ plist will contain a :peer element that has the output of | |||
| 657 | 656 | ||
| 658 | ** Tramp | 657 | ** Tramp |
| 659 | 658 | ||
| 659 | +++ | ||
| 660 | *** New connection method "nc", which allows to access dumb busyboxes. | 660 | *** New connection method "nc", which allows to access dumb busyboxes. |
| 661 | 661 | ||
| 662 | +++ | ||
| 662 | *** Method-specific parameters can be overwritten now with variable | 663 | *** Method-specific parameters can be overwritten now with variable |
| 663 | `tramp-connection-properties'. | 664 | `tramp-connection-properties'. |
| 664 | 665 | ||
| 666 | --- | ||
| 667 | *** Handler for `file-notify-valid-p' for remote machines that support | ||
| 668 | filesystem notifications. | ||
| 669 | |||
| 665 | ** SQL mode | 670 | ** SQL mode |
| 666 | 671 | ||
| 667 | *** New user variable `sql-default-directory' enables remote | 672 | *** New user variable `sql-default-directory' enables remote |
| @@ -822,9 +827,15 @@ make the new option `eshell-destroy-buffer-when-process-dies' non-nil. | |||
| 822 | ** tar-mode: new `tar-new-entry' command, allowing for new members to | 827 | ** tar-mode: new `tar-new-entry' command, allowing for new members to |
| 823 | be added to the archive. | 828 | be added to the archive. |
| 824 | 829 | ||
| 830 | --- | ||
| 825 | ** Autorevert: dired buffers are also auto-reverted via file | 831 | ** Autorevert: dired buffers are also auto-reverted via file |
| 826 | notifications, if Emacs is compiled with file notification support. | 832 | notifications, if Emacs is compiled with file notification support. |
| 827 | 833 | ||
| 834 | +++ | ||
| 835 | ** File Notifications: the new function `file-notify-valid-p' checks, | ||
| 836 | whether a file notification descriptor still corresponds to an | ||
| 837 | activate watch. | ||
| 838 | |||
| 828 | ** Obsolete packages | 839 | ** Obsolete packages |
| 829 | 840 | ||
| 830 | --- | 841 | --- |
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index cf42b5951f7..b7b0a1c016f 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el | |||
| @@ -1003,27 +1003,48 @@ file names." | |||
| 1003 | v (concat localname filename) | 1003 | v (concat localname filename) |
| 1004 | "file-name-all-completions" result)))))))) | 1004 | "file-name-all-completions" result)))))))) |
| 1005 | 1005 | ||
| 1006 | (defun tramp-gvfs-handle-file-notify-add-watch (file-name _flags _callback) | 1006 | (defun tramp-gvfs-handle-file-notify-add-watch (file-name flags _callback) |
| 1007 | "Like `file-notify-add-watch' for Tramp files." | 1007 | "Like `file-notify-add-watch' for Tramp files." |
| 1008 | (setq file-name (expand-file-name file-name)) | 1008 | (setq file-name (expand-file-name file-name)) |
| 1009 | (with-parsed-tramp-file-name file-name nil | 1009 | (with-parsed-tramp-file-name file-name nil |
| 1010 | (let ((p (start-process | 1010 | ;; We cannot watch directories, because `gvfs-monitor-dir' is not |
| 1011 | "gvfs-monitor-file" (generate-new-buffer " *gvfs-monitor-file*") | 1011 | ;; supported for gvfs-mounted directories. |
| 1012 | "gvfs-monitor-file" (tramp-gvfs-url-file-name file-name)))) | 1012 | (when (file-directory-p file-name) |
| 1013 | (tramp-error | ||
| 1014 | v 'file-notify-error "Monitoring not supported for `%s'" file-name)) | ||
| 1015 | (let* ((default-directory (file-name-directory file-name)) | ||
| 1016 | (events | ||
| 1017 | (cond | ||
| 1018 | ((and (memq 'change flags) (memq 'attribute-change flags)) | ||
| 1019 | '(created changed changes-done-hint moved deleted | ||
| 1020 | attribute-changed)) | ||
| 1021 | ((memq 'change flags) | ||
| 1022 | '(created changed changes-done-hint moved deleted)) | ||
| 1023 | ((memq 'attribute-change flags) '(attribute-changed)))) | ||
| 1024 | (p (start-process | ||
| 1025 | "gvfs-monitor-file" (generate-new-buffer " *gvfs-monitor-file*") | ||
| 1026 | "gvfs-monitor-file" (tramp-gvfs-url-file-name file-name)))) | ||
| 1013 | (if (not (processp p)) | 1027 | (if (not (processp p)) |
| 1014 | (tramp-error | 1028 | (tramp-error |
| 1015 | v 'file-notify-error "gvfs-monitor-file failed to start") | 1029 | v 'file-notify-error "Monitoring not supported for `%s'" file-name) |
| 1016 | (tramp-message | 1030 | (tramp-message |
| 1017 | v 6 "Run `%s', %S" (mapconcat 'identity (process-command p) " ") p) | 1031 | v 6 "Run `%s', %S" (mapconcat 'identity (process-command p) " ") p) |
| 1018 | (tramp-set-connection-property p "vector" v) | 1032 | (tramp-set-connection-property p "vector" v) |
| 1033 | (tramp-compat-process-put p 'events events) | ||
| 1034 | (tramp-compat-process-put p 'watch-name localname) | ||
| 1019 | (tramp-compat-set-process-query-on-exit-flag p nil) | 1035 | (tramp-compat-set-process-query-on-exit-flag p nil) |
| 1020 | (set-process-filter p 'tramp-gvfs-file-gvfs-monitor-file-process-filter) | 1036 | (set-process-filter p 'tramp-gvfs-monitor-file-process-filter) |
| 1021 | (with-current-buffer (process-buffer p) | 1037 | ;; There might be an error if the monitor is not supported. |
| 1022 | (setq default-directory (file-name-directory file-name))) | 1038 | ;; Give the filter a chance to read the output. |
| 1039 | (tramp-accept-process-output p 1) | ||
| 1040 | (unless (memq (process-status p) '(run open)) | ||
| 1041 | (tramp-error | ||
| 1042 | v 'file-notify-error "Monitoring not supported for `%s'" file-name)) | ||
| 1023 | p)))) | 1043 | p)))) |
| 1024 | 1044 | ||
| 1025 | (defun tramp-gvfs-file-gvfs-monitor-file-process-filter (proc string) | 1045 | (defun tramp-gvfs-monitor-file-process-filter (proc string) |
| 1026 | "Read output from \"gvfs-monitor-file\" and add corresponding file-notify events." | 1046 | "Read output from \"gvfs-monitor-file\" and add corresponding \ |
| 1047 | file-notify events." | ||
| 1027 | (let* ((rest-string (tramp-compat-process-get proc 'rest-string)) | 1048 | (let* ((rest-string (tramp-compat-process-get proc 'rest-string)) |
| 1028 | (dd (with-current-buffer (process-buffer proc) default-directory)) | 1049 | (dd (with-current-buffer (process-buffer proc) default-directory)) |
| 1029 | (ddu (regexp-quote (tramp-gvfs-url-file-name dd)))) | 1050 | (ddu (regexp-quote (tramp-gvfs-url-file-name dd)))) |
| @@ -1034,6 +1055,8 @@ file names." | |||
| 1034 | ;; Attribute change is returned in unused wording. | 1055 | ;; Attribute change is returned in unused wording. |
| 1035 | string (tramp-compat-replace-regexp-in-string | 1056 | string (tramp-compat-replace-regexp-in-string |
| 1036 | "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) | 1057 | "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) |
| 1058 | (when (string-match "Monitoring not supported" string) | ||
| 1059 | (delete-process proc)) | ||
| 1037 | 1060 | ||
| 1038 | (while (string-match | 1061 | (while (string-match |
| 1039 | (concat "^[\n\r]*" | 1062 | (concat "^[\n\r]*" |
| @@ -1041,10 +1064,10 @@ file names." | |||
| 1041 | "File = \\([^\n\r]+\\)[\n\r]+" | 1064 | "File = \\([^\n\r]+\\)[\n\r]+" |
| 1042 | "Event = \\([^[:blank:]]+\\)[\n\r]+") | 1065 | "Event = \\([^[:blank:]]+\\)[\n\r]+") |
| 1043 | string) | 1066 | string) |
| 1044 | (let ((action (intern-soft | 1067 | (let ((file (match-string 1 string)) |
| 1068 | (action (intern-soft | ||
| 1045 | (tramp-compat-replace-regexp-in-string | 1069 | (tramp-compat-replace-regexp-in-string |
| 1046 | "_" "-" (downcase (match-string 2 string))))) | 1070 | "_" "-" (downcase (match-string 2 string)))))) |
| 1047 | (file (match-string 1 string))) | ||
| 1048 | (setq string (replace-match "" nil nil string)) | 1071 | (setq string (replace-match "" nil nil string)) |
| 1049 | ;; File names are returned as URL paths. We must convert them. | 1072 | ;; File names are returned as URL paths. We must convert them. |
| 1050 | (when (string-match ddu file) | 1073 | (when (string-match ddu file) |
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 206ddfbfb55..433b2ba09c7 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el | |||
| @@ -3722,12 +3722,12 @@ Fall back to normal file name handler if no Tramp handler exists." | |||
| 3722 | "Like `file-notify-add-watch' for Tramp files." | 3722 | "Like `file-notify-add-watch' for Tramp files." |
| 3723 | (setq file-name (expand-file-name file-name)) | 3723 | (setq file-name (expand-file-name file-name)) |
| 3724 | (with-parsed-tramp-file-name file-name nil | 3724 | (with-parsed-tramp-file-name file-name nil |
| 3725 | (let* ((default-directory (file-name-directory file-name)) | 3725 | (let ((default-directory (file-name-directory file-name)) |
| 3726 | command events filter p sequence) | 3726 | command events filter p sequence) |
| 3727 | (cond | 3727 | (cond |
| 3728 | ;; gvfs-monitor-dir. | 3728 | ;; gvfs-monitor-dir. |
| 3729 | ((setq command (tramp-get-remote-gvfs-monitor-dir v)) | 3729 | ((setq command (tramp-get-remote-gvfs-monitor-dir v)) |
| 3730 | (setq filter 'tramp-sh-file-gvfs-monitor-dir-process-filter | 3730 | (setq filter 'tramp-sh-gvfs-monitor-dir-process-filter |
| 3731 | events | 3731 | events |
| 3732 | (cond | 3732 | (cond |
| 3733 | ((and (memq 'change flags) (memq 'attribute-change flags)) | 3733 | ((and (memq 'change flags) (memq 'attribute-change flags)) |
| @@ -3739,16 +3739,16 @@ Fall back to normal file name handler if no Tramp handler exists." | |||
| 3739 | sequence `(,command ,localname))) | 3739 | sequence `(,command ,localname))) |
| 3740 | ;; inotifywait. | 3740 | ;; inotifywait. |
| 3741 | ((setq command (tramp-get-remote-inotifywait v)) | 3741 | ((setq command (tramp-get-remote-inotifywait v)) |
| 3742 | (setq filter 'tramp-sh-file-inotifywait-process-filter | 3742 | (setq filter 'tramp-sh-inotifywait-process-filter |
| 3743 | events | 3743 | events |
| 3744 | (cond | 3744 | (cond |
| 3745 | ((and (memq 'change flags) (memq 'attribute-change flags)) | 3745 | ((and (memq 'change flags) (memq 'attribute-change flags)) |
| 3746 | (concat "create,modify,move,moved_from,moved_to,move_self," | 3746 | (concat "create,modify,move,moved_from,moved_to,move_self," |
| 3747 | "delete,delete_self,attrib")) | 3747 | "delete,delete_self,attrib,ignored")) |
| 3748 | ((memq 'change flags) | 3748 | ((memq 'change flags) |
| 3749 | (concat "create,modify,move,moved_from,moved_to,move_self," | 3749 | (concat "create,modify,move,moved_from,moved_to,move_self," |
| 3750 | "delete,delete_self")) | 3750 | "delete,delete_self,ignored")) |
| 3751 | ((memq 'attribute-change flags) "attrib")) | 3751 | ((memq 'attribute-change flags) "attrib,ignored")) |
| 3752 | sequence `(,command "-mq" "-e" ,events ,localname))) | 3752 | sequence `(,command "-mq" "-e" ,events ,localname))) |
| 3753 | ;; None. | 3753 | ;; None. |
| 3754 | (t (tramp-error | 3754 | (t (tramp-error |
| @@ -3770,13 +3770,20 @@ Fall back to normal file name handler if no Tramp handler exists." | |||
| 3770 | (mapconcat 'identity sequence " ")) | 3770 | (mapconcat 'identity sequence " ")) |
| 3771 | (tramp-message v 6 "Run `%s', %S" (mapconcat 'identity sequence " ") p) | 3771 | (tramp-message v 6 "Run `%s', %S" (mapconcat 'identity sequence " ") p) |
| 3772 | (tramp-set-connection-property p "vector" v) | 3772 | (tramp-set-connection-property p "vector" v) |
| 3773 | ;; Needed for `tramp-sh-file-gvfs-monitor-dir-process-filter'. | 3773 | ;; Needed for `tramp-sh-gvfs-monitor-dir-process-filter'. |
| 3774 | (tramp-compat-process-put p 'events events) | 3774 | (tramp-compat-process-put p 'events events) |
| 3775 | (tramp-compat-process-put p 'watch-name localname) | ||
| 3775 | (tramp-compat-set-process-query-on-exit-flag p nil) | 3776 | (tramp-compat-set-process-query-on-exit-flag p nil) |
| 3776 | (set-process-filter p filter) | 3777 | (set-process-filter p filter) |
| 3778 | ;; There might be an error if the monitor is not supported. | ||
| 3779 | ;; Give the filter a chance to read the output. | ||
| 3780 | (tramp-accept-process-output p 1) | ||
| 3781 | (unless (memq (process-status p) '(run open)) | ||
| 3782 | (tramp-error | ||
| 3783 | v 'file-notify-error "Monitoring not supported for `%s'" file-name)) | ||
| 3777 | p)))) | 3784 | p)))) |
| 3778 | 3785 | ||
| 3779 | (defun tramp-sh-file-gvfs-monitor-dir-process-filter (proc string) | 3786 | (defun tramp-sh-gvfs-monitor-dir-process-filter (proc string) |
| 3780 | "Read output from \"gvfs-monitor-dir\" and add corresponding \ | 3787 | "Read output from \"gvfs-monitor-dir\" and add corresponding \ |
| 3781 | file-notify events." | 3788 | file-notify events." |
| 3782 | (let ((remote-prefix | 3789 | (let ((remote-prefix |
| @@ -3790,6 +3797,8 @@ file-notify events." | |||
| 3790 | ;; Attribute change is returned in unused wording. | 3797 | ;; Attribute change is returned in unused wording. |
| 3791 | string (tramp-compat-replace-regexp-in-string | 3798 | string (tramp-compat-replace-regexp-in-string |
| 3792 | "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) | 3799 | "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) |
| 3800 | (when (string-match "Monitoring not supported" string) | ||
| 3801 | (delete-process proc)) | ||
| 3793 | 3802 | ||
| 3794 | (while (string-match | 3803 | (while (string-match |
| 3795 | (concat "^[\n\r]*" | 3804 | (concat "^[\n\r]*" |
| @@ -3798,18 +3807,24 @@ file-notify events." | |||
| 3798 | "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?" | 3807 | "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?" |
| 3799 | "Event = \\([^[:blank:]]+\\)[\n\r]+") | 3808 | "Event = \\([^[:blank:]]+\\)[\n\r]+") |
| 3800 | string) | 3809 | string) |
| 3801 | (let ((object | 3810 | (let* ((file (match-string 1 string)) |
| 3802 | (list | 3811 | (file1 (match-string 3 string)) |
| 3803 | proc | 3812 | (object |
| 3804 | (intern-soft | 3813 | (list |
| 3805 | (tramp-compat-replace-regexp-in-string | 3814 | proc |
| 3806 | "_" "-" (downcase (match-string 4 string)))) | 3815 | (intern-soft |
| 3807 | ;; File names are returned as absolute paths. We must | 3816 | (tramp-compat-replace-regexp-in-string |
| 3808 | ;; add the remote prefix. | 3817 | "_" "-" (downcase (match-string 4 string)))) |
| 3809 | (concat remote-prefix (match-string 1 string)) | 3818 | ;; File names are returned as absolute paths. We must |
| 3810 | (when (match-string 3 string) | 3819 | ;; add the remote prefix. |
| 3811 | (concat remote-prefix (match-string 3 string)))))) | 3820 | (concat remote-prefix file) |
| 3821 | (when file1 (concat remote-prefix file1))))) | ||
| 3812 | (setq string (replace-match "" nil nil string)) | 3822 | (setq string (replace-match "" nil nil string)) |
| 3823 | ;; Remove watch when file or directory to be watched is deleted. | ||
| 3824 | (when (and (member (cadr object) '(moved deleted)) | ||
| 3825 | (string-equal | ||
| 3826 | file (tramp-compat-process-get proc 'watch-name))) | ||
| 3827 | (delete-process proc)) | ||
| 3813 | ;; Usually, we would add an Emacs event now. Unfortunately, | 3828 | ;; Usually, we would add an Emacs event now. Unfortunately, |
| 3814 | ;; `unread-command-events' does not accept several events at | 3829 | ;; `unread-command-events' does not accept several events at |
| 3815 | ;; once. Therefore, we apply the callback directly. | 3830 | ;; once. Therefore, we apply the callback directly. |
| @@ -3821,7 +3836,7 @@ file-notify events." | |||
| 3821 | (when string (tramp-message proc 10 "Rest string:\n%s" string)) | 3836 | (when string (tramp-message proc 10 "Rest string:\n%s" string)) |
| 3822 | (tramp-compat-process-put proc 'rest-string string))) | 3837 | (tramp-compat-process-put proc 'rest-string string))) |
| 3823 | 3838 | ||
| 3824 | (defun tramp-sh-file-inotifywait-process-filter (proc string) | 3839 | (defun tramp-sh-inotifywait-process-filter (proc string) |
| 3825 | "Read output from \"inotifywait\" and add corresponding file-notify events." | 3840 | "Read output from \"inotifywait\" and add corresponding file-notify events." |
| 3826 | (tramp-message proc 6 "%S\n%s" proc string) | 3841 | (tramp-message proc 6 "%S\n%s" proc string) |
| 3827 | (dolist (line (split-string string "[\n\r]+" 'omit-nulls)) | 3842 | (dolist (line (split-string string "[\n\r]+" 'omit-nulls)) |
| @@ -3843,6 +3858,9 @@ file-notify events." | |||
| 3843 | (tramp-compat-replace-regexp-in-string "_" "-" (downcase x)))) | 3858 | (tramp-compat-replace-regexp-in-string "_" "-" (downcase x)))) |
| 3844 | (split-string (match-string 1 line) "," 'omit-nulls)) | 3859 | (split-string (match-string 1 line) "," 'omit-nulls)) |
| 3845 | (match-string 3 line)))) | 3860 | (match-string 3 line)))) |
| 3861 | ;; Remove watch when file or directory to be watched is deleted. | ||
| 3862 | (when (equal (cadr object) 'ignored) | ||
| 3863 | (delete-process proc)) | ||
| 3846 | ;; Usually, we would add an Emacs event now. Unfortunately, | 3864 | ;; Usually, we would add an Emacs event now. Unfortunately, |
| 3847 | ;; `unread-command-events' does not accept several events at | 3865 | ;; `unread-command-events' does not accept several events at |
| 3848 | ;; once. Therefore, we apply the callback directly. | 3866 | ;; once. Therefore, we apply the callback directly. |
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 9ec3226417c..fbb8c8a349e 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el | |||
| @@ -3407,7 +3407,7 @@ of." | |||
| 3407 | (defun tramp-handle-file-notify-add-watch (filename _flags _callback) | 3407 | (defun tramp-handle-file-notify-add-watch (filename _flags _callback) |
| 3408 | "Like `file-notify-add-watch' for Tramp files." | 3408 | "Like `file-notify-add-watch' for Tramp files." |
| 3409 | ;; This is the default handler. tramp-gvfs.el and tramp-sh.el have | 3409 | ;; This is the default handler. tramp-gvfs.el and tramp-sh.el have |
| 3410 | ;; its own one. | 3410 | ;; their own one. |
| 3411 | (setq filename (expand-file-name filename)) | 3411 | (setq filename (expand-file-name filename)) |
| 3412 | (with-parsed-tramp-file-name filename nil | 3412 | (with-parsed-tramp-file-name filename nil |
| 3413 | (tramp-error | 3413 | (tramp-error |
| @@ -3419,11 +3419,17 @@ of." | |||
| 3419 | (unless (processp proc) | 3419 | (unless (processp proc) |
| 3420 | (tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc)) | 3420 | (tramp-error proc 'file-notify-error "Not a valid descriptor %S" proc)) |
| 3421 | (tramp-message proc 6 "Kill %S" proc) | 3421 | (tramp-message proc 6 "Kill %S" proc) |
| 3422 | (kill-process proc)) | 3422 | (delete-process proc)) |
| 3423 | 3423 | ||
| 3424 | (defun tramp-handle-file-notify-valid-p (proc) | 3424 | (defun tramp-handle-file-notify-valid-p (proc) |
| 3425 | "Like `file-notify-valid-p' for Tramp files." | 3425 | "Like `file-notify-valid-p' for Tramp files." |
| 3426 | (and proc (processp proc) (memq (process-status proc) '(run open)))) | 3426 | (and proc (processp proc) (memq (process-status proc) '(run open)) |
| 3427 | ;; Sometimes, the process is still in status `run' when the | ||
| 3428 | ;; file or directory to be watched is deleted already. | ||
| 3429 | (with-current-buffer (process-buffer proc) | ||
| 3430 | (file-exists-p | ||
| 3431 | (concat (file-remote-p default-directory) | ||
| 3432 | (tramp-compat-process-get proc 'watch-name)))))) | ||
| 3427 | 3433 | ||
| 3428 | ;;; Functions for establishing connection: | 3434 | ;;; Functions for establishing connection: |
| 3429 | 3435 | ||
diff --git a/test/automated/file-notify-tests.el b/test/automated/file-notify-tests.el index dfc32443d17..9d66f03ae0c 100644 --- a/test/automated/file-notify-tests.el +++ b/test/automated/file-notify-tests.el | |||
| @@ -61,6 +61,8 @@ | |||
| 61 | (defvar file-notify--test-results nil) | 61 | (defvar file-notify--test-results nil) |
| 62 | (defvar file-notify--test-event nil) | 62 | (defvar file-notify--test-event nil) |
| 63 | (defvar file-notify--test-events nil) | 63 | (defvar file-notify--test-events nil) |
| 64 | (defun file-notify--test-timeout () | ||
| 65 | (if (file-remote-p temporary-file-directory) 6 3)) | ||
| 64 | 66 | ||
| 65 | (defun file-notify--test-cleanup () | 67 | (defun file-notify--test-cleanup () |
| 66 | "Cleanup after a test." | 68 | "Cleanup after a test." |
| @@ -69,13 +71,16 @@ | |||
| 69 | (when (and file-notify--test-tmpfile | 71 | (when (and file-notify--test-tmpfile |
| 70 | (file-exists-p file-notify--test-tmpfile)) | 72 | (file-exists-p file-notify--test-tmpfile)) |
| 71 | (if (directory-name-p file-notify--test-tmpfile) | 73 | (if (directory-name-p file-notify--test-tmpfile) |
| 72 | (delete-directory file-notify--test-tmpfile) | 74 | (delete-directory file-notify--test-tmpfile 'recursive) |
| 73 | (delete-file file-notify--test-tmpfile))) | 75 | (delete-file file-notify--test-tmpfile))) |
| 74 | (when (and file-notify--test-tmpfile1 | 76 | (when (and file-notify--test-tmpfile1 |
| 75 | (file-exists-p file-notify--test-tmpfile1)) | 77 | (file-exists-p file-notify--test-tmpfile1)) |
| 76 | (if (directory-name-p file-notify--test-tmpfile1) | 78 | (if (directory-name-p file-notify--test-tmpfile1) |
| 77 | (delete-directory file-notify--test-tmpfile1) | 79 | (delete-directory file-notify--test-tmpfile1 'recursive) |
| 78 | (delete-file file-notify--test-tmpfile1))) | 80 | (delete-file file-notify--test-tmpfile1))) |
| 81 | (when (file-remote-p temporary-file-directory) | ||
| 82 | (tramp-cleanup-connection | ||
| 83 | (tramp-dissect-file-name temporary-file-directory) nil 'keep-password)) | ||
| 79 | 84 | ||
| 80 | (setq file-notify--test-tmpfile nil) | 85 | (setq file-notify--test-tmpfile nil) |
| 81 | (setq file-notify--test-tmpfile1 nil) | 86 | (setq file-notify--test-tmpfile1 nil) |
| @@ -150,6 +155,8 @@ being the result.") | |||
| 150 | (should | 155 | (should |
| 151 | (setq file-notify--test-desc | 156 | (setq file-notify--test-desc |
| 152 | (file-notify-add-watch temporary-file-directory '(change) 'ignore))) | 157 | (file-notify-add-watch temporary-file-directory '(change) 'ignore))) |
| 158 | |||
| 159 | ;; Cleanup. | ||
| 153 | (file-notify--test-cleanup)) | 160 | (file-notify--test-cleanup)) |
| 154 | 161 | ||
| 155 | (file-notify--deftest-remote file-notify-test00-availability | 162 | (file-notify--deftest-remote file-notify-test00-availability |
| @@ -190,6 +197,7 @@ being the result.") | |||
| 190 | (file-notify-add-watch temporary-file-directory '(change) 3)) | 197 | (file-notify-add-watch temporary-file-directory '(change) 3)) |
| 191 | '(wrong-type-argument 3))) | 198 | '(wrong-type-argument 3))) |
| 192 | 199 | ||
| 200 | ;; Cleanup. | ||
| 193 | (file-notify--test-cleanup)) | 201 | (file-notify--test-cleanup)) |
| 194 | 202 | ||
| 195 | (file-notify--deftest-remote file-notify-test01-add-watch | 203 | (file-notify--deftest-remote file-notify-test01-add-watch |
| @@ -215,11 +223,11 @@ is bound somewhere." | |||
| 215 | 223 | ||
| 216 | (defun file-notify--test-event-handler (event) | 224 | (defun file-notify--test-event-handler (event) |
| 217 | "Run a test over FILE-NOTIFY--TEST-EVENT. | 225 | "Run a test over FILE-NOTIFY--TEST-EVENT. |
| 218 | For later analysis, append the test result to | 226 | For later analysis, append the test result to `file-notify--test-results' |
| 219 | `file-notify--test-results' and the event to | 227 | and the event to `file-notify--test-events'." |
| 220 | `file-notify--test-events'." | ||
| 221 | (let* ((file-notify--test-event event) | 228 | (let* ((file-notify--test-event event) |
| 222 | (result (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) | 229 | (result |
| 230 | (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) | ||
| 223 | (setq file-notify--test-events | 231 | (setq file-notify--test-events |
| 224 | (append file-notify--test-events `(,file-notify--test-event))) | 232 | (append file-notify--test-events `(,file-notify--test-event))) |
| 225 | (setq file-notify--test-results | 233 | (setq file-notify--test-results |
| @@ -243,7 +251,7 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 243 | (declare (indent 3)) | 251 | (declare (indent 3)) |
| 244 | (let ((outer (make-symbol "outer"))) | 252 | (let ((outer (make-symbol "outer"))) |
| 245 | `(let ((,outer file-notify--test-events)) | 253 | `(let ((,outer file-notify--test-events)) |
| 246 | (let ((file-notify--test-events nil)) | 254 | (let (file-notify--test-events) |
| 247 | ,@body | 255 | ,@body |
| 248 | (file-notify--wait-for-events | 256 | (file-notify--wait-for-events |
| 249 | ,timeout (= ,n (length file-notify--test-events))) | 257 | ,timeout (= ,n (length file-notify--test-events))) |
| @@ -256,9 +264,7 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 256 | (skip-unless (file-notify--test-local-enabled)) | 264 | (skip-unless (file-notify--test-local-enabled)) |
| 257 | (unwind-protect | 265 | (unwind-protect |
| 258 | (progn | 266 | (progn |
| 259 | (setq file-notify--test-results nil | 267 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) |
| 260 | file-notify--test-events nil | ||
| 261 | file-notify--test-tmpfile (file-notify--test-make-temp-name) | ||
| 262 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name) | 268 | file-notify--test-tmpfile1 (file-notify--test-make-temp-name) |
| 263 | file-notify--test-desc | 269 | file-notify--test-desc |
| 264 | (file-notify-add-watch | 270 | (file-notify-add-watch |
| @@ -268,41 +274,66 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 268 | 274 | ||
| 269 | ;; Check creation, change, and deletion. | 275 | ;; Check creation, change, and deletion. |
| 270 | (file-notify--test-with-events | 276 | (file-notify--test-with-events |
| 271 | 3 3 (lambda (events) | 277 | 3 (file-notify--test-timeout) |
| 272 | (should (equal '(created changed deleted) | 278 | (lambda (events) |
| 273 | (mapcar #'cadr events)))) | 279 | (should (equal '(created changed deleted) |
| 280 | (mapcar #'cadr events)))) | ||
| 274 | (write-region | 281 | (write-region |
| 275 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 282 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 276 | (delete-file file-notify--test-tmpfile)) | 283 | (delete-file file-notify--test-tmpfile)) |
| 277 | 284 | ||
| 278 | ;; Check copy. | 285 | ;; Check copy. |
| 279 | (file-notify--test-with-events | 286 | (file-notify--test-with-events |
| 280 | 3 3 (lambda (events) | 287 | 3 (file-notify--test-timeout) |
| 281 | (should (equal '(created changed deleted) | 288 | (lambda (events) |
| 282 | (mapcar #'cadr events)))) | 289 | (should (equal '(created changed deleted) |
| 290 | (mapcar #'cadr events)))) | ||
| 283 | (write-region | 291 | (write-region |
| 284 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 292 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 285 | (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) | 293 | (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) |
| 294 | ;; The next two events shall not be visible. | ||
| 295 | (set-file-modes file-notify--test-tmpfile 000) | ||
| 296 | (set-file-times file-notify--test-tmpfile '(0 0)) | ||
| 286 | (delete-file file-notify--test-tmpfile) | 297 | (delete-file file-notify--test-tmpfile) |
| 287 | (delete-file file-notify--test-tmpfile1)) | 298 | (delete-file file-notify--test-tmpfile1)) |
| 288 | 299 | ||
| 289 | ;; Check rename. | 300 | ;; Check rename. |
| 290 | (file-notify--test-with-events | 301 | (file-notify--test-with-events |
| 291 | 3 3 (lambda (events) | 302 | 3 (file-notify--test-timeout) |
| 292 | (should (equal '(created changed renamed) | 303 | (lambda (events) |
| 293 | (mapcar #'cadr events)))) | 304 | (should (equal '(created changed renamed) |
| 305 | (mapcar #'cadr events)))) | ||
| 294 | (write-region | 306 | (write-region |
| 295 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 307 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| 296 | (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) | 308 | (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) |
| 297 | ;; After the rename, we won't get events anymore. | 309 | ;; After the rename, we won't get events anymore. |
| 298 | (delete-file file-notify--test-tmpfile1)) | 310 | (delete-file file-notify--test-tmpfile1)) |
| 299 | 311 | ||
| 312 | ;; Check attribute change. | ||
| 313 | (file-notify-rm-watch file-notify--test-desc) | ||
| 314 | (setq file-notify--test-desc | ||
| 315 | (file-notify-add-watch | ||
| 316 | file-notify--test-tmpfile | ||
| 317 | '(attribute-change) 'file-notify--test-event-handler)) | ||
| 318 | (file-notify--test-with-events | ||
| 319 | 2 (file-notify--test-timeout) | ||
| 320 | (lambda (events) | ||
| 321 | (should (equal '(attribute-changed attribute-changed) | ||
| 322 | (mapcar #'cadr events)))) | ||
| 323 | (write-region | ||
| 324 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 325 | (set-file-modes file-notify--test-tmpfile 000) | ||
| 326 | (read-event nil nil 0.1) ; In order to distinguish the events. | ||
| 327 | (set-file-times file-notify--test-tmpfile '(0 0)) | ||
| 328 | (delete-file file-notify--test-tmpfile)) | ||
| 329 | |||
| 300 | ;; Check the global sequence again just to make sure that | 330 | ;; Check the global sequence again just to make sure that |
| 301 | ;; `file-notify--test-events' has been set correctly. | 331 | ;; `file-notify--test-events' has been set correctly. |
| 302 | (should (equal (mapcar #'cadr file-notify--test-events) | 332 | (should (equal (mapcar #'cadr file-notify--test-events) |
| 303 | '(created changed deleted | 333 | '(created changed deleted |
| 304 | created changed deleted | 334 | created changed deleted |
| 305 | created changed renamed))) | 335 | created changed renamed |
| 336 | attribute-changed attribute-changed))) | ||
| 306 | 337 | ||
| 307 | (should file-notify--test-results) | 338 | (should file-notify--test-results) |
| 308 | (dolist (result file-notify--test-results) | 339 | (dolist (result file-notify--test-results) |
| @@ -310,6 +341,8 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 310 | (when (ert-test-failed-p result) | 341 | (when (ert-test-failed-p result) |
| 311 | (ert-fail | 342 | (ert-fail |
| 312 | (cadr (ert-test-result-with-condition-condition result)))))) | 343 | (cadr (ert-test-result-with-condition-condition result)))))) |
| 344 | |||
| 345 | ;; Cleanup. | ||
| 313 | (file-notify--test-cleanup))) | 346 | (file-notify--test-cleanup))) |
| 314 | 347 | ||
| 315 | (file-notify--deftest-remote file-notify-test02-events | 348 | (file-notify--deftest-remote file-notify-test02-events |
| @@ -367,7 +400,7 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 367 | (buffer-string)))) | 400 | (buffer-string)))) |
| 368 | (should (string-match "another text" (buffer-string))))) | 401 | (should (string-match "another text" (buffer-string))))) |
| 369 | 402 | ||
| 370 | ;; Exit. | 403 | ;; Cleanup. |
| 371 | (ignore-errors (kill-buffer buf)) | 404 | (ignore-errors (kill-buffer buf)) |
| 372 | (file-notify--test-cleanup)))) | 405 | (file-notify--test-cleanup)))) |
| 373 | 406 | ||
| @@ -377,6 +410,31 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 377 | (ert-deftest file-notify-test04-file-validity () | 410 | (ert-deftest file-notify-test04-file-validity () |
| 378 | "Check `file-notify-valid-p' for files." | 411 | "Check `file-notify-valid-p' for files." |
| 379 | (skip-unless (file-notify--test-local-enabled)) | 412 | (skip-unless (file-notify--test-local-enabled)) |
| 413 | |||
| 414 | (unwind-protect | ||
| 415 | (progn | ||
| 416 | (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) | ||
| 417 | (setq file-notify--test-desc (file-notify-add-watch | ||
| 418 | file-notify--test-tmpfile | ||
| 419 | '(change) | ||
| 420 | #'file-notify--test-event-handler)) | ||
| 421 | (file-notify--test-with-events | ||
| 422 | 2 (file-notify--test-timeout) | ||
| 423 | (lambda (events) | ||
| 424 | (should (equal '(created changed) | ||
| 425 | (mapcar #'cadr events)))) | ||
| 426 | (should (file-notify-valid-p file-notify--test-desc)) | ||
| 427 | (write-region | ||
| 428 | "any text" nil file-notify--test-tmpfile nil 'no-message) | ||
| 429 | (should (file-notify-valid-p file-notify--test-desc))) | ||
| 430 | ;; After removing the watch, the descriptor must not be valid | ||
| 431 | ;; anymore. | ||
| 432 | (file-notify-rm-watch file-notify--test-desc) | ||
| 433 | (should-not (file-notify-valid-p file-notify--test-desc))) | ||
| 434 | |||
| 435 | ;; Cleanup. | ||
| 436 | (file-notify--test-cleanup)) | ||
| 437 | |||
| 380 | ;; The batch-mode operation of w32notify is fragile (there's no | 438 | ;; The batch-mode operation of w32notify is fragile (there's no |
| 381 | ;; input threads to send the message to). | 439 | ;; input threads to send the message to). |
| 382 | (skip-unless (not (and noninteractive (eq file-notify--library 'w32notify)))) | 440 | (skip-unless (not (and noninteractive (eq file-notify--library 'w32notify)))) |
| @@ -389,9 +447,10 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 389 | '(change) | 447 | '(change) |
| 390 | #'file-notify--test-event-handler)) | 448 | #'file-notify--test-event-handler)) |
| 391 | (file-notify--test-with-events | 449 | (file-notify--test-with-events |
| 392 | 2 3 (lambda (events) | 450 | 2 (file-notify--test-timeout) |
| 393 | (should (equal '(created changed) | 451 | (lambda (events) |
| 394 | (mapcar #'cadr events)))) | 452 | (should (equal '(created changed) |
| 453 | (mapcar #'cadr events)))) | ||
| 395 | (should (file-notify-valid-p file-notify--test-desc)) | 454 | (should (file-notify-valid-p file-notify--test-desc)) |
| 396 | (write-region | 455 | (write-region |
| 397 | "any text" nil file-notify--test-tmpfile nil 'no-message) | 456 | "any text" nil file-notify--test-tmpfile nil 'no-message) |
| @@ -399,10 +458,12 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 399 | ;; After deleting the parent, the descriptor must not be valid | 458 | ;; After deleting the parent, the descriptor must not be valid |
| 400 | ;; anymore. | 459 | ;; anymore. |
| 401 | (delete-directory temporary-file-directory t) | 460 | (delete-directory temporary-file-directory t) |
| 402 | (read-event nil nil 0.5) | 461 | (file-notify--wait-for-events |
| 462 | (file-notify--test-timeout) | ||
| 463 | (not (file-notify-valid-p file-notify--test-desc))) | ||
| 403 | (should-not (file-notify-valid-p file-notify--test-desc))) | 464 | (should-not (file-notify-valid-p file-notify--test-desc))) |
| 404 | 465 | ||
| 405 | ;; Exit. | 466 | ;; Cleanup. |
| 406 | (file-notify--test-cleanup))) | 467 | (file-notify--test-cleanup))) |
| 407 | 468 | ||
| 408 | (file-notify--deftest-remote file-notify-test04-file-validity | 469 | (file-notify--deftest-remote file-notify-test04-file-validity |
| @@ -411,6 +472,25 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 411 | (ert-deftest file-notify-test05-dir-validity () | 472 | (ert-deftest file-notify-test05-dir-validity () |
| 412 | "Check `file-notify-valid-p' for directories." | 473 | "Check `file-notify-valid-p' for directories." |
| 413 | (skip-unless (file-notify--test-local-enabled)) | 474 | (skip-unless (file-notify--test-local-enabled)) |
| 475 | |||
| 476 | (unwind-protect | ||
| 477 | (progn | ||
| 478 | (setq file-notify--test-tmpfile (file-name-as-directory | ||
| 479 | (file-notify--test-make-temp-name))) | ||
| 480 | (make-directory file-notify--test-tmpfile) | ||
| 481 | (setq file-notify--test-desc (file-notify-add-watch | ||
| 482 | file-notify--test-tmpfile | ||
| 483 | '(change) | ||
| 484 | #'file-notify--test-event-handler)) | ||
| 485 | (should (file-notify-valid-p file-notify--test-desc)) | ||
| 486 | ;; After removing the watch, the descriptor must not be valid | ||
| 487 | ;; anymore. | ||
| 488 | (file-notify-rm-watch file-notify--test-desc) | ||
| 489 | (should-not (file-notify-valid-p file-notify--test-desc))) | ||
| 490 | |||
| 491 | ;; Cleanup. | ||
| 492 | (file-notify--test-cleanup)) | ||
| 493 | |||
| 414 | ;; The batch-mode operation of w32notify is fragile (there's no | 494 | ;; The batch-mode operation of w32notify is fragile (there's no |
| 415 | ;; input threads to send the message to). | 495 | ;; input threads to send the message to). |
| 416 | (skip-unless (not (and noninteractive (eq file-notify--library 'w32notify)))) | 496 | (skip-unless (not (and noninteractive (eq file-notify--library 'w32notify)))) |
| @@ -424,13 +504,15 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." | |||
| 424 | '(change) | 504 | '(change) |
| 425 | #'file-notify--test-event-handler)) | 505 | #'file-notify--test-event-handler)) |
| 426 | (should (file-notify-valid-p file-notify--test-desc)) | 506 | (should (file-notify-valid-p file-notify--test-desc)) |
| 427 | (delete-directory file-notify--test-tmpfile t) | ||
| 428 | ;; After deleting the directory, the descriptor must not be | 507 | ;; After deleting the directory, the descriptor must not be |
| 429 | ;; valid anymore. | 508 | ;; valid anymore. |
| 430 | (read-event nil nil 0.5) | 509 | (delete-directory file-notify--test-tmpfile t) |
| 510 | (file-notify--wait-for-events | ||
| 511 | (file-notify--test-timeout) | ||
| 512 | (not (file-notify-valid-p file-notify--test-desc))) | ||
| 431 | (should-not (file-notify-valid-p file-notify--test-desc))) | 513 | (should-not (file-notify-valid-p file-notify--test-desc))) |
| 432 | 514 | ||
| 433 | ;; Exit. | 515 | ;; Cleanup. |
| 434 | (file-notify--test-cleanup))) | 516 | (file-notify--test-cleanup))) |
| 435 | 517 | ||
| 436 | (file-notify--deftest-remote file-notify-test05-dir-validity | 518 | (file-notify--deftest-remote file-notify-test05-dir-validity |