isPathExcluded returns true when the given relative file path should be skipped based on hardcoded dir rules or .gitignore patterns. Patterns are resolved the way git resolves them: in file order, with the LAST matching pattern deciding, and a leading "!" inverting that pattern's verdict. Order mat
(relPath string, gitignorePatterns []string)
| 253 | // correct under last-match-wins. Treating negations as unmatchable made every |
| 254 | // file in such a repository look excluded, so a review silently covered nothing. |
| 255 | func (p *Provider) isPathExcluded(relPath string, gitignorePatterns []string) bool { |
| 256 | // Hardcoded directory prefix checks. These are an unconditional blocklist: |
| 257 | // a .gitignore negation cannot re-admit .git/ or node_modules/. |
| 258 | for _, prefix := range providerDirIgnoreDirs { |
| 259 | dirPart := strings.TrimSuffix(prefix, "/") |
| 260 | if relPath == dirPart || strings.HasPrefix(relPath, prefix) { |
| 261 | return true |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | excluded := false |
| 266 | for _, pat := range gitignorePatterns { |
| 267 | body, negated := strings.CutPrefix(pat, "!") |
| 268 | if body == "" { |
| 269 | continue |
| 270 | } |
| 271 | |
| 272 | // Directory-only patterns (trailing "/") apply to directories, never to |
| 273 | // files. Git uses a negated one such as `!*/` to keep descending into |
| 274 | // subdirectories, not to re-admit the files inside them — honouring it |
| 275 | // here would readmit everything below the root. |
| 276 | if negated && strings.HasSuffix(body, "/") { |
| 277 | continue |
| 278 | } |
| 279 | |
| 280 | if matchGitignoreBody(relPath, body) { |
| 281 | excluded = !negated |
| 282 | } |
| 283 | } |
| 284 | return excluded |
| 285 | } |
| 286 | |
| 287 | // matchGitignorePattern checks if relPath matches a single .gitignore pattern. |
| 288 | // |
no test coverage detected