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)
| 194 | // correct under last-match-wins. Treating negations as unmatchable made every |
| 195 | // file in such a repository look excluded, so a review silently covered nothing. |
| 196 | func (p *Provider) isPathExcluded(relPath string, gitignorePatterns []string) bool { |
| 197 | // Hardcoded directory prefix checks. These are an unconditional blocklist: |
| 198 | // a .gitignore negation cannot re-admit .git/ or node_modules/. |
| 199 | for _, prefix := range providerDirIgnoreDirs { |
| 200 | dirPart := strings.TrimSuffix(prefix, "/") |
| 201 | if relPath == dirPart || strings.HasPrefix(relPath, prefix) { |
| 202 | return true |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | excluded := false |
| 207 | for _, pat := range gitignorePatterns { |
| 208 | body, negated := strings.CutPrefix(pat, "!") |
| 209 | if body == "" { |
| 210 | continue |
| 211 | } |
| 212 | |
| 213 | // Directory-only patterns (trailing "/") apply to directories, never to |
| 214 | // files. Git uses a negated one such as `!*/` to keep descending into |
| 215 | // subdirectories, not to re-admit the files inside them — honouring it |
| 216 | // here would readmit everything below the root. |
| 217 | if negated && strings.HasSuffix(body, "/") { |
| 218 | continue |
| 219 | } |
| 220 | |
| 221 | if matchGitignoreBody(relPath, body) { |
| 222 | excluded = !negated |
| 223 | } |
| 224 | } |
| 225 | return excluded |
| 226 | } |
| 227 | |
| 228 | // matchGitignorePattern checks if relPath matches a single .gitignore pattern. |
| 229 | // |
no test coverage detected