Skip to content

Honor Projectile's ignore rules under alien indexing#2104

Merged
bbatsov merged 8 commits into
masterfrom
feature/alien-honors-ignores
Jul 21, 2026
Merged

Honor Projectile's ignore rules under alien indexing#2104
bbatsov merged 8 commits into
masterfrom
feature/alien-honors-ignores

Conversation

@bbatsov

@bbatsov bbatsov commented Jul 20, 2026

Copy link
Copy Markdown
Owner

alien is the default indexing method and it applied none of Projectile's ignore rules - not the globally-ignored files/dirs/suffixes, not the - entries of a .projectile. We even shipped a warning whose only job was to say the dirconfig was being bypassed.

Post-filtering the output is what hybrid already does, so instead the rules are handed to the tool: exclude pathspecs for git ls-files, -E globs for fd. Tools that can't express exclusions (svn, fossil, bzr, darcs, pijul, plain find) get their output filtered in Lisp. projectile-alien-honors-ignores turns it all off.

Two follow-on changes fell out of testing it against native: + keep and ! unignore entries stay hybrid/native only (no tool equivalent), and ignore matching is now case-sensitive everywhere - native/hybrid used to fold case, which fd can't reproduce at all.

Alien projects will list fewer files after this. That's the point, but it's the kind of change worth knowing about.

bbatsov added 4 commits July 20, 2026 16:17
Alien indexing delegated the walk to an external tool and then did
nothing else, so none of Projectile's ignore configuration applied:
not the globally-ignored files/directories/suffixes, and not the `-'
entries of a project's .projectile. This was a long-standing source of
confusion - enough that we shipped a warning whose only job was to tell
people their .projectile was being bypassed.

Rather than post-filtering the output (which is what hybrid does, and
would collapse the two methods into one), push the rules down into the
tool itself: git ls-files takes `:(exclude,glob)' pathspecs and fd takes
repeated `-E' globs, so the filtering still happens outside Emacs and
alien stays fast. The few tools that can't express exclusions at all
(svn, fossil, bzr, darcs, pijul and the plain find fallback) fall back
to filtering the output in Lisp, so behaviour is uniform either way.
Git submodule listings run their own ls-files that never saw our
exclusions, so those get the Lisp pass too.

The new `projectile-alien-honors-ignores' opts out and restores the 3.2
behaviour. The exclusions also ride on the command published by
projectile-project-files-producer, so external finders built on the seam
show the same file set projectile-find-file does.

Dirconfig `+' keep and `!' unignore entries can't be expressed as tool
exclusions and remain hybrid/native only.

The acceptance test builds a real git repo and asserts alien and hybrid
produce the same file set. The warning and its option are gone.
The manual's indexing comparison table said alien honored none of them,
and ignoring.adoc opened with a warning that .projectile is ignored
under alien. Both are now wrong. Split the dirconfig row in two, since
`-` entries apply everywhere but `+`/`!` are still hybrid/native only.
Found by differentially testing alien against native - which is the
real oracle here, since native applies the rules directly in Lisp.
Comparing alien to hybrid (as the acceptance test did) can't catch a
mistranslation, because both start from the same external listing.

- Don't push the rules down under hybrid. Both methods share
  projectile-dir-files-alien, so hybrid was getting the exclusions on
  the command *and* running its own filter afterwards, which silently
  gave it alien's semantics wherever the two differ: a bare
  projectile-globally-ignored-directories entry is top-level-only under
  hybrid but any-depth under alien, so hybrid quietly started dropping
  nested matches. Hybrid filters its own output and needs no push-down.

- Strip the `*' marker from globally ignored directory names. A leading
  `*' there means "at any depth", it is not a wildcard, so passing it
  to a glob matcher made `*.osc' also match `foo.osc'. This also fixes
  the same latent bug in the globs handed to project.el's
  project-ignores and to the ripgrep search path, which shared the
  translation.

Adds a native/alien parity spec covering globs, directory patterns and
`?' wildcards, plus regressions for both fixes. Documents which tools
push the rules down and which get their output filtered, and the
any-depth difference from hybrid.
ENSIME was archived in 2018 and .eunit is a rebar2 artifact, so both
were pure noise - and now that the ignore rules are handed to the
external indexing tool, every stale entry is an argument on every
indexing command. The rest of the list earns its place: the VCS
metadata directories all correspond to a VCS Projectile supports, and
.idea/.vscode/.tox/.stack-work/.ccls-cache/.clangd are all current.
@bbatsov

bbatsov commented Jul 20, 2026

Copy link
Copy Markdown
Owner Author

Trimmed .ensime_cache and .eunit from the default ignored dirs, and added a table to indexing.adoc for which tools take the exclusions and which get filtered in Lisp.

Comparing alien against native (not hybrid - both start from the same listing, so the original test proved nothing) turned up two bugs: hybrid was getting the exclusions pushed down too, and a * in projectile-globally-ignored-directories was read as a wildcard when it's really an "any depth" marker. Both fixed.

Separately: native treats *tmp as a literal dir name while hybrid strips the *, and ignoring.adoc claims they match. Left alone, probably wants its own issue.

bbatsov added 2 commits July 20, 2026 18:27
native and hybrid fold case (string-suffix-p's IGNORE-CASE argument, and
case-fold-search defaulting to t for the dirconfig regexps); git
pathspecs and fd --exclude do not. Worth stating plainly until we
decide which of the two behaviours is the one we actually want.
native and hybrid folded case: string-suffix-p was called with its
IGNORE-CASE argument for the ignored suffixes, and the pattern matching
went through string-match-p, which honours case-fold-search - t by
default. So `.elc' also hid BUILD.ELC. git pathspecs and fd --exclude
have no equivalent (fd can't be made case-insensitive per-exclude at
all), which left the three methods disagreeing once alien started
honouring the rules.

Rather than reproduce the folding in the tools, drop it: pin
case-fold-search off around the ignore matchers and stop passing
IGNORE-CASE to string-suffix-p. Case-sensitive is also the less
surprising reading on a case-sensitive filesystem.

The one spec that pinned the old behaviour (foo.tar.GZ removed by a
`.tar.gz' entry) dates to 2017 and looks incidental to the change it
rode in on - that commit was about treating the entries as suffixes at
all, not about case. Updated, with explicit specs for both matchers.
@bbatsov

bbatsov commented Jul 20, 2026

Copy link
Copy Markdown
Owner Author

Made ignore matching case-sensitive everywhere instead of teaching the tools to fold case. git can do it with icase pathspecs but fd --exclude can't at all, and projectile-git-use-fd defaults on when fd is installed - so replicating it would make the file set depend on whether fd is on PATH.

The folding was incidental anyway: string-suffix-p called with IGNORE-CASE, and string-match-p inheriting case-fold-search. One spec pinned the old behaviour (foo.tar.GZ removed by .tar.gz); it comes from f866041 in 2017, which was about treating the entries as suffixes at all, so the spec got updated rather than the behaviour kept.

bbatsov added 2 commits July 21, 2026 08:22
One sentence per entry, with bullets for the two that genuinely need
them, instead of a paragraph each.
@bbatsov
bbatsov merged commit 776b453 into master Jul 21, 2026
5 checks passed
@bbatsov
bbatsov deleted the feature/alien-honors-ignores branch July 21, 2026 05:45
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