From 838023d469054cc19d0a2b7cf48e39082d8220f0 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 27 Oct 2015 16:02:26 +0100 Subject: [PATCH] Fall back to polling in autorevert when needed * lisp/autorevert.el (auto-revert-notify-handler): When a `stopped' event arrives from file notification, fall back to polling. * test/automated/file-notify-tests.el (file-notify-test03-autorevert): Extend test for polling when file notification ceases to work. --- lisp/autorevert.el | 79 ++++++++++++++++++++++--------------- test/automated/file-notify-tests.el | 29 +++++++++++++- 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 37ee8eedcfd..f0c12d2d97e 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -570,37 +570,54 @@ no more reverts are possible until the next call of ;; Since we watch a directory, a file name must be returned. (cl-assert (stringp file)) (when (eq action 'renamed) (cl-assert (stringp file1))) - ;; Loop over all buffers, in order to find the intended one. - (cl-dolist (buffer buffers) - (when (buffer-live-p buffer) - (with-current-buffer buffer - (when (or - ;; A buffer associated with a file. - (and (stringp buffer-file-name) - (or - (and (memq action '(attribute-changed changed created)) - (string-equal - (file-name-nondirectory file) - (file-name-nondirectory buffer-file-name))) - (and (eq action 'renamed) - (string-equal - (file-name-nondirectory file1) - (file-name-nondirectory buffer-file-name))))) - ;; A buffer w/o a file, like dired. - (and (null buffer-file-name) - (memq action '(created renamed deleted)))) - ;; Mark buffer modified. - (setq auto-revert-notify-modified-p t) - - ;; Revert the buffer now if we're not locked out. - (when (/= auto-revert-buffers-counter-lockedout - auto-revert-buffers-counter) - (auto-revert-handler) - (setq auto-revert-buffers-counter-lockedout - auto-revert-buffers-counter)) - - ;; No need to check other buffers. - (cl-return)))))))) + + (if (eq action 'stopped) + ;; File notification has stopped. Continue with polling. + (cl-dolist (buffer buffers) + (with-current-buffer buffer + (when (or + ;; A buffer associated with a file. + (and (stringp buffer-file-name) + (string-equal + (file-name-nondirectory file) + (file-name-nondirectory buffer-file-name))) + ;; A buffer w/o a file, like dired. + (null buffer-file-name)) + (auto-revert-notify-rm-watch) + (setq-local auto-revert-use-notify nil)))) + + ;; Loop over all buffers, in order to find the intended one. + (cl-dolist (buffer buffers) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (when (or + ;; A buffer associated with a file. + (and (stringp buffer-file-name) + (or + (and (memq + action '(attribute-changed changed created)) + (string-equal + (file-name-nondirectory file) + (file-name-nondirectory buffer-file-name))) + (and (eq action 'renamed) + (string-equal + (file-name-nondirectory file1) + (file-name-nondirectory buffer-file-name))))) + ;; A buffer w/o a file, like dired. + (and (null buffer-file-name) + (memq action '(created renamed deleted)))) + ;; Mark buffer modified. + (setq auto-revert-notify-modified-p t) + + ;; Revert the buffer now if we're not locked out. + (when (/= auto-revert-buffers-counter-lockedout + auto-revert-buffers-counter) + (auto-revert-handler) + (setq auto-revert-buffers-counter-lockedout + auto-revert-buffers-counter)) + + ;; No need to check other buffers. + (cl-return))))))))) (defun auto-revert-active-p () "Check if auto-revert is active (in current buffer or globally)." diff --git a/test/automated/file-notify-tests.el b/test/automated/file-notify-tests.el index 472c6927b87..f411c6b76b0 100644 --- a/test/automated/file-notify-tests.el +++ b/test/automated/file-notify-tests.el @@ -461,6 +461,8 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." ;; Modify file. We wait for a second, in order to ;; have another timestamp. + (with-current-buffer (get-buffer-create "*Messages*") + (narrow-to-region (point-max) (point-max))) (sleep-for 1) (write-region "another text" nil file-notify--test-tmpfile nil 'no-message) @@ -472,9 +474,34 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (string-match (format-message "Reverting buffer `%s'." (buffer-name buf)) (buffer-string)))) - (should (string-match "another text" (buffer-string))))) + (should (string-match "another text" (buffer-string))) + + ;; Stop file notification. Autorevert shall still work via polling. + (file-notify-rm-watch auto-revert-notify-watch-descriptor) + (file-notify--wait-for-events + timeout (null auto-revert-use-notify)) + (should-not auto-revert-use-notify) + (should-not auto-revert-notify-watch-descriptor) + + ;; Modify file. We wait for a second, in order to + ;; have another timestamp. + (with-current-buffer (get-buffer-create "*Messages*") + (narrow-to-region (point-max) (point-max))) + (sleep-for 2) + (write-region + "foo bla" nil file-notify--test-tmpfile nil 'no-message) + + ;; Check, that the buffer has been reverted. + (with-current-buffer (get-buffer-create "*Messages*") + (file-notify--wait-for-events + timeout + (string-match + (format-message "Reverting buffer `%s'." (buffer-name buf)) + (buffer-string)))) + (should (string-match "foo bla" (buffer-string))))) ;; Cleanup. + (with-current-buffer "*Messages*" (widen)) (ignore-errors (kill-buffer buf)) (file-notify--test-cleanup)))) -- 2.11.4.GIT