Subject: Re: bug#34949: 27.0.50; Docstring of `vc-deduce-fileset' incomplete

From: Juri Linkov <[email-masked]>
Date: Tue, 10 Mar 2020 00:55:41 +0200

> Anyway, please go ahead and try it for yourself.

I finished implementing this, and now it works surprisingly well -
typing 'C-x v v' on Dired directories puts marks on them in *vc-dir* buffer:

diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 96c400c54a..23f83bda3b 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1068,14 +1068,27 @@ vc-deduce-fileset
 (declare-function dired-get-marked-files "dired"
                   (&optional localp arg filter distinguish-one-marked error))
 
+(defvar vc-dir-mark-files nil)
+
 (defun vc-dired-deduce-fileset (&optional state-model-only-files observer)
   (let ((backend (vc-responsible-backend default-directory))
         (files (dired-get-marked-files nil nil nil nil t))
 	only-files-list
 	state
 	model)
+
     (when (and (not observer) (cl-some #'file-directory-p files))
-      (error "State changing VC operations on directories not supported in `dired-mode'"))
+      (let* ((rootdir (vc-call-backend backend 'root default-directory))
+             (vc-dir-mark-files
+              (mapcar (lambda (file)
+                        (file-relative-name
+                         (if (file-directory-p file)
+                             (file-name-as-directory file)
+                           file)
+                         rootdir))
+                      files)))
+        (vc-dir rootdir))
+      (user-error "State changing VC operations on directories supported only in `vc-dir'"))
 
     (when state-model-only-files
       (setq only-files-list (mapcar (lambda (file) (cons file (vc-state file))) files))
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 38b4937e85..8b03c7213e 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -1174,7 +1174,8 @@ vc-dir-refresh
       ;; Bzr has serious locking problems, so setup the headers first (this is
       ;; synchronous) rather than doing it while dir-status is running.
       (ewoc-set-hf vc-ewoc (vc-dir-headers backend def-dir) "")
-      (let ((buffer (current-buffer)))
+      (let ((buffer (current-buffer))
+            (mark-files vc-dir-mark-files))
         (with-current-buffer vc-dir-process-buffer
           (setq default-directory def-dir)
           (erase-buffer)
@@ -1193,7 +1194,15 @@ vc-dir-refresh
                    (if remaining
                        (vc-dir-refresh-files
                         (mapcar 'vc-dir-fileinfo->name remaining))
-                     (setq mode-line-process nil))))))))))))
+                     (setq mode-line-process nil)
+                     (when mark-files
+                       (vc-dir-unmark-all-files t)
+                       (ewoc-map
+                        (lambda (filearg)
+                          (when (member (vc-dir-fileinfo->name filearg) mark-files)
+                            (setf (vc-dir-fileinfo->marked filearg) t)
+                            t))
+                        vc-ewoc)))))))))))))
 
 (defun vc-dir-show-fileentry (file)
   "Insert an entry for a specific file into the current *VC-dir* listing.