branch: elpa/magit
commit 5e364d2ff3eb9fb47ca9fcc7f748a984f704401d
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>
Speed up Git's part in listing files in status buffer
In [1: 83d89ee5bb] we did speed up Magit's part in this task, but also
removed optimization used to speed up Git's part. Bring those back.
Also respect all local values of `status.showUntrackedFiles' again.
Closes #5298.
1: 2025-01-27 83d89ee5bb1c488544bae60d52f7ee1987b6449e
Speed up and simplify listing files in status buffer
---
docs/magit.org | 24 ++++++++++++++++------
docs/magit.texi | 29 ++++++++++++++++++++------
lisp/magit-status.el | 57 ++++++++++++++++++++++++++++++++++------------------
3 files changed, 78 insertions(+), 32 deletions(-)
diff --git a/docs/magit.org b/docs/magit.org
index f9752ea5238..f5c190ba843 100644
--- a/docs/magit.org
+++ b/docs/magit.org
@@ -2271,25 +2271,37 @@ These functions honor the buffer's file filter, which
can be set using
This option controls whether the above function inserts a list of
untracked files in the status buffer.
+ - If ~nil~, do not list any untracked files.
+ - If ~t~, list untracked files, but if a directory does not contain any
+ untracked files, then only list that directory, not the contained
+ untracked files.
+ - If ~all~, then list each individual untracked files. This is can be
+ very slow and is discouraged.
+
+ The corresponding values for the Git variable are "no", "normal"
+ and "all".
+
To disable listing untracked files in a specific repository only,
add the following to ~.dir-locals.el~:
#+begin_src emacs-lisp
((magit-status-mode
- (magit-status-show-untracked-files . \"no\")))
+ (magit-status-show-untracked-files . "no")))
#+end_src
Alternatively (and mostly for historic reasons), it is possible to
- use ~git config~ to disable listing files for a specific repository,
- using:
+ use ~git config~ to set the repository-local value:
#+begin_src shell-script
git config set --local status.showUntrackedFiles no
#+end_src
- This does *not* override the (if any) local value of this Lisp variable.
- It also is not possible to use the Git variable to enable listing files
- (in case the global value of this variable is nil).
+ This does *not* override the (if any) local value of this Lisp variable,
+ but it does override its global value.
+
+ See the last section in the git-status(1) manpage, to speed up the part
+ of the work Git is responsible for. Turning that list into sections is
+ also not free, so Magit only lists ~magit-status-file-list-limit~ files.
- User Option: magit-status-file-list-limit ::
diff --git a/docs/magit.texi b/docs/magit.texi
index c51b44e2da6..5f62c126aac 100644
--- a/docs/magit.texi
+++ b/docs/magit.texi
@@ -2653,25 +2653,42 @@ actually does so, depends on the option described next.
This option controls whether the above function inserts a list of
untracked files in the status buffer.
+@itemize
+@item
+If @code{nil}, do not list any untracked files.
+@item
+If @code{t}, list untracked files, but if a directory does not contain any
+untracked files, then only list that directory, not the contained
+untracked files.
+@item
+If @code{all}, then list each individual untracked files. This is can be
+very slow and is discouraged.
+@end itemize
+
+The corresponding values for the Git variable are "no", "normal"
+and "all".
+
To disable listing untracked files in a specific repository only,
add the following to @code{.dir-locals.el}:
@lisp
((magit-status-mode
- (magit-status-show-untracked-files . \"no\")))
+ (magit-status-show-untracked-files . "no")))
@end lisp
Alternatively (and mostly for historic reasons), it is possible to
-use @code{git config} to disable listing files for a specific repository,
-using:
+use @code{git config} to set the repository-local value:
@example
git config set --local status.showUntrackedFiles no
@end example
-This does @strong{not} override the (if any) local value of this Lisp variable.
-It also is not possible to use the Git variable to enable listing files
-(in case the global value of this variable is nil).
+This does @strong{not} override the (if any) local value of this Lisp variable,
+but it does override its global value.
+
+See the last section in the git-status(1) manpage, to speed up the part
+of the work Git is responsible for. Turning that list into sections is
+also not free, so Magit only lists @code{magit-status-file-list-limit} files.
@end defopt
@defopt magit-status-file-list-limit
diff --git a/lisp/magit-status.el b/lisp/magit-status.el
index d06a32264c1..952cca50827 100644
--- a/lisp/magit-status.el
+++ b/lisp/magit-status.el
@@ -145,6 +145,16 @@ The functions which respect this option are
(defcustom magit-status-show-untracked-files t
"Whether to list untracked files in the status buffer.
+- If nil, do not list any untracked files.
+- If t, list untracked files, but if a directory does not contain any
+ untracked files, then only list that directory, not the contained
+ untracked files.
+- If all, then list each individual untracked files. This is can be
+ very slow and is discouraged.
+
+The corresponding values for the Git variable are \"no\", \"normal\"
+and \"all\".
+
To disable listing untracked files in a specific repository only, add
the following to \".dir-locals.el\":
@@ -152,13 +162,16 @@ the following to \".dir-locals.el\":
(magit-status-show-untracked-files . \"no\")))
Alternatively (and mostly for historic reasons), it is possible to use
-`git-config' to disable listing files for a specific repository, using:
+`git-config' to set the repository-local value:
git config set --local status.showUntrackedFiles no
-This does *not* override the (if any) local value of this Lisp variable.
-It also is not possible to use the Git variable to enable listing files
-\(in case the global value of this variable is nil)."
+This does *not* override the (if any) local value of this Lisp variable,
+but it does override its global value.
+
+See the last section in the git-status(1) manpage, to speed up the part
+of the work Git is responsible for. Turning that list into sections is
+also not free, so Magit only lists `magit-status-file-list-limit' files."
:package-version '(magit . "4.2.1")
:group 'magit-status
:type 'boolean
@@ -737,24 +750,28 @@ remote in alphabetic order."
List files if `magit-status-show-untracked-files' is non-nil, but also
take the local value of Git variable `status.showUntrackedFiles' into
-account. If the Lisp variable has no local value and the local value
-of the Git variable is \"no\" or \"false\", then do not insert files. In
-all other cases only the Lisp variable matters.
-
-Honor the buffer's file filter, which can be set using \"D - -\"."
- (when-let
+account. The local value of the Lisp variable takes precedence over
+the local value of the Git variable. The global value of the Git is
+always ignored."
+ (when-let*
((value (or (and (local-variable-p 'magit-status-show-untracked-files)
magit-status-show-untracked-files)
- (and (not (member
- (magit-get "--local" "status.showUntrackedFiles")
- '("no" "false")))
- magit-status-show-untracked-files))))
- (if (eq value t)
- (magit-insert-files 'untracked
- (lambda (args) (magit-untracked-files nil (cdr
args))))
- (display-warning 'magit-insert-untracked-files
- (format "Value should be a lisp boolean, not %S." value)
- :error))))
+ (pcase (magit-get "--local" "status.showUntrackedFiles")
+ ((or "no" "false") 'no)
+ ("all" 'all)
+ (_ t))
+ magit-status-show-untracked-files))
+ ((not (eq value 'no))))
+ (magit-insert-files
+ 'untracked
+ (lambda (files)
+ (mapcan (lambda (line)
+ (and (eq (aref line 0) ??)
+ (list (substring line 3))))
+ (apply #'magit-git-items "status" "-z" "--porcelain"
+ (format "--untracked-files=%s"
+ (if (eq value 'all) "all" "normal"))
+ "--" files))))))
(defun magit-insert-tracked-files ()
"Insert a list of tracked files.