branch: elpa/magit
commit 7ccff374d06df833a03bfd19bbce80e29833d29b
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>
magit-file-{untrack,rename,delete}: Support acting on directories
And `magit-do-async-shell-command' too.
Closes #5247.
---
docs/CHANGELOG.4 | 3 +++
lisp/magit-dired.el | 2 +-
lisp/magit-files.el | 35 +++++++++++++++++++++++++----------
3 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/docs/CHANGELOG.4 b/docs/CHANGELOG.4
index 6eddf40e88..fff3ab8972 100644
--- a/docs/CHANGELOG.4
+++ b/docs/CHANGELOG.4
@@ -28,6 +28,9 @@
- Added Git v2.55's new ~--graph-lane-limit~ to log menus. It is hidden
by default and not available when using an older Git. #5088
+- ~magit-file-untrack~, ~magit-file-rename~, ~magit-file-delete~ and
+ ~magit-do-async-shell-command~ can now act on directories. #5247
+
* v4.6.0 2026-07-01
The primary focus of this release are blob-visiting buffers. For
diff --git a/lisp/magit-dired.el b/lisp/magit-dired.el
index b00ee88a1d..85f58d1e02 100644
--- a/lisp/magit-dired.el
+++ b/lisp/magit-dired.el
@@ -102,7 +102,7 @@ for a repository."
"Open FILE with `dired-do-async-shell-command'.
Interactively, open the file at point."
(interactive (list (or (magit-file-at-point)
- (magit-read-file "Act on file"))))
+ (magit-read-file "Act on file" nil t))))
(require 'dired-aux)
(dired-do-async-shell-command
(dired-read-shell-command "& on %s: " current-prefix-arg (list file))
diff --git a/lisp/magit-files.el b/lisp/magit-files.el
index 5087470fbe..1abc036a27 100644
--- a/lisp/magit-files.el
+++ b/lisp/magit-files.el
@@ -638,7 +638,7 @@ staged as well as unstaged changes."
(if (magit-file-tracked-p (car files))
(magit-confirm-files 'untrack files "Untrack")
(user-error "Already untracked"))
- (list (magit-read-tracked-file "Untrack file"))))
+ (list (magit-read-tracked-file "Untrack file" t))))
current-prefix-arg))
(magit-with-toplevel
(magit-run-git "rm" "--cached" (and force "--force") "--" files)))
@@ -649,7 +649,7 @@ staged as well as unstaged changes."
NEWNAME may be a file or directory name. If FILE isn't tracked in
Git, fallback to using `rename-file'."
(interactive
- (let* ((file (magit-read-file "Rename file"))
+ (let* ((file (magit-read-file "Rename file" nil t))
(path (expand-file-name file (magit-toplevel))))
(list path (expand-file-name
(read-file-name (format "Move %s to destination: " file)
@@ -689,13 +689,16 @@ uncommitted changes. When the files aren't being tracked
in
Git, then fallback to using `delete-file'."
(interactive (list (if-let ((files (magit-region-values 'file t)))
(magit-confirm-files 'delete files "Delete")
- (list (magit-read-file "Delete file")))
+ (list (magit-read-file "Delete file" nil t)))
current-prefix-arg))
(if (magit-file-tracked-p (car files))
(magit-call-git "rm" (and force "--force") "--" files)
(let ((topdir (magit-toplevel)))
(dolist (file files)
- (delete-file (expand-file-name file topdir) t))))
+ (setq file (expand-file-name file topdir))
+ (if (file-directory-p file)
+ (delete-directory file t t)
+ (delete-file file t)))))
(magit-refresh))
;;;###autoload
@@ -721,18 +724,30 @@ Git, then fallback to using `delete-file'."
prompt files nil t nil 'magit-read-file-hist
(car (member (or default (magit-current-file)) files)))))
-(defun magit-read-file (prompt &optional tracked-only)
- (let ((choices (nconc (magit-list-files)
- (and (not tracked-only)
- (magit-untracked-files)))))
+(defun magit-read-file (prompt &optional tracked-only include-dirs)
+ (let* ((files (nconc (magit-list-files)
+ (and (not tracked-only)
+ (magit-untracked-files))))
+ (choices
+ (if include-dirs
+ (let (dirs)
+ (dolist (file files)
+ (while (and file
+ (setq file (file-name-parent-directory file))
+ (not (equal file "./")))
+ (if (member file dirs)
+ (setq file nil)
+ (push file dirs))))
+ (sort (nconc dirs files) #'string<))
+ files)))
(magit-completing-read
prompt choices nil t nil nil
(car (member (or (magit-section-value-if '(file submodule))
(magit-file-relative-name nil tracked-only))
choices)))))
-(defun magit-read-tracked-file (prompt)
- (magit-read-file prompt t))
+(defun magit-read-tracked-file (prompt &optional include-dirs)
+ (magit-read-file prompt t include-dirs))
(defun magit-read-unmerged-file (&optional prompt)
(let ((current (magit-current-file))