;; 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
;; 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
(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)
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
"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)
(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)
: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
: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
: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
;;;###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.
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)))
;;;###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),
;;;###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)"
;;;###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.
(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))))
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
(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.
(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.