Skip to content

Codebase fixes round 2: TRAMP safety, safe-local-variable, hash table correctness#1987

Merged
bbatsov merged 9 commits intomasterfrom
feature/codebase-fixes-round2
Feb 28, 2026
Merged

Codebase fixes round 2: TRAMP safety, safe-local-variable, hash table correctness#1987
bbatsov merged 9 commits intomasterfrom
feature/codebase-fixes-round2

Conversation

@bbatsov
Copy link
Owner

@bbatsov bbatsov commented Feb 28, 2026

Second round of codebase fixes following the deep audit. Focuses on TRAMP robustness, correctness, and usability improvements.

Fixes:

  • projectile-update-project-type reset the type cache with wrong hash table :test (eql instead of equal)
  • projectile-find-file-hook-function ran buffer limiting on TRAMP buffers, risking hangs
  • projectile-compilation-dir used file-truename (resolves symlinks, slow on TRAMP) instead of expand-file-name
  • projectile-get-all-sub-projects used destructive nconc on returned data
  • Project settings variables lacked safe-local-variable predicates, causing prompts in .dir-locals.el

Performance:

  • Hash set for deleted file filtering in projectile-dir-files-alien (O(n+m) vs O(n*m))
  • Pass already-resolved project root through to projectile-detect-project-type

Includes 8 new test specs (218 total, all passing).

When called with :precedence, the function recreated the type cache
hash table without :test 'equal, defaulting to eql.  Since project
roots are strings, no cache key would ever match, causing perpetual
re-detection of project types until Emacs was restarted.
The buffer-limiting function was called before the file-remote-p guard
in projectile-find-file-hook-function, triggering expensive buffer
enumeration and file-truename calls on every remote file open.  Move
it inside the existing TRAMP guard.
file-truename resolves symlinks via synchronous I/O, which can hang
Emacs when the project is on a remote host via TRAMP.  expand-file-name
is sufficient here (it normalizes path components) and works safely
with remote paths.
Variables documented as "should be set via .dir-locals.el" were missing
safe-local-variable properties, causing Emacs to prompt for confirmation
every time they were encountered.  Add stringp for command and directory
variables, booleanp for the caching toggle.

Intentionally omit projectile-project-related-files-fn since it accepts
functions, which cannot be safely evaluated from dir-locals.
The deleted file check used member inside seq-remove, which is O(n*m)
where n is total files and m is deleted files.  Convert the deleted
list to a hash set for O(1) lookups, making the overall operation O(n).
nconc destructively modifies the list returned by
projectile-get-immediate-sub-projects, which could affect any caller
holding a reference to that list.  Use append for a non-destructive
alternative.
projectile-project-type already resolves the project root. Pass it
through to projectile-detect-project-type so it doesn't resolve it
a second time just for the cache key.
- Test that projectile-update-project-type resets cache with 'equal test
- Test safe-local-variable predicates for project settings variables
- Test that projectile-project-type passes project-root through to
  detect-project-type
@bbatsov bbatsov force-pushed the feature/codebase-fixes-round2 branch from 6dc3483 to 03a987b Compare February 28, 2026 08:15
@bbatsov bbatsov merged commit 97fa0b8 into master Feb 28, 2026
10 checks passed
@bbatsov bbatsov deleted the feature/codebase-fixes-round2 branch February 28, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant