diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 345a28d3f1..80c580e5ec 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -897,6 +897,7 @@ vc-prefix-map (define-key map "s" 'vc-create-tag) (define-key map "u" 'vc-revert) (define-key map "v" 'vc-next-action) + (define-key map "V" 'vc-next-action-on-root) (define-key map "+" 'vc-update) ;; I'd prefer some kind of symmetry with vc-update: (define-key map "P" 'vc-push) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index f7d651fac6..13d60b6fcf 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1065,19 +1067,27 @@ vc-deduce-fileset (list buffer-file-name)))) (t (error "File is not under version control"))))) +(defun vc-root-deduce-fileset (callback) + (let* ((backend (vc-responsible-backend default-directory)) + (rootdir (vc-call-backend backend 'root default-directory))) + (vc-directory-deduce-fileset rootdir callback))) + +(defun vc-directory-deduce-fileset (dir callback) + ;; TODO: use vc-dir-status-files + ) + (declare-function dired-get-marked-files "dired" (&optional localp arg filter distinguish-one-marked error)) -(defun vc-dired-deduce-fileset (&optional state-model-only-files observer) +(defun vc-dired-deduce-fileset (&optional callback) (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'")) - (when state-model-only-files + (when callback + ;; TODO: use vc-directory-deduce-fileset (setq only-files-list (mapcar (lambda (file) (cons file (vc-state file))) files)) (setq state (cdar only-files-list)) ;; Check that all files are in a consistent state, since we use that @@ -1132,6 +1142,11 @@ vc-read-backend (completing-read prompt (mapcar #'symbol-name vc-handled-backends) nil 'require-match))) +(defun vc-next-action-on-root (verbose) + (interactive "P") + (vc-root-deduce-fileset + (lambda (vc-fileset) (vc-next-action-on-fileset vc-fileset verbose)))) + ;; Here's the major entry point. ;;;###autoload @@ -1158,8 +1173,16 @@ vc-next-action If every file is locked by you and unchanged, unlock them. If every file is locked by someone else, offer to steal the lock." (interactive "P") - (let* ((vc-fileset (vc-deduce-fileset nil t 'state-model-only-files)) - (backend (car vc-fileset)) + (cond + ((derived-mode-p 'dired-mode) + ;; Async operation + (vc-dired-deduce-fileset + (lambda (vc-fileset) (vc-next-action-on-fileset vc-fileset verbose)))) + (t (vc-next-action-on-fileset + (vc-deduce-fileset nil t 'state-model-only-files) verbose)))) + +(defun vc-next-action-on-fileset (vc-fileset verbose) + (let* ((backend (car vc-fileset)) (files (nth 1 vc-fileset)) ;; (fileset-only-files (nth 2 vc-fileset)) ;; FIXME: We used to call `vc-recompute-state' here. @@ -3138,6 +3171,10 @@ vc-default-dir-status-files (funcall update-function (mapcar (lambda (file) (list file 'up-to-date)) files))) +(defun vc-dir-status-files (backend dir files update-function) + (funcall update-function + (mapcar (lambda (file) (list file 'up-to-date)) files))) + (defun vc-check-headers () "Check if the current file has any headers in it." (interactive)