Skip to content

Replace go-git gitignore matcher with custom implementation#99

Merged
andrew merged 7 commits intomainfrom
fix-gitignore-negation
Feb 9, 2026
Merged

Replace go-git gitignore matcher with custom implementation#99
andrew merged 7 commits intomainfrom
fix-gitignore-negation

Conversation

@andrew
Copy link
Contributor

@andrew andrew commented Feb 8, 2026

go-git's gitignore matcher doesn't handle negation patterns correctly. Repos with deny-by-default .gitignore patterns (/* then !.github/) cause DependenciesInWorkingDir and where to skip directory trees that should be visible, breaking diff on clean working trees.

Adds internal/gitignore package with a matcher that correctly implements gitignore semantics: last-match-wins, directory-only trailing slash, leading/middle slash anchoring, ** in all positions, and pattern scoping for nested .gitignore files. Includes a test that validates against git check-ignore directly.

Tested against ericcornelissen/ades@14ab252 which has a thorough deny-by-default .gitignore. Previously broken, now shows "No dependency changes" as expected.

Ref #98

@andrew andrew force-pushed the fix-gitignore-negation branch 4 times, most recently from a1186c6 to 686cbad Compare February 8, 2026 20:26
go-git's gitignore.Matcher doesn't handle negation patterns correctly.
Repos with deny-by-default .gitignore patterns (/* then !.github/) cause
DependenciesInWorkingDir and where to skip entire directory trees that
should be visible, breaking diff on clean working trees.

Add internal/gitignore package with a matcher that correctly implements
gitignore semantics: last-match-wins, directory-only trailing slash,
leading/middle slash anchoring, ** in all positions, and pattern scoping
for nested .gitignore files. Verified against git check-ignore.

Remove LoadIgnoreMatcher/IgnoreMatcher from repository.go. Add
GetExcludeDirs for configurable directory skipping via git config.

Ref #98
The "escaped wildcards" test case creates files named hello* and hello?
on disk, which Windows does not support. Skip this case on Windows since
it's a filesystem limitation, not a matcher bug.
npm lockfiles can contain the same package at multiple versions due to
dependency hoisting (e.g. ini@6.0.0 and ini@4.1.1). Both computeDiff
and AnalyzeCommit used single-value maps keyed by package name, so
duplicate versions collapsed to whichever was iterated last. When the
database and working tree paths iterated in different orders, this
produced phantom "modified" entries on clean workspaces.

Replace single-value maps with multi-maps in both locations:

- computeDiff: group by manifest:name, compare version sets when a
  package appears at multiple versions
- AnalyzeCommit: replace beforeByName/afterByName with multi-maps so
  PreviousRequirement reflects the actual replaced version

Fixes #53
Git's wildmatch supports POSIX character classes like [[:space:]],
[[:alpha:]], [[:digit:]] inside bracket expressions. Our parseBracket
found the first ] as the closing bracket, splitting [[:space:]] into
[[:space:] plus a literal ]. Fix by skipping past [:...:] sequences
when scanning for the closing bracket.

Test cases adapted from git/t/t3070-wildmatch.sh, including multiple
classes in one bracket and mixing ranges with POSIX classes.
In wildmatch, \X inside a bracket expression means literal X. The
bracket parser was blindly doubling all backslashes for the regex
engine, which broke patterns like [\-_] (literal dash and underscore),
[\1-\3] (range 1-3), and [[-\]] (range [ to ]).

The fix processes escape sequences during both bracket scanning (so \]
does not prematurely close the bracket) and content building (so \X
resolves to the literal character).
@andrew andrew force-pushed the fix-gitignore-negation branch from c476f27 to 224ce8d Compare February 9, 2026 09:41
Replace the internal gitignore package with the standalone module.
@andrew andrew merged commit 227b7c6 into main Feb 9, 2026
4 checks passed
@andrew andrew deleted the fix-gitignore-negation branch February 9, 2026 11:48
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