diff options
| author | Bozhidar Batsov <bozhidar@toptal.com> | 2026-04-27 07:48:07 +0000 |
|---|---|---|
| committer | Bozhidar Batsov <bozhidar@toptal.com> | 2026-04-27 07:48:07 +0000 |
| commit | fc8559850228f54efbc7ee4ea56b2e376cec5b04 (patch) | |
| tree | 840af3bf3617a5dad6e3234778c7a3729bcab034 | |
| parent | a55eeb2b1821c5252a5ea3d8c7c79728a42763fe (diff) | |
Persist disk cache in projectile-purge-dir-from-cache
`projectile-purge-file-from-cache' writes the updated file list to
disk under persistent caching; the directory variant only mutated
the in-memory hash, so the purged subtree would reappear on the
next Emacs session. Mirror the persistence step here.
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | projectile.el | 10 | ||||
| -rw-r--r-- | test/projectile-test.el | 34 |
3 files changed, 41 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f0cd36..298727c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ * Fix `projectile-cache-current-file` calling `projectile-project-root` twice instead of reusing the already-resolved value. * Fix `projectile-load-project-cache` not recording a cache time, which combined with `projectile-files-cache-expire` made the TTL check immediately re-evict freshly loaded data — every call ended up re-reading the cache file from disk and the data was never reindexed. The cache file's mtime is now used to seed `projectile-projects-cache-time`. * Fix `projectile-load-project-cache` storing nil in cache on corrupt/empty cache files, preventing future reload attempts. +* Fix `projectile-purge-dir-from-cache` only updating the in-memory cache; with persistent caching the purged directory's files would reappear on the next session. The on-disk cache is now updated as well, matching the behavior of `projectile-purge-file-from-cache`. * Fix `projectile--cmake-command-presets` using `mapcar` instead of `mapcan`, producing nested lists for included presets. * Fix `projectile--eat` ignoring the `new-process` argument when generating buffer names. * Fix `projectile-check-vcs-status` hanging indefinitely by adding a 30-second timeout to its busy-wait loop. diff --git a/projectile.el b/projectile.el index 977860e..f81133d 100644 --- a/projectile.el +++ b/projectile.el @@ -1261,10 +1261,12 @@ The cache is created both in memory and on the hard drive." (projectile-current-project-dirs) :caller 'projectile-read-directory))) (let* ((project-root (projectile-project-root)) - (project-cache (gethash project-root projectile-projects-cache))) - (puthash project-root - (seq-remove (lambda (str) (string-prefix-p dir str)) project-cache) - projectile-projects-cache))) + (project-cache (gethash project-root projectile-projects-cache)) + (new-cache (seq-remove (lambda (str) (string-prefix-p dir str)) + project-cache))) + (puthash project-root new-cache projectile-projects-cache) + (when (projectile-persistent-cache-p) + (projectile-serialize new-cache (projectile-project-cache-file project-root))))) (defun projectile-file-cached-p (file project) "Check if FILE is already in PROJECT cache." diff --git a/test/projectile-test.el b/test/projectile-test.el index e21effb..9e4c358 100644 --- a/test/projectile-test.el +++ b/test/projectile-test.el @@ -3232,6 +3232,40 @@ projectile-process-current-project-buffers-current to have similar behaviour" ;; projectile-serialize should be called with the updated list, not the stale one (expect 'projectile-serialize :to-have-been-called-with '("foo.el" "baz.el") "/tmp/cache.eld")))) +(describe "projectile-purge-dir-from-cache" + (it "removes files under the directory from the in-memory cache" + (let ((projectile-projects-cache (make-hash-table :test 'equal)) + (projectile-enable-caching t)) + (puthash "/project/" + '("src/foo.el" "src/sub/bar.el" "test/baz.el") + projectile-projects-cache) + (spy-on 'projectile-project-root :and-return-value "/project/") + (projectile-purge-dir-from-cache "src/") + (expect (gethash "/project/" projectile-projects-cache) + :to-equal '("test/baz.el")))) + (it "serializes the updated cache when persistent caching is enabled" + (let ((projectile-projects-cache (make-hash-table :test 'equal)) + (projectile-enable-caching 'persistent)) + (puthash "/project/" + '("src/foo.el" "src/sub/bar.el" "test/baz.el") + projectile-projects-cache) + (spy-on 'projectile-project-root :and-return-value "/project/") + (spy-on 'projectile-serialize) + (spy-on 'projectile-project-cache-file :and-return-value "/tmp/cache.eld") + (projectile-purge-dir-from-cache "src/") + (expect 'projectile-serialize + :to-have-been-called-with '("test/baz.el") "/tmp/cache.eld"))) + (it "does not touch disk when persistent caching is disabled" + (let ((projectile-projects-cache (make-hash-table :test 'equal)) + (projectile-enable-caching t)) + (puthash "/project/" + '("src/foo.el" "test/baz.el") + projectile-projects-cache) + (spy-on 'projectile-project-root :and-return-value "/project/") + (spy-on 'projectile-serialize) + (projectile-purge-dir-from-cache "src/") + (expect 'projectile-serialize :not :to-have-been-called)))) + (describe "projectile-default-generic-command" (it "returns a string command as-is" (let ((projectile-project-types '((test-type compile-command "make")))) |
