autorevert: Resume with polling if file is deleted
* lisp/autorevert.el: Use consistent wording in comments and docstrings. (auto-revert-mode): Add local function to `kill-buffer-hook'. (auto-revert-notify-handler): Improve handling of `stopped' event. * test/lisp/autorevert-tests.el (auto-revert-test02-auto-revert-deleted-file): New test. (auto-revert-test03-auto-revert-tail-mode) (auto-revert-test04-auto-revert-mode-dired): Rename them.
This commit is contained in:
parent
c456627ffa
commit
ed54b3ff97
2 changed files with 121 additions and 37 deletions
|
@ -51,6 +51,12 @@
|
|||
;; Emacs. You should never even notice that this package is active
|
||||
;; (except that your buffers will be reverted, of course).
|
||||
;;
|
||||
;; If the file exists, Auto-Revert Mode updates the buffer based on
|
||||
;; its (possibly empty) contents. If the file no longer exists, then
|
||||
;; there is nothing to revert, so it does not modify the buffer. Once
|
||||
;; a deleted file corresponding to a buffer in Auto-Revert Mode
|
||||
;; reappears, Auto-Revert Mode continues to work.
|
||||
;;
|
||||
;; If Emacs is compiled with file notification support, notifications
|
||||
;; are used instead of checking the time stamp of the files. You can
|
||||
;; disable this by setting the user option `auto-revert-use-notify' to
|
||||
|
@ -58,19 +64,19 @@
|
|||
;; excluded from file notifications can be specified by
|
||||
;; `auto-revert-notify-exclude-dir-regexp'.
|
||||
;;
|
||||
;; After reverting a file buffer, Auto Revert Mode normally puts point
|
||||
;; After reverting a file buffer, Auto-Revert Mode normally puts point
|
||||
;; at the same position that a regular manual revert would. However,
|
||||
;; there is one exception to this rule. If point is at the end of the
|
||||
;; buffer before reverting, it stays at the end. Similarly if point
|
||||
;; is displayed at the end of a file buffer in any window, it will stay
|
||||
;; at the end of the buffer in that window, even if the window is not
|
||||
;; selected. This way, you can use Auto Revert Mode to `tail' a file.
|
||||
;; selected. This way, you can use Auto-Revert Mode to `tail' a file.
|
||||
;; Just put point at the end of the buffer and it will stay there.
|
||||
;; These rules apply to file buffers. For non-file buffers, the
|
||||
;; behavior may be mode dependent.
|
||||
;;
|
||||
;; While you can use Auto Revert Mode to tail a file, this package
|
||||
;; contains a third minor mode, Auto Revert Tail Mode, which does so
|
||||
;; While you can use Auto-Revert Mode to tail a file, this package
|
||||
;; contains a third minor mode, Auto-Revert Tail Mode, which does so
|
||||
;; more efficiently, as long as you are sure that the file will only
|
||||
;; change by growing at the end. It only appends the new output,
|
||||
;; instead of reverting the entire buffer. It does so even if the
|
||||
|
@ -112,8 +118,8 @@
|
|||
|
||||
(defgroup auto-revert nil
|
||||
"Revert individual buffers when files on disk change.
|
||||
Auto-Revert mode enables auto-revert in individual buffers.
|
||||
Global Auto-Revert mode does so in all buffers."
|
||||
Auto-Revert Mode enables auto-revert in individual buffers.
|
||||
Global Auto-Revert Mode does so in all buffers."
|
||||
:group 'files
|
||||
:group 'convenience)
|
||||
|
||||
|
@ -144,7 +150,7 @@ If a timer is already active, there are two ways to make sure
|
|||
that the new value will take effect immediately. You can set
|
||||
this variable through Custom or you can call the command
|
||||
`auto-revert-set-timer' after setting the variable. Otherwise,
|
||||
the new value will take effect the first time Auto Revert Mode
|
||||
the new value will take effect the first time Auto-Revert Mode
|
||||
calls `auto-revert-set-timer' for internal reasons or in your
|
||||
next editing session."
|
||||
:group 'auto-revert
|
||||
|
@ -176,7 +182,7 @@ When non-nil, a message is generated whenever a file is reverted."
|
|||
"String to display in the mode line when Auto-Revert Mode is active.
|
||||
|
||||
\(When the string is not empty, make sure that it has a leading space.)"
|
||||
:tag "Auto Revert Mode Text" ; To separate it from `global-...'
|
||||
:tag "Auto-Revert Mode Text" ; To separate it from `global-...'
|
||||
:group 'auto-revert
|
||||
:type 'string)
|
||||
|
||||
|
@ -190,7 +196,7 @@ When non-nil, a message is generated whenever a file is reverted."
|
|||
|
||||
(defcustom auto-revert-mode-hook nil
|
||||
"Functions to run when Auto-Revert Mode is activated."
|
||||
:tag "Auto Revert Mode Hook" ; To separate it from `global-...'
|
||||
:tag "Auto-Revert Mode Hook" ; To separate it from `global-...'
|
||||
:group 'auto-revert
|
||||
:type 'hook)
|
||||
|
||||
|
@ -209,11 +215,11 @@ would only waste precious space."
|
|||
:type 'hook)
|
||||
|
||||
(defcustom global-auto-revert-non-file-buffers nil
|
||||
"When nil, Global Auto-Revert mode operates only on file-visiting buffers.
|
||||
"When nil, Global Auto-Revert Mode operates only on file-visiting buffers.
|
||||
|
||||
When non-nil, both file buffers and buffers with a custom
|
||||
`revert-buffer-function' and a `buffer-stale-function' are
|
||||
reverted by Global Auto-Revert mode. These include the Buffer
|
||||
reverted by Global Auto-Revert Mode. These include the Buffer
|
||||
List buffer displayed by `buffer-menu', and Dired buffers showing
|
||||
complete local directories. The Buffer List buffer reverts every
|
||||
`auto-revert-interval' seconds; Dired buffers when the file list of
|
||||
|
@ -240,8 +246,8 @@ For more information, see Info node `(emacs)Autorevert'."
|
|||
:type 'hook)
|
||||
|
||||
(defcustom auto-revert-check-vc-info nil
|
||||
"If non-nil Auto Revert Mode reliably updates version control info.
|
||||
Auto Revert Mode updates version control info whenever the buffer
|
||||
"If non-nil Auto-Revert Mode reliably updates version control info.
|
||||
Auto-Revert Mode updates version control info whenever the buffer
|
||||
needs reverting, regardless of the value of this variable.
|
||||
However, the version control state can change without changes to
|
||||
the work file. If the change is made from the current Emacs
|
||||
|
@ -271,7 +277,7 @@ This variable becomes buffer local when set in any fashion.")
|
|||
:version "24.4")
|
||||
|
||||
(defcustom auto-revert-use-notify t
|
||||
"If non-nil Auto Revert Mode uses file notification functions.
|
||||
"If non-nil Auto-Revert Mode uses file notification functions.
|
||||
You should set this variable through Custom."
|
||||
:group 'auto-revert
|
||||
:type 'boolean
|
||||
|
@ -337,12 +343,12 @@ This has been reported by a file notification event.")
|
|||
|
||||
;;;###autoload
|
||||
(define-minor-mode auto-revert-mode
|
||||
"Toggle reverting buffer when the file changes (Auto Revert mode).
|
||||
With a prefix argument ARG, enable Auto Revert mode if ARG is
|
||||
"Toggle reverting buffer when the file changes (Auto-Revert Mode).
|
||||
With a prefix argument ARG, enable Auto-Revert Mode if ARG is
|
||||
positive, and disable it otherwise. If called from Lisp, enable
|
||||
the mode if ARG is omitted or nil.
|
||||
|
||||
Auto Revert mode is a minor mode that affects only the current
|
||||
Auto-Revert Mode is a minor mode that affects only the current
|
||||
buffer. When enabled, it reverts the buffer when the file on
|
||||
disk changes.
|
||||
|
||||
|
@ -351,8 +357,14 @@ Use `auto-revert-tail-mode' if you know that the file will only grow
|
|||
without being changed in the part that is already in the buffer."
|
||||
:group 'auto-revert :lighter auto-revert-mode-text
|
||||
(if auto-revert-mode
|
||||
(if (not (memq (current-buffer) auto-revert-buffer-list))
|
||||
(push (current-buffer) auto-revert-buffer-list))
|
||||
(when (not (memq (current-buffer) auto-revert-buffer-list))
|
||||
(push (current-buffer) auto-revert-buffer-list)
|
||||
(add-hook
|
||||
'kill-buffer-hook
|
||||
(lambda ()
|
||||
(setq auto-revert-buffer-list
|
||||
(delq (current-buffer) auto-revert-buffer-list)))
|
||||
nil t))
|
||||
(when auto-revert-use-notify (auto-revert-notify-rm-watch))
|
||||
(setq auto-revert-buffer-list
|
||||
(delq (current-buffer) auto-revert-buffer-list)))
|
||||
|
@ -374,11 +386,11 @@ This function is designed to be added to hooks, for example:
|
|||
;;;###autoload
|
||||
(define-minor-mode auto-revert-tail-mode
|
||||
"Toggle reverting tail of buffer when the file grows.
|
||||
With a prefix argument ARG, enable Auto-Revert Tail mode if ARG
|
||||
With a prefix argument ARG, enable Auto-Revert Tail Mode if ARG
|
||||
is positive, and disable it otherwise. If called from Lisp,
|
||||
enable the mode if ARG is omitted or nil.
|
||||
|
||||
When Auto Revert Tail mode is enabled, the tail of the file is
|
||||
When Auto-Revert Tail Mode is enabled, the tail of the file is
|
||||
constantly followed, as with the shell command `tail -f'. This
|
||||
means that whenever the file grows on disk (presumably because
|
||||
some background process is appending to it from time to time),
|
||||
|
@ -428,7 +440,7 @@ Perform a full revert? ")
|
|||
|
||||
;;;###autoload
|
||||
(defun turn-on-auto-revert-tail-mode ()
|
||||
"Turn on Auto-Revert Tail mode.
|
||||
"Turn on Auto-Revert Tail Mode.
|
||||
|
||||
This function is designed to be added to hooks, for example:
|
||||
(add-hook \\='my-logfile-mode-hook #\\='turn-on-auto-revert-tail-mode)"
|
||||
|
@ -437,12 +449,12 @@ This function is designed to be added to hooks, for example:
|
|||
|
||||
;;;###autoload
|
||||
(define-minor-mode global-auto-revert-mode
|
||||
"Toggle Global Auto Revert mode.
|
||||
With a prefix argument ARG, enable Global Auto Revert mode if ARG
|
||||
"Toggle Global Auto-Revert Mode.
|
||||
With a prefix argument ARG, enable Global Auto-Revert Mode if ARG
|
||||
is positive, and disable it otherwise. If called from Lisp,
|
||||
enable the mode if ARG is omitted or nil.
|
||||
|
||||
Global Auto Revert mode is a global minor mode that reverts any
|
||||
Global Auto-Revert Mode is a global minor mode that reverts any
|
||||
buffer associated with a file when the file changes on disk. Use
|
||||
`auto-revert-mode' to revert a particular buffer.
|
||||
|
||||
|
@ -573,16 +585,19 @@ no more reverts are possible until the next call of
|
|||
|
||||
(if (eq action 'stopped)
|
||||
;; File notification has stopped. Continue with polling.
|
||||
(cl-dolist (buffer buffers)
|
||||
(cl-dolist (buffer
|
||||
(if global-auto-revert-mode
|
||||
(buffer-list) auto-revert-buffer-list))
|
||||
(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))
|
||||
(when (and (equal descriptor auto-revert-notify-watch-descriptor)
|
||||
(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))))
|
||||
|
||||
|
@ -736,7 +751,7 @@ To avoid starvation, the buffers in `auto-revert-remaining-buffers'
|
|||
are checked first the next time this function is called.
|
||||
|
||||
This function is also responsible for removing buffers no longer in
|
||||
Auto-Revert mode from `auto-revert-buffer-list', and for canceling
|
||||
Auto-Revert Mode from `auto-revert-buffer-list', and for canceling
|
||||
the timer when no buffers need to be checked."
|
||||
|
||||
(setq auto-revert-buffers-counter
|
||||
|
|
|
@ -156,7 +156,76 @@
|
|||
(ignore-errors (delete-directory tmpdir1 'recursive))
|
||||
(ignore-errors (delete-directory tmpdir2 'recursive)))))
|
||||
|
||||
(ert-deftest auto-revert-test02-auto-revert-tail-mode ()
|
||||
;; This is inspired by Bug#23276.
|
||||
(ert-deftest auto-revert-test02-auto-revert-deleted-file ()
|
||||
"Check autorevert for a deleted file."
|
||||
:tags '(:expensive-test)
|
||||
|
||||
(let ((tmpfile (make-temp-file "auto-revert-test"))
|
||||
buf)
|
||||
(unwind-protect
|
||||
(progn
|
||||
(with-current-buffer (get-buffer-create "*Messages*")
|
||||
(narrow-to-region (point-max) (point-max)))
|
||||
(write-region "any text" nil tmpfile nil 'no-message)
|
||||
(setq buf (find-file-noselect tmpfile))
|
||||
(with-current-buffer buf
|
||||
(should (string-equal (buffer-string) "any text"))
|
||||
;; `buffer-stale--default-function' checks for
|
||||
;; `verify-visited-file-modtime'. We must ensure that
|
||||
;; it returns nil.
|
||||
(sleep-for 1)
|
||||
(auto-revert-mode 1)
|
||||
(should auto-revert-mode)
|
||||
|
||||
;; Remove file while reverting. We simulate this by
|
||||
;; modifying `before-revert-hook'.
|
||||
(add-hook
|
||||
'before-revert-hook
|
||||
(lambda () (delete-file buffer-file-name))
|
||||
nil t)
|
||||
(with-current-buffer (get-buffer-create "*Messages*")
|
||||
(narrow-to-region (point-max) (point-max)))
|
||||
(sleep-for 1)
|
||||
(write-region "another text" nil tmpfile nil 'no-message)
|
||||
|
||||
;; Check, that the buffer hasn't been reverted. File
|
||||
;; notification should be disabled, falling back to
|
||||
;; polling.
|
||||
(auto-revert--wait-for-revert buf)
|
||||
(should (string-match "any text" (buffer-string)))
|
||||
(should-not auto-revert-use-notify)
|
||||
|
||||
;; Once the file has been recreated, the buffer shall be
|
||||
;; reverted.
|
||||
(kill-local-variable 'before-revert-hook)
|
||||
(with-current-buffer (get-buffer-create "*Messages*")
|
||||
(narrow-to-region (point-max) (point-max)))
|
||||
(sleep-for 1)
|
||||
(write-region "another text" nil tmpfile nil 'no-message)
|
||||
|
||||
;; Check, that the buffer has been reverted.
|
||||
(auto-revert--wait-for-revert buf)
|
||||
(should (string-match "another text" (buffer-string)))
|
||||
|
||||
;; An empty file shall still be reverted.
|
||||
(with-current-buffer (get-buffer-create "*Messages*")
|
||||
(narrow-to-region (point-max) (point-max)))
|
||||
(sleep-for 1)
|
||||
(write-region "" nil tmpfile nil 'no-message)
|
||||
|
||||
;; Check, that the buffer has been reverted.
|
||||
(auto-revert--wait-for-revert buf)
|
||||
(should (string-equal "" (buffer-string)))))
|
||||
|
||||
;; Exit.
|
||||
(with-current-buffer "*Messages*" (widen))
|
||||
(ignore-errors
|
||||
(with-current-buffer buf (set-buffer-modified-p nil))
|
||||
(kill-buffer buf))
|
||||
(ignore-errors (delete-file tmpfile)))))
|
||||
|
||||
(ert-deftest auto-revert-test03-auto-revert-tail-mode ()
|
||||
"Check autorevert tail mode."
|
||||
;; `auto-revert-buffers' runs every 5". And we must wait, until the
|
||||
;; file has been reverted.
|
||||
|
@ -194,7 +263,7 @@
|
|||
(ignore-errors (kill-buffer buf))
|
||||
(ignore-errors (delete-file tmpfile)))))
|
||||
|
||||
(ert-deftest auto-revert-test03-auto-revert-mode-dired ()
|
||||
(ert-deftest auto-revert-test04-auto-revert-mode-dired ()
|
||||
"Check autorevert for dired."
|
||||
;; `auto-revert-buffers' runs every 5". And we must wait, until the
|
||||
;; file has been reverted.
|
||||
|
|
Loading…
Add table
Reference in a new issue