branch: elpa/magit
commit 5e364d2ff3eb9fb47ca9fcc7f748a984f704401d
Author: Jonas Bernoulli <jo...@bernoul.li>
Commit: Jonas Bernoulli <jo...@bernoul.li>

    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.

Reply via email to