aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2020-03-30 01:34:47 +0300
committerJuri Linkov2020-03-30 01:34:47 +0300
commit7a6f5a5167037cdc3a0e9e312393781daedec085 (patch)
tree4ecad790cfa5a3d82be76d7b672a22cce1153b02
parent1276c8e10b000b571a12227ebe9216cc6305ef7f (diff)
downloademacs-7a6f5a5167037cdc3a0e9e312393781daedec085.tar.gz
emacs-7a6f5a5167037cdc3a0e9e312393781daedec085.zip
Support state changing VC operations on directories in Dired (bug#34949)
* lisp/dired-aux.el (dired-vc-next-action): New command. (dired-vc-deduce-fileset): Rename from vc-dired-deduce-fileset in vc.el. * lisp/dired.el (dired-mode-map): Remap vc-next-action to dired-vc-next-action. * lisp/vc/vc-dir.el (vc-dir-mark-files): New function. (vc-dir-refresh): Run hook vc-dir-refresh-hook. * lisp/vc/vc.el (vc-deduce-fileset): Rename arg 'observer' to 'not-state-changing' and document it in docstring. (vc-dired-deduce-fileset): Rename to dired-vc-deduce-fileset in dired-aux.el. * lisp/cedet/ede.el (ede-turn-on-hook, ede-minor-mode): * lisp/desktop.el (desktop-minor-mode-table): Rename the long ago obsolete vc-dired-mode to vc-dir-mode.
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/cedet/ede.el4
-rw-r--r--lisp/desktop.el2
-rw-r--r--lisp/dired-aux.el62
-rw-r--r--lisp/dired.el1
-rw-r--r--lisp/vc/vc-dir.el14
-rw-r--r--lisp/vc/vc.el40
7 files changed, 90 insertions, 37 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 4b477e5def6..bb5f549a2e2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -108,8 +108,8 @@ Mark mode, then Dired commands operate only on files in the active
108region. The values 'file' and 'line' of this user option define the 108region. The values 'file' and 'line' of this user option define the
109details of marking the file at the end of the region. 109details of marking the file at the end of the region.
110 110
111*** State changing VC operations are supported in 'dired-mode' on files 111*** State changing VC operations are supported in Dired on files and
112(but still not on directories). 112directories with the help of new command 'dired-vc-next-action'.
113 113
114** Change Logs and VC 114** Change Logs and VC
115 115
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index c2036878288..8c336117c92 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -470,7 +470,7 @@ To be used in hook functions."
470 ;; Emacs 21 has no buffer file name for directory edits. 470 ;; Emacs 21 has no buffer file name for directory edits.
471 ;; so we need to add these hacks in. 471 ;; so we need to add these hacks in.
472 (eq major-mode 'dired-mode) 472 (eq major-mode 'dired-mode)
473 (eq major-mode 'vc-dired-mode)) 473 (eq major-mode 'vc-dir-mode))
474 (ede-minor-mode 1))) 474 (ede-minor-mode 1)))
475 475
476(define-minor-mode ede-minor-mode 476(define-minor-mode ede-minor-mode
@@ -481,7 +481,7 @@ controlled project, then this mode is activated automatically
481provided `global-ede-mode' is enabled." 481provided `global-ede-mode' is enabled."
482 :group 'ede 482 :group 'ede
483 (cond ((or (eq major-mode 'dired-mode) 483 (cond ((or (eq major-mode 'dired-mode)
484 (eq major-mode 'vc-dired-mode)) 484 (eq major-mode 'vc-dir-mode))
485 (ede-dired-minor-mode (if ede-minor-mode 1 -1))) 485 (ede-dired-minor-mode (if ede-minor-mode 1 -1)))
486 (ede-minor-mode 486 (ede-minor-mode
487 (if (not ede-constructing) 487 (if (not ede-constructing)
diff --git a/lisp/desktop.el b/lisp/desktop.el
index de601a4de8c..9d117c6f0d6 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -534,7 +534,7 @@ can guess how to load the mode's definition.")
534 '((defining-kbd-macro nil) 534 '((defining-kbd-macro nil)
535 (isearch-mode nil) 535 (isearch-mode nil)
536 (vc-mode nil) 536 (vc-mode nil)
537 (vc-dired-mode nil) 537 (vc-dir-mode nil)
538 (erc-track-minor-mode nil) 538 (erc-track-minor-mode nil)
539 (savehist-mode nil)) 539 (savehist-mode nil))
540 "Table mapping minor mode variables to minor mode functions. 540 "Table mapping minor mode variables to minor mode functions.
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 6f50a3da6ca..60a352d78e0 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -3050,6 +3050,68 @@ instead."
3050 (backward-delete-char 1)) 3050 (backward-delete-char 1))
3051 (message "%s" (buffer-string))))) 3051 (message "%s" (buffer-string)))))
3052 3052
3053
3054;;; Version control from dired
3055
3056(declare-function vc-dir-unmark-all-files "vc-dir")
3057(declare-function vc-dir-mark-files "vc-dir")
3058
3059;;;###autoload
3060(defun dired-vc-next-action (verbose)
3061 "Do the next version control operation on marked files/directories.
3062When only files are marked then call `vc-next-action' with the
3063same value of the VERBOSE argument.
3064When also directories are marked then call `vc-dir' and mark
3065the same files/directories in the VC-Dir buffer that were marked
3066in the Dired buffer."
3067 (interactive "P")
3068 (let* ((marked-files
3069 (dired-get-marked-files nil nil nil nil t))
3070 (mark-files
3071 (when (cl-some #'file-directory-p marked-files)
3072 ;; Fix deficiency of Dired by adding slash to dirs
3073 (mapcar (lambda (file)
3074 (if (file-directory-p file)
3075 (file-name-as-directory file)
3076 file))
3077 marked-files))))
3078 (if mark-files
3079 (let ((transient-hook (make-symbol "vc-dir-mark-files")))
3080 (fset transient-hook
3081 (lambda ()
3082 (remove-hook 'vc-dir-refresh-hook transient-hook t)
3083 (vc-dir-unmark-all-files t)
3084 (vc-dir-mark-files mark-files)))
3085 (vc-dir-root)
3086 (add-hook 'vc-dir-refresh-hook transient-hook nil t))
3087 (vc-next-action verbose))))
3088
3089(declare-function vc-compatible-state "vc")
3090
3091(defun dired-vc-deduce-fileset (&optional state-model-only-files not-state-changing)
3092 (let ((backend (vc-responsible-backend default-directory))
3093 (files (dired-get-marked-files nil nil nil nil t))
3094 only-files-list
3095 state
3096 model)
3097 (when (and (not not-state-changing) (cl-some #'file-directory-p files))
3098 (user-error "State changing VC operations on directories supported only in `vc-dir'"))
3099
3100 (when state-model-only-files
3101 (setq only-files-list (mapcar (lambda (file) (cons file (vc-state file))) files))
3102 (setq state (cdar only-files-list))
3103 ;; Check that all files are in a consistent state, since we use that
3104 ;; state to decide which operation to perform.
3105 (dolist (crt (cdr only-files-list))
3106 (unless (vc-compatible-state (cdr crt) state)
3107 (error "When applying VC operations to multiple files, the files are required\nto be in similar VC states.\n%s in state %s clashes with %s in state %s"
3108 (car crt) (cdr crt) (caar only-files-list) state)))
3109 (setq only-files-list (mapcar 'car only-files-list))
3110 (when (and state (not (eq state 'unregistered)))
3111 (setq model (vc-checkout-model backend only-files-list))))
3112 (list backend files only-files-list state model)))
3113
3114
3053(provide 'dired-aux) 3115(provide 'dired-aux)
3054 3116
3055;; Local Variables: 3117;; Local Variables:
diff --git a/lisp/dired.el b/lisp/dired.el
index 41bbf9f56a2..72d1cc250a3 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1870,6 +1870,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
1870 (define-key map "\177" 'dired-unmark-backward) 1870 (define-key map "\177" 'dired-unmark-backward)
1871 (define-key map [remap undo] 'dired-undo) 1871 (define-key map [remap undo] 'dired-undo)
1872 (define-key map [remap advertised-undo] 'dired-undo) 1872 (define-key map [remap advertised-undo] 'dired-undo)
1873 (define-key map [remap vc-next-action] 'dired-vc-next-action)
1873 ;; thumbnail manipulation (image-dired) 1874 ;; thumbnail manipulation (image-dired)
1874 (define-key map "\C-td" 'image-dired-display-thumbs) 1875 (define-key map "\C-td" 'image-dired-display-thumbs)
1875 (define-key map "\C-tt" 'image-dired-tag-files) 1876 (define-key map "\C-tt" 'image-dired-tag-files)
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index b760e170676..ab5943917b8 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -696,6 +696,17 @@ share the same state."
696 (vc-dir-mark-file crt))) 696 (vc-dir-mark-file crt)))
697 (setq crt (ewoc-next vc-ewoc crt)))))))) 697 (setq crt (ewoc-next vc-ewoc crt))))))))
698 698
699(defun vc-dir-mark-files (mark-files)
700 "Mark files specified by file names in the argument MARK-FILES.
701MARK-FILES should be a list of absolute filenames."
702 (ewoc-map
703 (lambda (filearg)
704 (when (member (expand-file-name (vc-dir-fileinfo->name filearg))
705 mark-files)
706 (setf (vc-dir-fileinfo->marked filearg) t)
707 t))
708 vc-ewoc))
709
699(defun vc-dir-unmark-file () 710(defun vc-dir-unmark-file ()
700 ;; Unmark the current file and move to the next line. 711 ;; Unmark the current file and move to the next line.
701 (let* ((crt (ewoc-locate vc-ewoc)) 712 (let* ((crt (ewoc-locate vc-ewoc))
@@ -1193,7 +1204,8 @@ Throw an error if another update process is in progress."
1193 (if remaining 1204 (if remaining
1194 (vc-dir-refresh-files 1205 (vc-dir-refresh-files
1195 (mapcar 'vc-dir-fileinfo->name remaining)) 1206 (mapcar 'vc-dir-fileinfo->name remaining))
1196 (setq mode-line-process nil)))))))))))) 1207 (setq mode-line-process nil)
1208 (run-hooks 'vc-dir-refresh-hook))))))))))))
1197 1209
1198(defun vc-dir-show-fileentry (file) 1210(defun vc-dir-show-fileentry (file)
1199 "Insert an entry for a specific file into the current *VC-dir* listing. 1211 "Insert an entry for a specific file into the current *VC-dir* listing.
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 607fb37807c..d4323d59eb3 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1006,12 +1006,18 @@ Within directories, only files already under version control are noticed."
1006 1006
1007(declare-function vc-dir-current-file "vc-dir" ()) 1007(declare-function vc-dir-current-file "vc-dir" ())
1008(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files)) 1008(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files))
1009(declare-function dired-vc-deduce-fileset "dired-aux" (&optional state-model-only-files not-state-changing))
1009 1010
1010(defun vc-deduce-fileset (&optional observer allow-unregistered 1011(defun vc-deduce-fileset (&optional not-state-changing
1012 allow-unregistered
1011 state-model-only-files) 1013 state-model-only-files)
1012 "Deduce a set of files and a backend to which to apply an operation. 1014 "Deduce a set of files and a backend to which to apply an operation.
1013Return (BACKEND FILESET FILESET-ONLY-FILES STATE CHECKOUT-MODEL). 1015Return (BACKEND FILESET FILESET-ONLY-FILES STATE CHECKOUT-MODEL).
1014 1016
1017NOT-STATE-CHANGING if non-nil, means that the operation
1018requesting the fileset doesn't intend to change VC state,
1019such as printing the log or showing the diff.
1020
1015If we're in VC-dir mode, FILESET is the list of marked files, 1021If we're in VC-dir mode, FILESET is the list of marked files,
1016or the directory if no files are marked. 1022or the directory if no files are marked.
1017Otherwise, if in a buffer visiting a version-controlled file, 1023Otherwise, if in a buffer visiting a version-controlled file,
@@ -1025,14 +1031,12 @@ the FILESET-ONLY-FILES STATE and MODEL info. Otherwise, that
1025part may be skipped. 1031part may be skipped.
1026 1032
1027BEWARE: this function may change the current buffer." 1033BEWARE: this function may change the current buffer."
1028 ;; FIXME: OBSERVER is unused. The name is not intuitive and is not
1029 ;; documented. It's set to t when called from diff and print-log.
1030 (let (backend) 1034 (let (backend)
1031 (cond 1035 (cond
1032 ((derived-mode-p 'vc-dir-mode) 1036 ((derived-mode-p 'vc-dir-mode)
1033 (vc-dir-deduce-fileset state-model-only-files)) 1037 (vc-dir-deduce-fileset state-model-only-files))
1034 ((derived-mode-p 'dired-mode) 1038 ((derived-mode-p 'dired-mode)
1035 (vc-dired-deduce-fileset state-model-only-files observer)) 1039 (dired-vc-deduce-fileset state-model-only-files not-state-changing))
1036 ((setq backend (vc-backend buffer-file-name)) 1040 ((setq backend (vc-backend buffer-file-name))
1037 (if state-model-only-files 1041 (if state-model-only-files
1038 (list backend (list buffer-file-name) 1042 (list backend (list buffer-file-name)
@@ -1048,7 +1052,7 @@ BEWARE: this function may change the current buffer."
1048 (derived-mode-p 'dired-mode))))) 1052 (derived-mode-p 'dired-mode)))))
1049 (progn ;FIXME: Why not `with-current-buffer'? --Stef. 1053 (progn ;FIXME: Why not `with-current-buffer'? --Stef.
1050 (set-buffer vc-parent-buffer) 1054 (set-buffer vc-parent-buffer)
1051 (vc-deduce-fileset observer allow-unregistered state-model-only-files))) 1055 (vc-deduce-fileset not-state-changing allow-unregistered state-model-only-files)))
1052 ((and (derived-mode-p 'log-view-mode) 1056 ((and (derived-mode-p 'log-view-mode)
1053 (setq backend (vc-responsible-backend default-directory))) 1057 (setq backend (vc-responsible-backend default-directory)))
1054 (list backend nil)) 1058 (list backend nil))
@@ -1065,32 +1069,6 @@ BEWARE: this function may change the current buffer."
1065 (list buffer-file-name)))) 1069 (list buffer-file-name))))
1066 (t (error "File is not under version control"))))) 1070 (t (error "File is not under version control")))))
1067 1071
1068(declare-function dired-get-marked-files "dired"
1069 (&optional localp arg filter distinguish-one-marked error))
1070
1071(defun vc-dired-deduce-fileset (&optional state-model-only-files observer)
1072 (let ((backend (vc-responsible-backend default-directory))
1073 (files (dired-get-marked-files nil nil nil nil t))
1074 only-files-list
1075 state
1076 model)
1077 (when (and (not observer) (cl-some #'file-directory-p files))
1078 (error "State changing VC operations on directories not supported in `dired-mode'"))
1079
1080 (when state-model-only-files
1081 (setq only-files-list (mapcar (lambda (file) (cons file (vc-state file))) files))
1082 (setq state (cdar only-files-list))
1083 ;; Check that all files are in a consistent state, since we use that
1084 ;; state to decide which operation to perform.
1085 (dolist (crt (cdr only-files-list))
1086 (unless (vc-compatible-state (cdr crt) state)
1087 (error "When applying VC operations to multiple files, the files are required\nto be in similar VC states.\n%s in state %s clashes with %s in state %s"
1088 (car crt) (cdr crt) (caar only-files-list) state)))
1089 (setq only-files-list (mapcar 'car only-files-list))
1090 (when (and state (not (eq state 'unregistered)))
1091 (setq model (vc-checkout-model backend only-files-list))))
1092 (list backend files only-files-list state model)))
1093
1094(defun vc-ensure-vc-buffer () 1072(defun vc-ensure-vc-buffer ()
1095 "Make sure that the current buffer visits a version-controlled file." 1073 "Make sure that the current buffer visits a version-controlled file."
1096 (cond 1074 (cond