diff --git a/src/scikit_build_core/build/_file_processor.py b/src/scikit_build_core/build/_file_processor.py index f50e1408..a422daf8 100644 --- a/src/scikit_build_core/build/_file_processor.py +++ b/src/scikit_build_core/build/_file_processor.py @@ -89,7 +89,7 @@ def each_unignored_file( is_path=True, ): # Check to see if any include rules start with this - dstr = str(dirpath / dname).strip("/") + "/" + dstr = (dirpath / dname).as_posix().strip("/") + "/" if not any(p.lstrip("/").startswith(dstr) for p in include): dirs.remove(dname) diff --git a/tests/test_file_processor.py b/tests/test_file_processor.py index 1de1423c..aaa39a7b 100644 --- a/tests/test_file_processor.py +++ b/tests/test_file_processor.py @@ -201,6 +201,30 @@ def test_include_patterns( assert result == expected +def test_include_pattern_with_nested_path_and_broad_exclude( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """ + Test that nested include patterns are not pruned by directory traversal, + even when exclude patterns match all paths. + """ + monkeypatch.chdir(tmp_path) + nested_file = Path("a") / "b" / "c.txt" + nested_file.parent.mkdir(parents=True) + nested_file.write_text("content") + + result = set( + each_unignored_file( + Path(), + include=["a/b/c.txt"], + exclude=["*"], + mode="manual", + ) + ) + assert result == {nested_file} + + def test_exclude_patterns( tmp_path: Path, monkeypatch: pytest.MonkeyPatch,