aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorEdmund Jorgensen <tomheon@gmail.com>2022-06-26 02:55:44 -0400
committerGitHub <noreply@github.com>2022-06-26 09:55:44 +0300
commit78be7717cd7e81f039c7206de9ebef20f845d29f (patch)
tree534a062c77060807da3f1eb338fba158feb7731e /test
parent4d6da873ae54dbf6043b015efd9b737e2ce152c6 (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.el38
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"