Function: projectile-files-via-ext-command
projectile-files-via-ext-command is a byte-compiled function defined
in projectile.el.
Signature
(projectile-files-via-ext-command ROOT COMMAND &optional PATHSPECS)
Documentation
Get a list of relative file names in the project ROOT by executing COMMAND.
PATHSPECS, when non-nil, is a list of subdirectories (relative to
ROOT) appended to COMMAND as positional arguments. Each entry is
shell-quoted before being appended. All of the indexing commands
shipped with Projectile (git ls-files, fd, find, hg locate
etc.) accept additional path arguments at the end of the command
line; users with heavily customised commands that don't should
either not rely on + keep entries in .projectile or arrange
their command to accept positional paths.
If command is nil or an empty string, return nil.
This allows commands to be disabled.
When COMMAND exits non-zero but still produced output, that output is
used: external listers such as fd routinely exit non-zero on benign
conditions (e.g. an unreadable directory encountered mid-traversal)
while having listed everything else. A user-error is signalled only
when a non-zero exit produced no output at all, so a genuinely broken
command (most commonly a binary like fd or git missing on a remote
host) surfaces immediately instead of being mistaken for an empty
project. Either way COMMAND's stderr is captured into the
*projectile-files-errors* buffer.
Only text sent to standard output is taken into account.
Source Code
;; Defined in ~/.emacs.d/elpa/projectile-20260820.1509/projectile.el
(defun projectile-files-via-ext-command (root command &optional pathspecs)
"Get a list of relative file names in the project ROOT by executing COMMAND.
PATHSPECS, when non-nil, is a list of subdirectories (relative to
ROOT) appended to COMMAND as positional arguments. Each entry is
shell-quoted before being appended. All of the indexing commands
shipped with Projectile (`git ls-files', `fd', `find', `hg locate'
etc.) accept additional path arguments at the end of the command
line; users with heavily customised commands that don't should
either not rely on `+' keep entries in `.projectile' or arrange
their command to accept positional paths.
If `command' is nil or an empty string, return nil.
This allows commands to be disabled.
When COMMAND exits non-zero but still produced output, that output is
used: external listers such as `fd' routinely exit non-zero on benign
conditions (e.g. an unreadable directory encountered mid-traversal)
while having listed everything else. A `user-error' is signalled only
when a non-zero exit produced no output at all, so a genuinely broken
command (most commonly a binary like `fd' or `git' missing on a remote
host) surfaces immediately instead of being mistaken for an empty
project. Either way COMMAND's stderr is captured into the
`*projectile-files-errors*' buffer.
Only text sent to standard output is taken into account."
(when (and (stringp command) (not (string-empty-p command)))
(let* ((default-directory root)
;; A pipeline can't take the pathspecs; run it unrestricted and
;; filter its output below instead.
(pathspecs-on-command (and (projectile--command-accepts-pathspecs-p command)
pathspecs))
(full-command (projectile--ext-command-line command pathspecs-on-command))
(errors-file (make-temp-file "projectile-files-errors")))
(unwind-protect
(with-temp-buffer
;; `process-file-shell-command' goes through TRAMP for remote
;; roots and returns a reliable exit code. Stderr is collected
;; into a temp file and copied into `*projectile-files-errors*'
;; only when the command fails, so we don't pollute the buffer
;; on the happy path.
(let ((exit-code
(process-file-shell-command full-command nil
(list t errors-file)))
(files (projectile--ext-command-output-files)))
(when (and (numberp exit-code) (not (zerop exit-code)))
(let ((had-stderr (projectile--surface-ext-command-errors errors-file)))
(cond
;; Non-zero exit but we still got a listing: trust it. Only
;; mention it (quietly) when there was stderr worth seeing.
(files
(when had-stderr
(projectile--message
"`%s' exited with code %d but produced output; using it (see *projectile-files-errors*)"
full-command exit-code)))
;; Non-zero exit and nothing on stdout: a real failure.
(t
(user-error
"Projectile indexing command failed with exit code %d: %s\n\
See the *projectile-files-errors* buffer for details"
exit-code full-command)))))
(if pathspecs-on-command
files
(projectile--restrict-to-subdirs files pathspecs))))
(when (file-exists-p errors-file)
(delete-file errors-file))))))