master 9f163754264: Refresh VC-Dir headers after pull or push

Sean Whitton <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 9f163754264f3b840502ecfa09b4fc551e7aabb1
Author: Sean Whitton <[email protected]>
Commit: Sean Whitton <[email protected]>

    Refresh VC-Dir headers after pull or push
    
    * lisp/vc/vc-dir.el (vc-dir--buffers-dolist): New macro,
    factored out.
    (vc-dir-resynch-file): Use it.
    (vc-dir--refresh-headers): New function.
    * lisp/vc/vc.el (vc-pull, vc-push): Use it.
---
 lisp/vc/vc-dir.el | 91 +++++++++++++++++++++++++++++++++----------------------
 lisp/vc/vc.el     | 10 ++++--
 2 files changed, 62 insertions(+), 39 deletions(-)

diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index f0a922e6639..8166384bbd6 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -1388,44 +1388,52 @@ that file."
 	      fileentries))
       (vc-dir-update fileentries (current-buffer)))))
 
+(defmacro vc-dir--buffers-dolist (status-buf &rest body)
+  "Bind STATUS-BUF to each of `vc-dir-buffers' in turn and execute BODY.
+Also removes any out-of-date entries in `vc-dir-buffers'."
+  (declare (indent 1) (debug (sexp body)))
+  (cl-with-gensyms (drop)
+    `(let (,drop)
+       (save-current-buffer
+         (unwind-protect
+             (dolist (,status-buf vc-dir-buffers)
+               (if (not (buffer-live-p status-buf))
+                   (push ,status-buf ,drop)
+                 (set-buffer ,status-buf)
+                 (if (not (derived-mode-p 'vc-dir-mode))
+                     (push ,status-buf ,drop)
+                   ,@body)))
+           ;; Remove out-of-date entries from `vc-dir-buffers'.
+           (setq vc-dir-buffers
+                 (cl-nset-difference vc-dir-buffers ,drop :test #'eq)))))))
+
 (defun vc-dir-resynch-file (&optional fname)
   "Update the entries for FNAME in any directory buffers that list it."
-  (let* ((file (file-truename (or fname buffer-file-name)))
-         (drop '()))
-    (save-current-buffer
-      ;; look for a vc-dir buffer that might show this file.
-      (dolist (status-buf vc-dir-buffers)
-        (if (not (buffer-live-p status-buf))
-            (push status-buf drop)
-          (set-buffer status-buf)
-          (if (not (derived-mode-p 'vc-dir-mode))
-              (push status-buf drop)
-            (let ((ddir (expand-file-name
-                         ;; The actual contents of this VC-Dir buffer,
-                         ;; which is what we care about here, is always
-                         ;; relative to the toplevel value.
-                         ;; If we invoked the current command from
-                         ;; STATUS-BUF then it might have shadowed
-                         ;; `default-directory' in order to do its work,
-                         ;; but that's irrelevant to us here.
-                         (buffer-local-toplevel-value 'default-directory))))
-              (when (file-in-directory-p file ddir)
-                (if (file-directory-p file)
-		    (progn
-		      (vc-dir-resync-directory-files file)
-		      (vc-dir--set-header ddir))
-                  (let* ((complete-state
-                          ;; Pass two truenames (bug#80803, bug#80967).
-                          (vc-dir-recompute-file-state file
-                                                       (file-truename ddir)))
-			 (state (cadr complete-state)))
-                    (vc-dir-update (list complete-state)
-                                   status-buf
-                                   (or (not state)
-				       (eq state 'up-to-date)))))))))))
-    ;; Remove out-of-date entries from vc-dir-buffers.
-    (setq vc-dir-buffers
-          (cl-nset-difference vc-dir-buffers drop :test #'eq))))
+  (let ((file (file-truename (or fname buffer-file-name))))
+    (vc-dir--buffers-dolist status-buf
+      ;; Look for a VC-Dir buffer that might show this file.
+      (let ((ddir (expand-file-name
+                   ;; The actual contents of this VC-Dir buffer, which
+                   ;; is what we care about here, is always relative to
+                   ;; the toplevel value.  If we invoked the current
+                   ;; command from STATUS-BUF then it might have
+                   ;; shadowed `default-directory' in order to do its
+                   ;; work, but that's irrelevant to us here.
+                   (buffer-local-toplevel-value 'default-directory))))
+        (when (file-in-directory-p file ddir)
+          (if (file-directory-p file)
+	      (progn
+		(vc-dir-resync-directory-files file)
+		(vc-dir--set-header ddir))
+            (let* ((complete-state
+                    ;; Pass two truenames (bug#80803, bug#80967).
+                    (vc-dir-recompute-file-state file
+                                                 (file-truename ddir)))
+		   (state (cadr complete-state)))
+              (vc-dir-update (list complete-state)
+                             status-buf
+                             (or (not state)
+				 (eq state 'up-to-date))))))))))
 
 (defvar use-vc-backend)  ;; dynamically bound
 
@@ -1792,12 +1800,21 @@ Throw an error if another update process is in progress."
                      (setq mode-line-process nil)
                      (run-hooks 'vc-dir-refresh-hook))))))))))))
 
+(defun vc-dir--refresh-headers (directory)
+  "Refresh the headers for any VC-Dir buffers within DIRECTORY."
+  (let ((directory (expand-file-name directory)))
+    (vc-dir--buffers-dolist status-buf
+      (let ((ddir (buffer-local-toplevel-value 'default-directory)))
+        (when (file-in-directory-p ddir directory)
+          (vc-dir--set-header ddir))))))
+
 (defun vc-dir-show-fileentry (file)
   "Insert an entry for a specific file into the current *VC-Dir* listing.
 This is typically used if the file is up-to-date (or has been added
 outside of VC) and one wants to do some operation on it."
   (interactive "fShow file: ")
-  (vc-dir-update (list (list (file-relative-name file) (vc-state file))) (current-buffer)))
+  (vc-dir-update `((,(file-relative-name file) ,(vc-state file)))
+                 (current-buffer)))
 
 (defun vc-dir-hide-state (&optional state)
   "Hide items that are in STATE from display.
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index ecfca3847f0..a9b72f471ae 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -4859,6 +4859,8 @@ to the working revision (except for keyword expansion)."
 ;;;###autoload
 (defalias 'vc-restore #'vc-revert)
 
+(declare-function vc-dir--refresh-headers "vc-dir")
+
 ;;;###autoload
 (defun vc-pull (&optional arg)
   "Update the current fileset or branch.
@@ -4896,7 +4898,9 @@ tip revision are merged into the working file."
       ;; FIXME: Ideally we would only clear out the stored value for the
       ;; REMOTE-LOCATION from which we are pulling.
       (vc-run-delayed
-        (vc--repo-setprop backend 'vc-incoming-revision nil)))
+        (vc--repo-setprop backend 'vc-incoming-revision nil))
+      (when vc-dir-buffers
+        (vc-dir--refresh-headers (vc-root-dir backend))))
      ;; If VCS has `merge-news' functionality (CVS and SVN), use it.
      ((vc-find-backend-function backend 'merge-news)
       (save-some-buffers                ; save buffers visiting files
@@ -4939,7 +4943,9 @@ It also signals an error in a Bazaar bound branch."
                ;; FIXME: Ideally we would only clear out the
                ;; REMOTE-LOCATION to which we are pushing.
                (vc-run-delayed
-                 (vc--repo-setprop backend 'vc-incoming-revision nil)))
+                 (vc--repo-setprop backend 'vc-incoming-revision nil))
+               (when vc-dir-buffers
+                 (vc-dir--refresh-headers (vc-root-dir backend))))
       (user-error "VC push is unsupported for `%s'" backend))))
 
 ;;;###autoload
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.