Skip to content

Commit 4dbcda2

Browse files
committed
Filter deleted-but-unstaged files from git ls-files output (#1897)
When fd is unavailable or disabled, `git ls-files -zco --exclude-standard` returns files still tracked in the index even if deleted from disk. This causes projectile-dir-files-alien to list ghost files. Fix by running `git ls-files -zd` and removing those entries from the result.
1 parent 5560f08 commit 4dbcda2

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Bugs fixed
1010

11+
* [#1897](https://github.com/bbatsov/projectile/issues/1897): Filter deleted-but-unstaged files from `git ls-files` output in alien/hybrid indexing (when `fd` is not used).
1112
* [#1873](https://github.com/bbatsov/projectile/issues/1873): Skip unreadable directories during native indexing instead of aborting with a permission error.
1213
* [#1961](https://github.com/bbatsov/projectile/issues/1961): Prevent directories from matching file-type project root markers (e.g., a `workspace` directory no longer matches the `WORKSPACE` Bazel marker on case-insensitive filesystems).
1314
* [#1749](https://github.com/bbatsov/projectile/issues/1749): Strip `./` prefix from `fd` output in `projectile-files-via-ext-command`, fixing compatibility with older `fd` versions that don't support `--strip-cwd-prefix`.

projectile.el

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,10 +1539,21 @@ IGNORED-DIRECTORIES may optionally be provided."
15391539
(let ((vcs (projectile-project-vcs directory)))
15401540
(cond
15411541
((eq vcs 'git)
1542-
(nconc (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))
1543-
(projectile-get-sub-projects-files directory vcs)))
1542+
(let* ((files (nconc (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))
1543+
(projectile-get-sub-projects-files directory vcs)))
1544+
;; When using git ls-files (not fd), deleted but unstaged
1545+
;; files are still reported. Remove them.
1546+
(deleted (unless (and projectile-git-use-fd projectile-fd-executable)
1547+
(projectile-git-deleted-files directory))))
1548+
(if deleted
1549+
(seq-remove (lambda (f) (member f deleted)) files)
1550+
files)))
15441551
(t (projectile-files-via-ext-command directory (projectile-get-ext-command vcs))))))
15451552

1553+
(defun projectile-git-deleted-files (directory)
1554+
"Get a list of deleted but unstaged files in DIRECTORY."
1555+
(projectile-files-via-ext-command directory "git ls-files -zd"))
1556+
15461557
(defun projectile-get-ext-command (vcs)
15471558
"Determine which external command to invoke based on the project's VCS.
15481559
Fallback to a generic command when not in a VCS-controlled project."

test/projectile-test.el

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,30 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'.
532532
(let ((projectile-indexing-method 'hybrid))
533533
(expect (projectile-dir-files "/my/root/") :to-equal '("a/b/c" "a/d/e")))))
534534

535+
(describe "projectile-dir-files-alien"
536+
(it "excludes deleted-but-unstaged files when not using fd"
537+
(projectile-test-with-sandbox
538+
(projectile-test-with-files
539+
("project/"
540+
"project/.git/"
541+
"project/existing.txt")
542+
(let ((default-directory (file-truename (expand-file-name "project/")))
543+
(projectile-git-use-fd nil)
544+
(projectile-fd-executable nil)
545+
(projectile-indexing-method 'alien))
546+
;; Initialize a real git repo, commit a file, then delete it without staging
547+
(call-process "git" nil nil nil "init")
548+
(call-process "git" nil nil nil "config" "user.email" "test@test.com")
549+
(call-process "git" nil nil nil "config" "user.name" "Test")
550+
(call-process "git" nil nil nil "add" "existing.txt")
551+
(write-region "content" nil "deleted.txt")
552+
(call-process "git" nil nil nil "add" "deleted.txt")
553+
(call-process "git" nil nil nil "commit" "-m" "init")
554+
(delete-file "deleted.txt")
555+
(let ((files (projectile-dir-files-alien default-directory)))
556+
(expect files :to-contain "existing.txt")
557+
(expect files :not :to-contain "deleted.txt")))))))
558+
535559
(describe "projectile-index-directory"
536560
(it "skips unreadable directories"
537561
(unless (eq system-type 'windows-nt)

0 commit comments

Comments
 (0)