Skip to content

Commit 5b8e3a8

Browse files
committed
fix: don't traverse into excluded directories
Signed-off-by: Henry Schreiner <[email protected]>
1 parent 765af30 commit 5b8e3a8

File tree

1 file changed

+89
-28
lines changed

1 file changed

+89
-28
lines changed

src/scikit_build_core/build/_file_processor.py

Lines changed: 89 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
import pathspec
99

10-
from scikit_build_core.format import pyproject_format
10+
from .._logging import logger
11+
from ..format import pyproject_format
1112

1213
if TYPE_CHECKING:
1314
from collections.abc import Generator, Sequence
@@ -65,33 +66,93 @@ def each_unignored_file(
6566

6667
include_spec = pathspec.GitIgnoreSpec.from_lines(include)
6768

68-
for dirstr, _, filenames in os.walk(str(starting_path), followlinks=True):
69+
for dirstr, dirs, filenames in os.walk(str(starting_path), followlinks=True):
6970
dirpath = Path(dirstr)
70-
all_paths = (dirpath / fn for fn in filenames)
71-
for p in all_paths:
72-
# Always include something included
73-
if include_spec.match_file(p):
74-
yield p
75-
continue
76-
77-
# Always exclude something excluded
78-
if user_exclude_spec.match_file(p):
79-
continue
80-
81-
# Ignore from global ignore
82-
if global_exclude_spec.match_file(p):
83-
continue
84-
85-
# Ignore built-in patterns
86-
if builtin_exclude_spec.match_file(p):
87-
continue
88-
89-
# Check relative ignores (Python 3.9's is_relative_to workaround)
90-
if any(
91-
nex.match_file(p.relative_to(np))
92-
for np, nex in nested_excludes.items()
93-
if dirpath == np or np in dirpath.parents
71+
for dname in dirs:
72+
if not match_path(
73+
dirpath,
74+
dirpath / dname,
75+
include_spec,
76+
global_exclude_spec,
77+
builtin_exclude_spec,
78+
user_exclude_spec,
79+
nested_excludes,
80+
is_path=True,
9481
):
95-
continue
82+
dirs.remove(dname)
83+
84+
for fn in filenames:
85+
path = dirpath / fn
86+
if match_path(
87+
dirpath,
88+
path,
89+
include_spec,
90+
global_exclude_spec,
91+
builtin_exclude_spec,
92+
user_exclude_spec,
93+
nested_excludes,
94+
is_path=False,
95+
):
96+
yield path
97+
98+
99+
def match_path(
100+
dirpath: Path,
101+
p: Path,
102+
include_spec: pathspec.GitIgnoreSpec,
103+
global_exclude_spec: pathspec.GitIgnoreSpec,
104+
builtin_exclude_spec: pathspec.GitIgnoreSpec,
105+
user_exclude_spec: pathspec.GitIgnoreSpec,
106+
nested_excludes: dict[Path, pathspec.GitIgnoreSpec],
107+
*,
108+
is_path: bool,
109+
) -> bool:
110+
ptype = "directory" if is_path else "file"
111+
112+
# Always include something included
113+
if include_spec.match_file(p):
114+
logger.info("Including {} {} because it is explicitly included.", ptype, p)
115+
return True
116+
117+
# Always exclude something excluded
118+
if user_exclude_spec.match_file(p):
119+
logger.info(
120+
"Excluding {} {} because it is explicitly excluded by the user.", ptype, p
121+
)
122+
return False
123+
124+
# Ignore from global ignore
125+
if global_exclude_spec.match_file(p):
126+
logger.info(
127+
"Excluding {} {} because it is explicitly excluded by the global ignore.",
128+
ptype,
129+
p,
130+
)
131+
return False
132+
133+
# Ignore built-in patterns
134+
if builtin_exclude_spec.match_file(p):
135+
logger.info(
136+
"Excluding {} {} because it is explicitly excluded by the built-in ignore.",
137+
ptype,
138+
p,
139+
)
140+
return False
141+
142+
# Check relative ignores (Python 3.9's is_relative_to workaround)
143+
if any(
144+
nex.match_file(p.relative_to(np))
145+
for np, nex in nested_excludes.items()
146+
if dirpath == np or np in dirpath.parents
147+
):
148+
logger.info(
149+
"Excluding {} {} because it is explicitly included by nested ignore.",
150+
ptype,
151+
p,
152+
)
153+
return False
96154

97-
yield p
155+
logger.info(
156+
"Including {} {} because it exists (and isn't matched any other way).", ptype, p
157+
)
158+
return True

0 commit comments

Comments
 (0)