diff options
| author | Edmund Jorgensen <tomheon@gmail.com> | 2022-06-26 02:55:44 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-26 09:55:44 +0300 |
| commit | 78be7717cd7e81f039c7206de9ebef20f845d29f (patch) | |
| tree | 534a062c77060807da3f1eb338fba158feb7731e /test | |
| parent | 4d6da873ae54dbf6043b015efd9b737e2ce152c6 (diff) | |
[Fix #1755] Cache failure to find project root (#1779)
When `projectile-project-root` was unable to find a project root for a
directory, it would not cache the negative result, so future invocations would
repeat the (often expensive) search for a project root every time.
With this change, `projectile-project-root` caches failure to find a project
root, when that failure is expected to be permanent, and consults that cache
for speed on subsequent invocations. "Expected to be permanent" means that
either we're trying to find the project root of a local directory, or we're
successfully connected to a remote directory via TRAMP. If the directory isn't
local, but we can't connect to it, we consider that a transient failure and
don't cache it.
Under the hood, this change uses the same `projectile-project-root-cache`
that's used to cache successful attempts to find a project root, but with a new
key `projectilerootless-{dir}`. This should allow cache invalidation to work
as expected.
Diffstat (limited to 'test')
| -rw-r--r-- | test/projectile-test.el | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/test/projectile-test.el b/test/projectile-test.el index a83268c..9760e78 100644 --- a/test/projectile-test.el +++ b/test/projectile-test.el @@ -691,7 +691,43 @@ Just delegates OPERATION and ARGS for all operations except for`shell-command`'. projectile-root-top-down projectile-root-top-down-recurring))) (projectile-test-should-root-in "projectA/src/" "projectA/src/") - (projectile-test-should-root-in "projectA/src/" "projectA/src/html")))))) + (projectile-test-should-root-in "projectA/src/" "projectA/src/html"))))) + + (it "caches permanent failure to find a project root" + (projectile-test-with-sandbox + (projectile-test-with-files + ("projectA/src/") + (let* ((projectile-project-root-functions '()) + (dir "projectA/src") + (cache-key (format "projectilerootless-%s" dir)) + (projectile-project-root-cache (make-hash-table :test 'equal))) + (expect (gethash cache-key projectile-project-root-cache) :to-be nil) + (expect (projectile-project-root dir) :to-be nil) + ;; now that this has run once, the cache should be populated with 'none + (expect (gethash cache-key projectile-project-root-cache) :to-be 'none) + ;; but projectile-project-root should still return nil + (expect (projectile-project-root dir) :to-be nil))))) + + (it "does not cache transitory failure to find a project root" + (projectile-test-with-sandbox + (projectile-test-with-files + ("projectA/src/") + ;; hackish, but override file-remote-p for a moment, which is called in + ;; projectile-project-root with 1 argument to test if the file is remote, + ;; and 3 arguments to see if the file is connected. We want to return t + ;; when checking if remote, and nil when checking if connected. + (cl-letf (((symbol-function 'file-remote-p) + (lambda (&rest args) (eql 1 (length args))))) + (let* ((projectile-project-root-functions '()) + (dir "projectA/src") + (cache-key (format "projectilerootless-%s" dir)) + (projectile-project-root-cache (make-hash-table :test 'equal))) + (expect (gethash cache-key projectile-project-root-cache) :to-be nil) + (expect (projectile-project-root dir) :to-be nil) + ;; since the failure was transitory, there should be nothing cached + (expect (gethash cache-key projectile-project-root-cache) :to-be nil) + ;; and projectile-project-root should still return nil + (expect (projectile-project-root dir) :to-be nil))))))) (describe "projectile-file-exists-p" (it "returns t if file exists" |
