diff options
| -rw-r--r-- | lisp/autorevert.el | 85 | ||||
| -rw-r--r-- | test/lisp/autorevert-tests.el | 73 |
2 files changed, 121 insertions, 37 deletions
diff --git a/lisp/autorevert.el b/lisp/autorevert.el index bc9d58e1a00..1129af8a2fa 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el | |||
| @@ -51,6 +51,12 @@ | |||
| 51 | ;; Emacs. You should never even notice that this package is active | 51 | ;; Emacs. You should never even notice that this package is active |
| 52 | ;; (except that your buffers will be reverted, of course). | 52 | ;; (except that your buffers will be reverted, of course). |
| 53 | ;; | 53 | ;; |
| 54 | ;; If the file exists, Auto-Revert Mode updates the buffer based on | ||
| 55 | ;; its (possibly empty) contents. If the file no longer exists, then | ||
| 56 | ;; there is nothing to revert, so it does not modify the buffer. Once | ||
| 57 | ;; a deleted file corresponding to a buffer in Auto-Revert Mode | ||
| 58 | ;; reappears, Auto-Revert Mode continues to work. | ||
| 59 | ;; | ||
| 54 | ;; If Emacs is compiled with file notification support, notifications | 60 | ;; If Emacs is compiled with file notification support, notifications |
| 55 | ;; are used instead of checking the time stamp of the files. You can | 61 | ;; are used instead of checking the time stamp of the files. You can |
| 56 | ;; disable this by setting the user option `auto-revert-use-notify' to | 62 | ;; disable this by setting the user option `auto-revert-use-notify' to |
| @@ -58,19 +64,19 @@ | |||
| 58 | ;; excluded from file notifications can be specified by | 64 | ;; excluded from file notifications can be specified by |
| 59 | ;; `auto-revert-notify-exclude-dir-regexp'. | 65 | ;; `auto-revert-notify-exclude-dir-regexp'. |
| 60 | ;; | 66 | ;; |
| 61 | ;; After reverting a file buffer, Auto Revert Mode normally puts point | 67 | ;; After reverting a file buffer, Auto-Revert Mode normally puts point |
| 62 | ;; at the same position that a regular manual revert would. However, | 68 | ;; at the same position that a regular manual revert would. However, |
| 63 | ;; there is one exception to this rule. If point is at the end of the | 69 | ;; there is one exception to this rule. If point is at the end of the |
| 64 | ;; buffer before reverting, it stays at the end. Similarly if point | 70 | ;; buffer before reverting, it stays at the end. Similarly if point |
| 65 | ;; is displayed at the end of a file buffer in any window, it will stay | 71 | ;; is displayed at the end of a file buffer in any window, it will stay |
| 66 | ;; at the end of the buffer in that window, even if the window is not | 72 | ;; at the end of the buffer in that window, even if the window is not |
| 67 | ;; selected. This way, you can use Auto Revert Mode to `tail' a file. | 73 | ;; selected. This way, you can use Auto-Revert Mode to `tail' a file. |
| 68 | ;; Just put point at the end of the buffer and it will stay there. | 74 | ;; Just put point at the end of the buffer and it will stay there. |
| 69 | ;; These rules apply to file buffers. For non-file buffers, the | 75 | ;; These rules apply to file buffers. For non-file buffers, the |
| 70 | ;; behavior may be mode dependent. | 76 | ;; behavior may be mode dependent. |
| 71 | ;; | 77 | ;; |
| 72 | ;; While you can use Auto Revert Mode to tail a file, this package | 78 | ;; While you can use Auto-Revert Mode to tail a file, this package |
| 73 | ;; contains a third minor mode, Auto Revert Tail Mode, which does so | 79 | ;; contains a third minor mode, Auto-Revert Tail Mode, which does so |
| 74 | ;; more efficiently, as long as you are sure that the file will only | 80 | ;; more efficiently, as long as you are sure that the file will only |
| 75 | ;; change by growing at the end. It only appends the new output, | 81 | ;; change by growing at the end. It only appends the new output, |
| 76 | ;; instead of reverting the entire buffer. It does so even if the | 82 | ;; instead of reverting the entire buffer. It does so even if the |
| @@ -112,8 +118,8 @@ | |||
| 112 | 118 | ||
| 113 | (defgroup auto-revert nil | 119 | (defgroup auto-revert nil |
| 114 | "Revert individual buffers when files on disk change. | 120 | "Revert individual buffers when files on disk change. |
| 115 | Auto-Revert mode enables auto-revert in individual buffers. | 121 | Auto-Revert Mode enables auto-revert in individual buffers. |
| 116 | Global Auto-Revert mode does so in all buffers." | 122 | Global Auto-Revert Mode does so in all buffers." |
| 117 | :group 'files | 123 | :group 'files |
| 118 | :group 'convenience) | 124 | :group 'convenience) |
| 119 | 125 | ||
| @@ -144,7 +150,7 @@ If a timer is already active, there are two ways to make sure | |||
| 144 | that the new value will take effect immediately. You can set | 150 | that the new value will take effect immediately. You can set |
| 145 | this variable through Custom or you can call the command | 151 | this variable through Custom or you can call the command |
| 146 | `auto-revert-set-timer' after setting the variable. Otherwise, | 152 | `auto-revert-set-timer' after setting the variable. Otherwise, |
| 147 | the new value will take effect the first time Auto Revert Mode | 153 | the new value will take effect the first time Auto-Revert Mode |
| 148 | calls `auto-revert-set-timer' for internal reasons or in your | 154 | calls `auto-revert-set-timer' for internal reasons or in your |
| 149 | next editing session." | 155 | next editing session." |
| 150 | :group 'auto-revert | 156 | :group 'auto-revert |
| @@ -176,7 +182,7 @@ When non-nil, a message is generated whenever a file is reverted." | |||
| 176 | "String to display in the mode line when Auto-Revert Mode is active. | 182 | "String to display in the mode line when Auto-Revert Mode is active. |
| 177 | 183 | ||
| 178 | \(When the string is not empty, make sure that it has a leading space.)" | 184 | \(When the string is not empty, make sure that it has a leading space.)" |
| 179 | :tag "Auto Revert Mode Text" ; To separate it from `global-...' | 185 | :tag "Auto-Revert Mode Text" ; To separate it from `global-...' |
| 180 | :group 'auto-revert | 186 | :group 'auto-revert |
| 181 | :type 'string) | 187 | :type 'string) |
| 182 | 188 | ||
| @@ -190,7 +196,7 @@ When non-nil, a message is generated whenever a file is reverted." | |||
| 190 | 196 | ||
| 191 | (defcustom auto-revert-mode-hook nil | 197 | (defcustom auto-revert-mode-hook nil |
| 192 | "Functions to run when Auto-Revert Mode is activated." | 198 | "Functions to run when Auto-Revert Mode is activated." |
| 193 | :tag "Auto Revert Mode Hook" ; To separate it from `global-...' | 199 | :tag "Auto-Revert Mode Hook" ; To separate it from `global-...' |
| 194 | :group 'auto-revert | 200 | :group 'auto-revert |
| 195 | :type 'hook) | 201 | :type 'hook) |
| 196 | 202 | ||
| @@ -209,11 +215,11 @@ would only waste precious space." | |||
| 209 | :type 'hook) | 215 | :type 'hook) |
| 210 | 216 | ||
| 211 | (defcustom global-auto-revert-non-file-buffers nil | 217 | (defcustom global-auto-revert-non-file-buffers nil |
| 212 | "When nil, Global Auto-Revert mode operates only on file-visiting buffers. | 218 | "When nil, Global Auto-Revert Mode operates only on file-visiting buffers. |
| 213 | 219 | ||
| 214 | When non-nil, both file buffers and buffers with a custom | 220 | When non-nil, both file buffers and buffers with a custom |
| 215 | `revert-buffer-function' and a `buffer-stale-function' are | 221 | `revert-buffer-function' and a `buffer-stale-function' are |
| 216 | reverted by Global Auto-Revert mode. These include the Buffer | 222 | reverted by Global Auto-Revert Mode. These include the Buffer |
| 217 | List buffer displayed by `buffer-menu', and Dired buffers showing | 223 | List buffer displayed by `buffer-menu', and Dired buffers showing |
| 218 | complete local directories. The Buffer List buffer reverts every | 224 | complete local directories. The Buffer List buffer reverts every |
| 219 | `auto-revert-interval' seconds; Dired buffers when the file list of | 225 | `auto-revert-interval' seconds; Dired buffers when the file list of |
| @@ -240,8 +246,8 @@ For more information, see Info node `(emacs)Autorevert'." | |||
| 240 | :type 'hook) | 246 | :type 'hook) |
| 241 | 247 | ||
| 242 | (defcustom auto-revert-check-vc-info nil | 248 | (defcustom auto-revert-check-vc-info nil |
| 243 | "If non-nil Auto Revert Mode reliably updates version control info. | 249 | "If non-nil Auto-Revert Mode reliably updates version control info. |
| 244 | Auto Revert Mode updates version control info whenever the buffer | 250 | Auto-Revert Mode updates version control info whenever the buffer |
| 245 | needs reverting, regardless of the value of this variable. | 251 | needs reverting, regardless of the value of this variable. |
| 246 | However, the version control state can change without changes to | 252 | However, the version control state can change without changes to |
| 247 | the work file. If the change is made from the current Emacs | 253 | 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.") | |||
| 271 | :version "24.4") | 277 | :version "24.4") |
| 272 | 278 | ||
| 273 | (defcustom auto-revert-use-notify t | 279 | (defcustom auto-revert-use-notify t |
| 274 | "If non-nil Auto Revert Mode uses file notification functions. | 280 | "If non-nil Auto-Revert Mode uses file notification functions. |
| 275 | You should set this variable through Custom." | 281 | You should set this variable through Custom." |
| 276 | :group 'auto-revert | 282 | :group 'auto-revert |
| 277 | :type 'boolean | 283 | :type 'boolean |
| @@ -337,12 +343,12 @@ This has been reported by a file notification event.") | |||
| 337 | 343 | ||
| 338 | ;;;###autoload | 344 | ;;;###autoload |
| 339 | (define-minor-mode auto-revert-mode | 345 | (define-minor-mode auto-revert-mode |
| 340 | "Toggle reverting buffer when the file changes (Auto Revert mode). | 346 | "Toggle reverting buffer when the file changes (Auto-Revert Mode). |
| 341 | With a prefix argument ARG, enable Auto Revert mode if ARG is | 347 | With a prefix argument ARG, enable Auto-Revert Mode if ARG is |
| 342 | positive, and disable it otherwise. If called from Lisp, enable | 348 | positive, and disable it otherwise. If called from Lisp, enable |
| 343 | the mode if ARG is omitted or nil. | 349 | the mode if ARG is omitted or nil. |
| 344 | 350 | ||
| 345 | Auto Revert mode is a minor mode that affects only the current | 351 | Auto-Revert Mode is a minor mode that affects only the current |
| 346 | buffer. When enabled, it reverts the buffer when the file on | 352 | buffer. When enabled, it reverts the buffer when the file on |
| 347 | disk changes. | 353 | disk changes. |
| 348 | 354 | ||
| @@ -351,8 +357,14 @@ Use `auto-revert-tail-mode' if you know that the file will only grow | |||
| 351 | without being changed in the part that is already in the buffer." | 357 | without being changed in the part that is already in the buffer." |
| 352 | :group 'auto-revert :lighter auto-revert-mode-text | 358 | :group 'auto-revert :lighter auto-revert-mode-text |
| 353 | (if auto-revert-mode | 359 | (if auto-revert-mode |
| 354 | (if (not (memq (current-buffer) auto-revert-buffer-list)) | 360 | (when (not (memq (current-buffer) auto-revert-buffer-list)) |
| 355 | (push (current-buffer) auto-revert-buffer-list)) | 361 | (push (current-buffer) auto-revert-buffer-list) |
| 362 | (add-hook | ||
| 363 | 'kill-buffer-hook | ||
| 364 | (lambda () | ||
| 365 | (setq auto-revert-buffer-list | ||
| 366 | (delq (current-buffer) auto-revert-buffer-list))) | ||
| 367 | nil t)) | ||
| 356 | (when auto-revert-use-notify (auto-revert-notify-rm-watch)) | 368 | (when auto-revert-use-notify (auto-revert-notify-rm-watch)) |
| 357 | (setq auto-revert-buffer-list | 369 | (setq auto-revert-buffer-list |
| 358 | (delq (current-buffer) auto-revert-buffer-list))) | 370 | (delq (current-buffer) auto-revert-buffer-list))) |
| @@ -374,11 +386,11 @@ This function is designed to be added to hooks, for example: | |||
| 374 | ;;;###autoload | 386 | ;;;###autoload |
| 375 | (define-minor-mode auto-revert-tail-mode | 387 | (define-minor-mode auto-revert-tail-mode |
| 376 | "Toggle reverting tail of buffer when the file grows. | 388 | "Toggle reverting tail of buffer when the file grows. |
| 377 | With a prefix argument ARG, enable Auto-Revert Tail mode if ARG | 389 | With a prefix argument ARG, enable Auto-Revert Tail Mode if ARG |
| 378 | is positive, and disable it otherwise. If called from Lisp, | 390 | is positive, and disable it otherwise. If called from Lisp, |
| 379 | enable the mode if ARG is omitted or nil. | 391 | enable the mode if ARG is omitted or nil. |
| 380 | 392 | ||
| 381 | When Auto Revert Tail mode is enabled, the tail of the file is | 393 | When Auto-Revert Tail Mode is enabled, the tail of the file is |
| 382 | constantly followed, as with the shell command `tail -f'. This | 394 | constantly followed, as with the shell command `tail -f'. This |
| 383 | means that whenever the file grows on disk (presumably because | 395 | means that whenever the file grows on disk (presumably because |
| 384 | some background process is appending to it from time to time), | 396 | some background process is appending to it from time to time), |
| @@ -428,7 +440,7 @@ Perform a full revert? ") | |||
| 428 | 440 | ||
| 429 | ;;;###autoload | 441 | ;;;###autoload |
| 430 | (defun turn-on-auto-revert-tail-mode () | 442 | (defun turn-on-auto-revert-tail-mode () |
| 431 | "Turn on Auto-Revert Tail mode. | 443 | "Turn on Auto-Revert Tail Mode. |
| 432 | 444 | ||
| 433 | This function is designed to be added to hooks, for example: | 445 | This function is designed to be added to hooks, for example: |
| 434 | (add-hook \\='my-logfile-mode-hook #\\='turn-on-auto-revert-tail-mode)" | 446 | (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: | |||
| 437 | 449 | ||
| 438 | ;;;###autoload | 450 | ;;;###autoload |
| 439 | (define-minor-mode global-auto-revert-mode | 451 | (define-minor-mode global-auto-revert-mode |
| 440 | "Toggle Global Auto Revert mode. | 452 | "Toggle Global Auto-Revert Mode. |
| 441 | With a prefix argument ARG, enable Global Auto Revert mode if ARG | 453 | With a prefix argument ARG, enable Global Auto-Revert Mode if ARG |
| 442 | is positive, and disable it otherwise. If called from Lisp, | 454 | is positive, and disable it otherwise. If called from Lisp, |
| 443 | enable the mode if ARG is omitted or nil. | 455 | enable the mode if ARG is omitted or nil. |
| 444 | 456 | ||
| 445 | Global Auto Revert mode is a global minor mode that reverts any | 457 | Global Auto-Revert Mode is a global minor mode that reverts any |
| 446 | buffer associated with a file when the file changes on disk. Use | 458 | buffer associated with a file when the file changes on disk. Use |
| 447 | `auto-revert-mode' to revert a particular buffer. | 459 | `auto-revert-mode' to revert a particular buffer. |
| 448 | 460 | ||
| @@ -573,16 +585,19 @@ no more reverts are possible until the next call of | |||
| 573 | 585 | ||
| 574 | (if (eq action 'stopped) | 586 | (if (eq action 'stopped) |
| 575 | ;; File notification has stopped. Continue with polling. | 587 | ;; File notification has stopped. Continue with polling. |
| 576 | (cl-dolist (buffer buffers) | 588 | (cl-dolist (buffer |
| 589 | (if global-auto-revert-mode | ||
| 590 | (buffer-list) auto-revert-buffer-list)) | ||
| 577 | (with-current-buffer buffer | 591 | (with-current-buffer buffer |
| 578 | (when (or | 592 | (when (and (equal descriptor auto-revert-notify-watch-descriptor) |
| 579 | ;; A buffer associated with a file. | 593 | (or |
| 580 | (and (stringp buffer-file-name) | 594 | ;; A buffer associated with a file. |
| 581 | (string-equal | 595 | (and (stringp buffer-file-name) |
| 582 | (file-name-nondirectory file) | 596 | (string-equal |
| 583 | (file-name-nondirectory buffer-file-name))) | 597 | (file-name-nondirectory file) |
| 584 | ;; A buffer w/o a file, like dired. | 598 | (file-name-nondirectory buffer-file-name))) |
| 585 | (null buffer-file-name)) | 599 | ;; A buffer w/o a file, like dired. |
| 600 | (null buffer-file-name))) | ||
| 586 | (auto-revert-notify-rm-watch) | 601 | (auto-revert-notify-rm-watch) |
| 587 | (setq-local auto-revert-use-notify nil)))) | 602 | (setq-local auto-revert-use-notify nil)))) |
| 588 | 603 | ||
| @@ -736,7 +751,7 @@ To avoid starvation, the buffers in `auto-revert-remaining-buffers' | |||
| 736 | are checked first the next time this function is called. | 751 | are checked first the next time this function is called. |
| 737 | 752 | ||
| 738 | This function is also responsible for removing buffers no longer in | 753 | This function is also responsible for removing buffers no longer in |
| 739 | Auto-Revert mode from `auto-revert-buffer-list', and for canceling | 754 | Auto-Revert Mode from `auto-revert-buffer-list', and for canceling |
| 740 | the timer when no buffers need to be checked." | 755 | the timer when no buffers need to be checked." |
| 741 | 756 | ||
| 742 | (setq auto-revert-buffers-counter | 757 | (setq auto-revert-buffers-counter |
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el index a6f8cb29563..2f951c0c9aa 100644 --- a/test/lisp/autorevert-tests.el +++ b/test/lisp/autorevert-tests.el | |||
| @@ -156,7 +156,76 @@ | |||
| 156 | (ignore-errors (delete-directory tmpdir1 'recursive)) | 156 | (ignore-errors (delete-directory tmpdir1 'recursive)) |
| 157 | (ignore-errors (delete-directory tmpdir2 'recursive))))) | 157 | (ignore-errors (delete-directory tmpdir2 'recursive))))) |
| 158 | 158 | ||
| 159 | (ert-deftest auto-revert-test02-auto-revert-tail-mode () | 159 | ;; This is inspired by Bug#23276. |
| 160 | (ert-deftest auto-revert-test02-auto-revert-deleted-file () | ||
| 161 | "Check autorevert for a deleted file." | ||
| 162 | :tags '(:expensive-test) | ||
| 163 | |||
| 164 | (let ((tmpfile (make-temp-file "auto-revert-test")) | ||
| 165 | buf) | ||
| 166 | (unwind-protect | ||
| 167 | (progn | ||
| 168 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 169 | (narrow-to-region (point-max) (point-max))) | ||
| 170 | (write-region "any text" nil tmpfile nil 'no-message) | ||
| 171 | (setq buf (find-file-noselect tmpfile)) | ||
| 172 | (with-current-buffer buf | ||
| 173 | (should (string-equal (buffer-string) "any text")) | ||
| 174 | ;; `buffer-stale--default-function' checks for | ||
| 175 | ;; `verify-visited-file-modtime'. We must ensure that | ||
| 176 | ;; it returns nil. | ||
| 177 | (sleep-for 1) | ||
| 178 | (auto-revert-mode 1) | ||
| 179 | (should auto-revert-mode) | ||
| 180 | |||
| 181 | ;; Remove file while reverting. We simulate this by | ||
| 182 | ;; modifying `before-revert-hook'. | ||
| 183 | (add-hook | ||
| 184 | 'before-revert-hook | ||
| 185 | (lambda () (delete-file buffer-file-name)) | ||
| 186 | nil t) | ||
| 187 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 188 | (narrow-to-region (point-max) (point-max))) | ||
| 189 | (sleep-for 1) | ||
| 190 | (write-region "another text" nil tmpfile nil 'no-message) | ||
| 191 | |||
| 192 | ;; Check, that the buffer hasn't been reverted. File | ||
| 193 | ;; notification should be disabled, falling back to | ||
| 194 | ;; polling. | ||
| 195 | (auto-revert--wait-for-revert buf) | ||
| 196 | (should (string-match "any text" (buffer-string))) | ||
| 197 | (should-not auto-revert-use-notify) | ||
| 198 | |||
| 199 | ;; Once the file has been recreated, the buffer shall be | ||
| 200 | ;; reverted. | ||
| 201 | (kill-local-variable 'before-revert-hook) | ||
| 202 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 203 | (narrow-to-region (point-max) (point-max))) | ||
| 204 | (sleep-for 1) | ||
| 205 | (write-region "another text" nil tmpfile nil 'no-message) | ||
| 206 | |||
| 207 | ;; Check, that the buffer has been reverted. | ||
| 208 | (auto-revert--wait-for-revert buf) | ||
| 209 | (should (string-match "another text" (buffer-string))) | ||
| 210 | |||
| 211 | ;; An empty file shall still be reverted. | ||
| 212 | (with-current-buffer (get-buffer-create "*Messages*") | ||
| 213 | (narrow-to-region (point-max) (point-max))) | ||
| 214 | (sleep-for 1) | ||
| 215 | (write-region "" nil tmpfile nil 'no-message) | ||
| 216 | |||
| 217 | ;; Check, that the buffer has been reverted. | ||
| 218 | (auto-revert--wait-for-revert buf) | ||
| 219 | (should (string-equal "" (buffer-string))))) | ||
| 220 | |||
| 221 | ;; Exit. | ||
| 222 | (with-current-buffer "*Messages*" (widen)) | ||
| 223 | (ignore-errors | ||
| 224 | (with-current-buffer buf (set-buffer-modified-p nil)) | ||
| 225 | (kill-buffer buf)) | ||
| 226 | (ignore-errors (delete-file tmpfile))))) | ||
| 227 | |||
| 228 | (ert-deftest auto-revert-test03-auto-revert-tail-mode () | ||
| 160 | "Check autorevert tail mode." | 229 | "Check autorevert tail mode." |
| 161 | ;; `auto-revert-buffers' runs every 5". And we must wait, until the | 230 | ;; `auto-revert-buffers' runs every 5". And we must wait, until the |
| 162 | ;; file has been reverted. | 231 | ;; file has been reverted. |
| @@ -194,7 +263,7 @@ | |||
| 194 | (ignore-errors (kill-buffer buf)) | 263 | (ignore-errors (kill-buffer buf)) |
| 195 | (ignore-errors (delete-file tmpfile))))) | 264 | (ignore-errors (delete-file tmpfile))))) |
| 196 | 265 | ||
| 197 | (ert-deftest auto-revert-test03-auto-revert-mode-dired () | 266 | (ert-deftest auto-revert-test04-auto-revert-mode-dired () |
| 198 | "Check autorevert for dired." | 267 | "Check autorevert for dired." |
| 199 | ;; `auto-revert-buffers' runs every 5". And we must wait, until the | 268 | ;; `auto-revert-buffers' runs every 5". And we must wait, until the |
| 200 | ;; file has been reverted. | 269 | ;; file has been reverted. |