Subject: bug#75626: 31.0.50; Dired misses or double-processes files when auto-revert-mode is enabled

From: Tassilo Horn <[email-masked]>
Date: Sun, 02 Feb 2025 20:10:15 +0100

Michael Albinus <[email-masked]> writes:

Hi Michael,

> Below is an updated patch for autorevert.el. I control this now via
> auto-revert-active-p; no further need to check in auto-revert-buffer.
>
> Could you, pls, test?

Of course.  It does not contain any changes to dired, so I've applied
the changes of your previous patch giving this complete patch:
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index 1dcfe8e911f..5acb1220471 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -774,9 +774,10 @@ auto-revert--end-lockout
 
 (defun auto-revert-active-p ()
   "Check if auto-revert is active in current buffer."
-  (or auto-revert-mode
-      auto-revert-tail-mode
-      auto-revert--global-mode))
+  (and (or auto-revert-mode
+           auto-revert-tail-mode
+           auto-revert--global-mode)
+       (not (memq (current-buffer) inhibit-auto-revert-buffers))))
 
 (defun auto-revert-handler ()
   "Revert current buffer, if appropriate.
@@ -798,14 +799,17 @@ auto-revert-handler
                                 (setq size
                                       (file-attribute-size
                                        (file-attributes buffer-file-name)))))
-                     (funcall (or buffer-stale-function
-                                  #'buffer-stale--default-function)
-                              t)))
+                     (and (not (memq (current-buffer)
+                                     inhibit-auto-revert-buffers))
+                          (funcall (or buffer-stale-function
+                                       #'buffer-stale--default-function)
+                                   t))))
             (and (or auto-revert-mode
                      global-auto-revert-non-file-buffers)
-                 (funcall (or buffer-stale-function
-                              #'buffer-stale--default-function)
-                          t))))
+                 (and (not (memq (current-buffer) inhibit-auto-revert-buffers))
+                      (funcall (or buffer-stale-function
+                                   #'buffer-stale--default-function)
+                               t)))))
          eob eoblist)
     (setq auto-revert-notify-modified-p nil
           auto-revert--last-time (current-time))
@@ -897,6 +901,31 @@ auto-revert--buffer-candidates
         (push buf new)))
     (nreverse (nconc new remaining))))
 
+;;;###autoload
+(progn
+  (defvar inhibit-auto-revert-buffers nil
+    "A list of buffers with suppressed auto-revert.")
+
+  (defmacro inhibit-auto-revert (&rest body)
+    "Deactivate auto-reverting of current buffer temporarily.
+Run BODY."
+    (declare (indent 0) (debug ((form body) body)))
+    `(progn
+       ;; Cleanup.
+       (dolist (buf inhibit-auto-revert-buffers)
+         (unless (buffer-live-p buf)
+           (setq inhibit-auto-revert-buffers
+                 (delq buf inhibit-auto-revert-buffers))))
+       (let ((buf (and (not (memq (current-buffer) inhibit-auto-revert-buffers))
+                       (current-buffer))))
+         (unwind-protect
+             (progn
+               (when buf (add-to-list 'inhibit-auto-revert-buffers buf))
+               ,@body)
+           (when buf
+             (setq inhibit-auto-revert-buffers
+                   (delq buf inhibit-auto-revert-buffers))))))))
+
 (defun auto-revert-buffer (buf)
   "Revert a single buffer BUF.
 
diff --git a/lisp/dired.el b/lisp/dired.el
index 2eb6546107a..01621c9ea4e 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -944,9 +944,6 @@ dired-mark-if
                           ""))))
     (and (> count 0) count)))
 
-(defvar-local dired--inhibit-auto-revert nil
-  "A non-nil value prevents `auto-revert-mode' from reverting the buffer.")
-
 (defmacro dired-map-over-marks (body arg &optional show-progress
 				     distinguish-one-marked)
   "Eval BODY with point on each marked line.  Return a list of BODY's results.
@@ -983,8 +980,8 @@ dired-map-over-marks
   ;;endless loop.
   ;;This warning should not apply any longer, sk  2-Sep-1991 14:10.
   `(prog1
-       (let ((dired--inhibit-auto-revert t)
-             (inhibit-read-only t)
+       (inhibit-auto-revert
+       (let ((inhibit-read-only t)
              case-fold-search found results)
 	 (if (and ,arg (not (eq ,arg 'marked)))
 	     (if (integerp ,arg)
@@ -1024,7 +1021,7 @@ dired-map-over-marks
 	     (if found
 		 results
                (unless (eq ,arg 'marked)
-	         (list ,body))))))
+	         (list ,body)))))))
      ;; save-excursion loses, again
      (dired-move-to-filename)))
 
@@ -1294,12 +1291,6 @@ dired-buffer-stale-p
 	 ;; Do not auto-revert when the dired buffer can be currently
 	 ;; written by the user as in `wdired-mode'.
 	 buffer-read-only
-         ;; When a dired operation using dired-map-over-marks is in
-         ;; progress, dired--inhibit-auto-revert is bound to some
-         ;; non-nil value and we must not auto-revert because that could
-         ;; change the order of files leading to skipping or
-         ;; double-processing (see bug#75626).
-         (not dired--inhibit-auto-revert)
 	 (dired-directory-changed-p dirname))))
 
 (defcustom dired-auto-revert-buffer nil
@@ -4089,10 +4080,10 @@ dired-internal-do-deletions
 	    (while l
 	      (goto-char (marker-position (cdr (car l))))
               (dired-move-to-filename)
-	      (let ((inhibit-read-only t)
-                    ;; Temporarily prevent auto-revert while deleting
-                    ;; entry in the dired buffer (bug#71264).
-                    (dired--inhibit-auto-revert t))
+              ;; Temporarily prevent auto-revert while deleting entry in
+              ;; the dired buffer (bug#71264).
+              (inhibit-auto-revert
+	      (let ((inhibit-read-only t))
 		(condition-case err
 		    (let ((fn (car (car l))))
 		      (dired-delete-file fn dired-recursive-deletes trash)
@@ -4108,7 +4099,7 @@ dired-internal-do-deletions
                   (quit (throw '--delete-cancel (message "OK, canceled")))
 		  (error ;; catch errors from failed deletions
 		   (dired-log "%s: %s\n" (car err) (error-message-string err))
-		   (setq failures (cons (car (car l)) failures)))))
+		   (setq failures (cons (car (car l)) failures))))))
 	      (setq l (cdr l)))
 	    (if (not failures)
 		(progress-reporter-done progress-reporter)

And yes, it works. :-)

Side-note: at first, it did not work after applying the patch and
running "make" in the emacs directory (reproducibly!), a problem I've
had before somewhere up the thread.  The original bug was there again.
I placed a watch on inhibit-auto-revert-buffers which revealed that it
was set by the computation for all marked files in order to present them
at the yes-or-no-p prompt.  But it was not set during the actual
processing!  I had to manually delete the dired and autorevert ELC files
and "make" again.

Does anyone have a clue why?  Does a recompile of a changed file with
existing ELC not produce it from scratch?

Bye,
Tassilo