From 986dc48c51ab36b8eaf06bded0e2187c32057fa2 Mon Sep 17 00:00:00 2001 From: Matt Derman Date: Fri, 28 Aug 2026 08:20:29 +0200 Subject: [PATCH] fix: preserve leading dots in cceignore paths --- src/context_engine/indexer/ignorefile.py | 2 +- tests/indexer/test_ignorefile.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/context_engine/indexer/ignorefile.py b/src/context_engine/indexer/ignorefile.py index fc20f7e..a3187fa 100644 --- a/src/context_engine/indexer/ignorefile.py +++ b/src/context_engine/indexer/ignorefile.py @@ -65,7 +65,7 @@ def matches_any(rel_path: str, is_dir: bool, patterns: list[str]) -> bool: if not patterns: return False # Normalise: forward slashes, no leading "./" - rel = rel_path.replace("\\", "/").lstrip("./") + rel = rel_path.replace("\\", "/").removeprefix("./") name = rel.rsplit("/", 1)[-1] for pat in patterns: # Trailing slash → directory-only pattern. diff --git a/tests/indexer/test_ignorefile.py b/tests/indexer/test_ignorefile.py index 051d357..8bd82bd 100644 --- a/tests/indexer/test_ignorefile.py +++ b/tests/indexer/test_ignorefile.py @@ -86,6 +86,12 @@ def test_trailing_slash_only_matches_dirs(): assert matches_any("src/build", is_dir=True, patterns=p) +def test_trailing_slash_matches_root_dot_directory(): + p = [".playwright/"] + assert matches_any(".playwright", is_dir=True, patterns=p) + assert matches_any("./.playwright", is_dir=True, patterns=p) + + # ── Empty / no-match guards ──────────────────────────────────────────────── def test_empty_patterns_matches_nothing(): @@ -110,18 +116,21 @@ def test_pipeline_walk_respects_cceignore(tmp_path): (p / "trace.log").write_text("noisy\n") (p / "scratch").mkdir() (p / "scratch" / "data.txt").write_text("temp\n") + (p / ".playwright").mkdir() + (p / ".playwright" / "state.json").write_text("{}\n") (p / "src").mkdir() (p / "src" / "lib.py").write_text("def lib(): pass\n") files = list(_iter_project_files( p, ignore_set=set(), skip_extensions=_SKIP_EXTENSIONS, - cceignore_patterns=["*.log", "scratch/"], + cceignore_patterns=["*.log", "scratch/", ".playwright/"], )) names = sorted(f.name for f in files) assert "main.py" in names assert "lib.py" in names assert "trace.log" not in names assert "data.txt" not in names # parent dir excluded by `scratch/` + assert "state.json" not in names def test_pipeline_no_cceignore_means_no_filter(tmp_path):