diff --git a/code_review_graph/incremental.py b/code_review_graph/incremental.py index 81dc3026..d229afbb 100644 --- a/code_review_graph/incremental.py +++ b/code_review_graph/incremental.py @@ -359,7 +359,14 @@ def _load_ignore_patterns(repo_root: Path) -> list[str]: for line in ignore_file.read_text(encoding="utf-8", errors="replace").splitlines(): line = line.strip() if line and not line.startswith("#"): - patterns.append(line) + # Treat plain directory entries like `.venv/` or `vendor/` as + # recursive globs, matching `.gitignore` behavior for directories. + if line.startswith("/"): + line = line[1:] + if line.endswith("/"): + line = f"{line}**" + if line: + patterns.append(line) return patterns diff --git a/tests/test_incremental.py b/tests/test_incremental.py index 0d864203..6ab2b381 100644 --- a/tests/test_incremental.py +++ b/tests/test_incremental.py @@ -194,7 +194,7 @@ def test_default_patterns_loaded(self, tmp_path): def test_custom_ignore_file(self, tmp_path): ignore = tmp_path / ".code-review-graphignore" - ignore.write_text("custom/**\n# comment\n\nvendor/**\n") + ignore.write_text("custom/\n# comment\n\nvendor/**\n") patterns = _load_ignore_patterns(tmp_path) assert "custom/**" in patterns assert "vendor/**" in patterns @@ -209,6 +209,17 @@ def test_should_ignore_matches(self): assert _should_ignore(".git/HEAD", patterns) assert not _should_ignore("src/main.py", patterns) + def test_should_ignore_directory_trailing_slash_pattern(self, tmp_path): + ignore = tmp_path / ".code-review-graphignore" + ignore.write_text("vendor/\ngenerated/\n") + + patterns = _load_ignore_patterns(tmp_path) + assert "vendor/**" in patterns + assert "generated/**" in patterns + assert _should_ignore("vendor/autoload.php", patterns) + assert _should_ignore("generated/code.js", patterns) + assert not _should_ignore("src/vendorized/file.php", patterns) + def test_should_ignore_nested_dependency_dirs(self): """Nested node_modules / vendor / .gradle should be ignored (#91).""" patterns = [