diff options
| author | Bozhidar Batsov <bozhidar@batsov.dev> | 2026-02-13 12:33:18 +0200 |
|---|---|---|
| committer | Bozhidar Batsov <bozhidar@batsov.dev> | 2026-02-13 12:33:18 +0200 |
| commit | 3c287cd1b4a5289e6342361471c11685e3f168ab (patch) | |
| tree | fd0c461d136ec3e9fadd14b071fe73a2c4f7faa4 | |
| parent | ca324b78471201dca4a7b1dc41ab7b716b1cc1c9 (diff) | |
Prevent directories from matching file-type project root markers
On case-insensitive filesystems (macOS default), a ~/workspace directory
matches the "WORKSPACE" Bazel marker because file-exists-p returns t for
both files and directories. This causes the home directory to be falsely
detected as a Bazel project root, leading to severe performance issues.
Add a (not (file-directory-p ...)) guard in projectile-root-top-down so
that only regular files can satisfy file-type marker checks.
Fixes #1961
| -rw-r--r-- | CHANGELOG.md | 4 | ||||
| -rw-r--r-- | projectile.el | 5 | ||||
| -rw-r--r-- | test/projectile-test.el | 11 |
3 files changed, 17 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f960f2..9f0ac7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ * [#1837](https://github.com/bbatsov/projectile/issues/1837): Add `eat` project terminal commands with keybindings `x x` and `x 4 x`. +### Bugs fixed + +* [#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). + ### Changes * [#1958](https://github.com/bbatsov/projectile/issues/1958): Exclude `.projectile-cache.eld` from search results (ripgrep/ag/grep) by default. diff --git a/projectile.el b/projectile.el index eed377a..7f0c581 100644 --- a/projectile.el +++ b/projectile.el @@ -1325,7 +1325,10 @@ Return the first (topmost) matched directory or nil if not found." (projectile-locate-dominating-file dir (lambda (dir) - (cl-find-if (lambda (f) (projectile-file-exists-p (projectile-expand-file-name-wildcard f dir))) + (cl-find-if (lambda (f) + (let ((expanded (projectile-expand-file-name-wildcard f dir))) + (and (projectile-file-exists-p expanded) + (not (file-directory-p expanded))))) (or list projectile-project-root-files))))) (defun projectile-root-marked (dir) diff --git a/test/projectile-test.el b/test/projectile-test.el index 4ebe3bd..33c50e4 100644 --- a/test/projectile-test.el +++ b/test/projectile-test.el @@ -629,9 +629,16 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. (expect (projectile-root-top-down "projectA/src/framework/lib" '(".git" "framework.conf")) :to-equal (expand-file-name "projectA/src/")) - (expect (projectile-root-top-down "projectA/src/html/" '(".svn")) + (expect (projectile-root-top-down "projectA/src/html/" '("index.html")) :to-equal - (expand-file-name "projectA/src/html/")))))) + (expand-file-name "projectA/src/html/"))))) + (it "does not match directories for file-type markers" + (projectile-test-with-sandbox + (projectile-test-with-files + ("projectA/workspace/" + "projectA/src/") + (expect (projectile-root-top-down "projectA/src/" '("workspace")) + :not :to-be-truthy))))) (describe "projectile-root-top-down-recurring" (it "identifies the root directory of a project by recurring top-down search" |
