mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-27 07:37:33 +00:00
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.
This commit is contained in:
parent
1276c8e10b
commit
7a6f5a5167
4
etc/NEWS
4
etc/NEWS
@ -108,8 +108,8 @@ Mark mode, then Dired commands operate only on files in the active
|
||||
region. The values 'file' and 'line' of this user option define the
|
||||
details of marking the file at the end of the region.
|
||||
|
||||
*** State changing VC operations are supported in 'dired-mode' on files
|
||||
(but still not on directories).
|
||||
*** State changing VC operations are supported in Dired on files and
|
||||
directories with the help of new command 'dired-vc-next-action'.
|
||||
|
||||
** Change Logs and VC
|
||||
|
||||
|
@ -470,7 +470,7 @@ To be used in hook functions."
|
||||
;; Emacs 21 has no buffer file name for directory edits.
|
||||
;; so we need to add these hacks in.
|
||||
(eq major-mode 'dired-mode)
|
||||
(eq major-mode 'vc-dired-mode))
|
||||
(eq major-mode 'vc-dir-mode))
|
||||
(ede-minor-mode 1)))
|
||||
|
||||
(define-minor-mode ede-minor-mode
|
||||
@ -481,7 +481,7 @@ controlled project, then this mode is activated automatically
|
||||
provided `global-ede-mode' is enabled."
|
||||
:group 'ede
|
||||
(cond ((or (eq major-mode 'dired-mode)
|
||||
(eq major-mode 'vc-dired-mode))
|
||||
(eq major-mode 'vc-dir-mode))
|
||||
(ede-dired-minor-mode (if ede-minor-mode 1 -1)))
|
||||
(ede-minor-mode
|
||||
(if (not ede-constructing)
|
||||
|
@ -534,7 +534,7 @@ can guess how to load the mode's definition.")
|
||||
'((defining-kbd-macro nil)
|
||||
(isearch-mode nil)
|
||||
(vc-mode nil)
|
||||
(vc-dired-mode nil)
|
||||
(vc-dir-mode nil)
|
||||
(erc-track-minor-mode nil)
|
||||
(savehist-mode nil))
|
||||
"Table mapping minor mode variables to minor mode functions.
|
||||
|
@ -3050,6 +3050,68 @@ instead."
|
||||
(backward-delete-char 1))
|
||||
(message "%s" (buffer-string)))))
|
||||
|
||||
|
||||
;;; Version control from dired
|
||||
|
||||
(declare-function vc-dir-unmark-all-files "vc-dir")
|
||||
(declare-function vc-dir-mark-files "vc-dir")
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-vc-next-action (verbose)
|
||||
"Do the next version control operation on marked files/directories.
|
||||
When only files are marked then call `vc-next-action' with the
|
||||
same value of the VERBOSE argument.
|
||||
When also directories are marked then call `vc-dir' and mark
|
||||
the same files/directories in the VC-Dir buffer that were marked
|
||||
in the Dired buffer."
|
||||
(interactive "P")
|
||||
(let* ((marked-files
|
||||
(dired-get-marked-files nil nil nil nil t))
|
||||
(mark-files
|
||||
(when (cl-some #'file-directory-p marked-files)
|
||||
;; Fix deficiency of Dired by adding slash to dirs
|
||||
(mapcar (lambda (file)
|
||||
(if (file-directory-p file)
|
||||
(file-name-as-directory file)
|
||||
file))
|
||||
marked-files))))
|
||||
(if mark-files
|
||||
(let ((transient-hook (make-symbol "vc-dir-mark-files")))
|
||||
(fset transient-hook
|
||||
(lambda ()
|
||||
(remove-hook 'vc-dir-refresh-hook transient-hook t)
|
||||
(vc-dir-unmark-all-files t)
|
||||
(vc-dir-mark-files mark-files)))
|
||||
(vc-dir-root)
|
||||
(add-hook 'vc-dir-refresh-hook transient-hook nil t))
|
||||
(vc-next-action verbose))))
|
||||
|
||||
(declare-function vc-compatible-state "vc")
|
||||
|
||||
(defun dired-vc-deduce-fileset (&optional state-model-only-files not-state-changing)
|
||||
(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 not-state-changing) (cl-some #'file-directory-p files))
|
||||
(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))
|
||||
(setq state (cdar only-files-list))
|
||||
;; Check that all files are in a consistent state, since we use that
|
||||
;; state to decide which operation to perform.
|
||||
(dolist (crt (cdr only-files-list))
|
||||
(unless (vc-compatible-state (cdr crt) state)
|
||||
(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"
|
||||
(car crt) (cdr crt) (caar only-files-list) state)))
|
||||
(setq only-files-list (mapcar 'car only-files-list))
|
||||
(when (and state (not (eq state 'unregistered)))
|
||||
(setq model (vc-checkout-model backend only-files-list))))
|
||||
(list backend files only-files-list state model)))
|
||||
|
||||
|
||||
(provide 'dired-aux)
|
||||
|
||||
;; Local Variables:
|
||||
|
@ -1870,6 +1870,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
|
||||
(define-key map "\177" 'dired-unmark-backward)
|
||||
(define-key map [remap undo] 'dired-undo)
|
||||
(define-key map [remap advertised-undo] 'dired-undo)
|
||||
(define-key map [remap vc-next-action] 'dired-vc-next-action)
|
||||
;; thumbnail manipulation (image-dired)
|
||||
(define-key map "\C-td" 'image-dired-display-thumbs)
|
||||
(define-key map "\C-tt" 'image-dired-tag-files)
|
||||
|
@ -696,6 +696,17 @@ share the same state."
|
||||
(vc-dir-mark-file crt)))
|
||||
(setq crt (ewoc-next vc-ewoc crt))))))))
|
||||
|
||||
(defun vc-dir-mark-files (mark-files)
|
||||
"Mark files specified by file names in the argument MARK-FILES.
|
||||
MARK-FILES should be a list of absolute filenames."
|
||||
(ewoc-map
|
||||
(lambda (filearg)
|
||||
(when (member (expand-file-name (vc-dir-fileinfo->name filearg))
|
||||
mark-files)
|
||||
(setf (vc-dir-fileinfo->marked filearg) t)
|
||||
t))
|
||||
vc-ewoc))
|
||||
|
||||
(defun vc-dir-unmark-file ()
|
||||
;; Unmark the current file and move to the next line.
|
||||
(let* ((crt (ewoc-locate vc-ewoc))
|
||||
@ -1193,7 +1204,8 @@ Throw an error if another update process is in progress."
|
||||
(if remaining
|
||||
(vc-dir-refresh-files
|
||||
(mapcar 'vc-dir-fileinfo->name remaining))
|
||||
(setq mode-line-process nil))))))))))))
|
||||
(setq mode-line-process nil)
|
||||
(run-hooks 'vc-dir-refresh-hook))))))))))))
|
||||
|
||||
(defun vc-dir-show-fileentry (file)
|
||||
"Insert an entry for a specific file into the current *VC-dir* listing.
|
||||
|
@ -1006,12 +1006,18 @@ Within directories, only files already under version control are noticed."
|
||||
|
||||
(declare-function vc-dir-current-file "vc-dir" ())
|
||||
(declare-function vc-dir-deduce-fileset "vc-dir" (&optional state-model-only-files))
|
||||
(declare-function dired-vc-deduce-fileset "dired-aux" (&optional state-model-only-files not-state-changing))
|
||||
|
||||
(defun vc-deduce-fileset (&optional observer allow-unregistered
|
||||
(defun vc-deduce-fileset (&optional not-state-changing
|
||||
allow-unregistered
|
||||
state-model-only-files)
|
||||
"Deduce a set of files and a backend to which to apply an operation.
|
||||
Return (BACKEND FILESET FILESET-ONLY-FILES STATE CHECKOUT-MODEL).
|
||||
|
||||
NOT-STATE-CHANGING if non-nil, means that the operation
|
||||
requesting the fileset doesn't intend to change VC state,
|
||||
such as printing the log or showing the diff.
|
||||
|
||||
If we're in VC-dir mode, FILESET is the list of marked files,
|
||||
or the directory if no files are marked.
|
||||
Otherwise, if in a buffer visiting a version-controlled file,
|
||||
@ -1025,14 +1031,12 @@ the FILESET-ONLY-FILES STATE and MODEL info. Otherwise, that
|
||||
part may be skipped.
|
||||
|
||||
BEWARE: this function may change the current buffer."
|
||||
;; FIXME: OBSERVER is unused. The name is not intuitive and is not
|
||||
;; documented. It's set to t when called from diff and print-log.
|
||||
(let (backend)
|
||||
(cond
|
||||
((derived-mode-p 'vc-dir-mode)
|
||||
(vc-dir-deduce-fileset state-model-only-files))
|
||||
((derived-mode-p 'dired-mode)
|
||||
(vc-dired-deduce-fileset state-model-only-files observer))
|
||||
(dired-vc-deduce-fileset state-model-only-files not-state-changing))
|
||||
((setq backend (vc-backend buffer-file-name))
|
||||
(if state-model-only-files
|
||||
(list backend (list buffer-file-name)
|
||||
@ -1048,7 +1052,7 @@ BEWARE: this function may change the current buffer."
|
||||
(derived-mode-p 'dired-mode)))))
|
||||
(progn ;FIXME: Why not `with-current-buffer'? --Stef.
|
||||
(set-buffer vc-parent-buffer)
|
||||
(vc-deduce-fileset observer allow-unregistered state-model-only-files)))
|
||||
(vc-deduce-fileset not-state-changing allow-unregistered state-model-only-files)))
|
||||
((and (derived-mode-p 'log-view-mode)
|
||||
(setq backend (vc-responsible-backend default-directory)))
|
||||
(list backend nil))
|
||||
@ -1065,32 +1069,6 @@ BEWARE: this function may change the current buffer."
|
||||
(list buffer-file-name))))
|
||||
(t (error "File is not under version control")))))
|
||||
|
||||
(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)
|
||||
(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
|
||||
(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
|
||||
;; state to decide which operation to perform.
|
||||
(dolist (crt (cdr only-files-list))
|
||||
(unless (vc-compatible-state (cdr crt) state)
|
||||
(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"
|
||||
(car crt) (cdr crt) (caar only-files-list) state)))
|
||||
(setq only-files-list (mapcar 'car only-files-list))
|
||||
(when (and state (not (eq state 'unregistered)))
|
||||
(setq model (vc-checkout-model backend only-files-list))))
|
||||
(list backend files only-files-list state model)))
|
||||
|
||||
(defun vc-ensure-vc-buffer ()
|
||||
"Make sure that the current buffer visits a version-controlled file."
|
||||
(cond
|
||||
|
Loading…
Reference in New Issue
Block a user