branch: elpa/magit commit a64f246f71ea61f0dec5263ef65b27ac3ef29d6f Author: Jonas Bernoulli <jo...@bernoul.li> Commit: Jonas Bernoulli <jo...@bernoul.li>
magit-discard: On "Untracked files" delete exactly the listed files Use the same code to generate a list of untracked fils, when `magit-discard' is invoked on the "Untracked files" section as was used to populate the list of files displayed in that section. We should do that even if it weren't for the following issue, but that is how we noticed something had to be done. Contrary to what the documentation claims, "git ls-files --other --directory --exclude-standard" does not honor ".gitignore" from sub-directories. Closes #5405. --- CHANGELOG | 6 ++++++ lisp/magit-apply.el | 3 +-- lisp/magit-git.el | 35 +++++++++++++++++++++++++++++++++++ lisp/magit-status.el | 21 ++------------------- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7ca944d60c..4950331256 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,6 +11,12 @@ Bugfixes: - Refreshing was skipped after discarding all untracked files. +- When sub-directories contain ".gitignore" files, then invoking + ~magit-discard~ on the "Untracked files" section did not necessarily + remove the same set of files as listed in that section. (At least + it did show the files, which would be removed, in the confirmation + prompt.) #5405 + * v4.3.7 2025-07-01 - Refreshing a buffer causes its content to be recreated, which can diff --git a/lisp/magit-apply.el b/lisp/magit-apply.el index 7584e89c49..9a52cc4655 100644 --- a/lisp/magit-apply.el +++ b/lisp/magit-apply.el @@ -500,8 +500,7 @@ of a side, then keep that side without prompting." (defun magit-discard-untracked () (magit-discard-files--delete - (magit-with-toplevel - (magit-untracked-files nil nil "--directory")) + (magit-with-toplevel (magit-list-untracked-files)) nil) (magit-refresh)) diff --git a/lisp/magit-git.el b/lisp/magit-git.el index 2e6a14c520..9ff3fbeff9 100644 --- a/lisp/magit-git.el +++ b/lisp/magit-git.el @@ -63,6 +63,9 @@ (defvar magit-this-error) (defvar magit-process-error-message-regexps) +;; From `magit-status'. +(defvar magit-status-show-untracked-files) + (eval-when-compile (cl-pushnew 'orig-rev eieio--known-slot-names) (cl-pushnew 'number eieio--known-slot-names)) @@ -1069,10 +1072,42 @@ tracked file." (magit-list-files "--cached" args)) (defun magit-untracked-files (&optional all files &rest args) + "Return a list of untracked files. + +Note that when using \"--directory\", the rules from \".gitignore\" +files from sub-directories are ignore, which is probably a Git bug. +See also `magit-list-untracked-files', which does not have this +issue." (magit-list-files "--other" args (and (not all) "--exclude-standard") "--" files)) +(defun magit-list-untracked-files (&optional files) + "Return a list of untracked files. + +List files if `magit-status-show-untracked-files' is non-nil, but also +take the local value of Git variable `status.showUntrackedFiles' into +account. The local value of the Lisp variable takes precedence over the +local value of the Git variable. The global value of the Git variable +is always ignored. + +See also `magit-untracked-files'." + (and-let* + ((value (or (and (local-variable-p 'magit-status-show-untracked-files) + magit-status-show-untracked-files) + (pcase (magit-get "--local" "status.showUntrackedFiles") + ((or "no" "off" "false" "0") 'no) + ((or "yes" "on" "true" "1") t) + ("all" 'all)) + magit-status-show-untracked-files)) + ((not (eq value 'no)))) + (mapcan (##and (eq (aref % 0) ??) + (list (substring % 3))) + (apply #'magit-git-items "status" "-z" "--porcelain" + (format "--untracked-files=%s" + (if (eq value 'all) "all" "normal")) + "--" files)))) + (defun magit-ignored-files (&rest args) (magit-list-files "--others" "--ignored" "--exclude-standard" args)) diff --git a/lisp/magit-status.el b/lisp/magit-status.el index f4d70d1099..b002776631 100644 --- a/lisp/magit-status.el +++ b/lisp/magit-status.el @@ -752,31 +752,14 @@ remote in alphabetic order." magit-insert-assume-unchanged-files) (defun magit-insert-untracked-files () - "Maybe insert list of untracked files. + "Maybe insert a list of untracked files. List files if `magit-status-show-untracked-files' is non-nil, but also take the local value of Git variable `status.showUntrackedFiles' into account. The local value of the Lisp variable takes precedence over the local value of the Git variable. The global value of the Git variable is always ignored." - (when-let* - ((value (or (and (local-variable-p 'magit-status-show-untracked-files) - magit-status-show-untracked-files) - (pcase (magit-get "--local" "status.showUntrackedFiles") - ((or "no" "off" "false" "0") 'no) - ((or "yes" "on" "true" "1") t) - ("all" 'all)) - magit-status-show-untracked-files)) - ((not (eq value 'no)))) - (magit-insert-files - 'untracked - (lambda (files) - (mapcan (##and (eq (aref % 0) ??) - (list (substring % 3))) - (apply #'magit-git-items "status" "-z" "--porcelain" - (format "--untracked-files=%s" - (if (eq value 'all) "all" "normal")) - "--" files)))))) + (magit-insert-files 'untracked #'magit-list-untracked-files)) (defun magit-insert-tracked-files () "Insert a list of tracked files.