Honor gitignore negation patterns for directories - #1564
Open
cryo2010 wants to merge 1 commit into
Open
Conversation
The gitignore idiom for ignoring extensionless files:
*
!*.*
!*/
caused ag to skip the entire repo. Directories were matched against
ignore patterns by plain name first, so * ignored them before the
trailing-slash form that !*/ can match was ever consulted.
Make path_ignore_search return a tri-state: 1 (ignored), -1 (explicitly
un-ignored by an invert pattern), 0 (no match). Invert patterns are now
checked before all other pattern classes at the same level, and an
explicit un-ignore stops the walk up the parent ignore chain, matching
git's deepest-match precedence. filename_filter evaluates a directory's
plain and trailing-slash forms together, letting an invert match on
either form win.
Fixes ggreer#1563
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1563
Problem
The common .gitignore idiom for ignoring extensionless files (POSIX binaries):
caused ag to skip essentially the entire repo. Git interprets it as "ignore everything, then un-ignore anything with a dot and all directories," but ag matched directories against ignore patterns by plain name first, so
*ignored them before the trailing-slash form that!*/can match was ever consulted. Negation matches also could not take precedence:path_ignore_searchreturned the same0for "invert pattern matched" and "nothing matched."Fix
path_ignore_searchnow returns a tri-state:1(ignored),-1(explicitly un-ignored by an invert pattern),0(no match). Invert patterns are checked before the other pattern classes at the same level, and the ackmate filter result is normalized to0/1so it does not collide with the new-1.filename_filterevaluates a directory's plain and trailing-slash forms together, so an invert match on either form wins. An explicit un-ignore stops the walk up the parent ignore chain, matching git's deepest-match precedence.Testing
tests/ignore_invert_dir.tcovering the idiom above; it fails on master and passes with this change.git status --porcelain --ignoredon a test repo with nested directories and extensionless files at multiple depths: ag's results now match git's ignore semantics exactly.