Skip to content

Commit 14eecf7

Browse files
authored
Merge pull request #285 from Wolfvin/fix/codelensignore-nested-dir-fallback
fix(ignore): fallback matcher ignores nested build dirs (refs #271 Group D)
2 parents ae66a97 + 74186fb commit 14eecf7

1 file changed

Lines changed: 29 additions & 14 deletions

File tree

scripts/codelensignore.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -208,30 +208,45 @@ def is_ignored(self, rel_path: str) -> bool:
208208
result = False
209209
for is_neg, rx, anchored, dir_only in self._rules:
210210
if dir_only:
211-
# Match if rel == pat or rel.startswith(pat + '/')
212-
# We achieve this by matching the pattern OR pattern + '/*'
213-
# Use the regex against the path and any prefix path that
214-
# ends at a separator.
215-
# Simpler: check the rule against every prefix of rel.
216-
matched = self._match_dir_prefix(rx, rel)
211+
matched = self._match_dir_prefix(rx, rel, anchored)
217212
else:
218213
matched = bool(rx.match(rel))
219214
if matched:
220215
result = not is_neg
221216
return result
222217

223218
@staticmethod
224-
def _match_dir_prefix(rx: 're.Pattern', rel: str) -> bool:
225-
"""True if *rel* OR any ancestor directory matches *rx*."""
226-
# Check the full path first
219+
def _match_dir_prefix(rx: 're.Pattern', rel: str, anchored: bool = True) -> bool:
220+
"""True if *rel* is inside a directory matched by *rx*.
221+
222+
For an *anchored* pattern (``/target/``) only root-relative ancestor
223+
directories count. For a *non-anchored* pattern (``target/`` — the
224+
gitignore default) the directory may sit at ANY depth, so a whole path
225+
segment matching the pattern is enough. Segment matching (not substring)
226+
keeps ``build/`` from matching ``build-tools/`` (issue #271 / gitignore
227+
backward-compat): ``src/target/debug/x`` is ignored by ``target/`` but
228+
``build-tools/config`` is not ignored by ``build/``.
229+
"""
230+
# Check the full path first (handles patterns with wildcards/subpaths).
227231
if rx.match(rel):
228232
return True
229-
# Then check every ancestor directory
230233
parts = rel.split('/')
231-
for i in range(1, len(parts)):
232-
prefix = '/'.join(parts[:i])
233-
if rx.match(prefix):
234-
return True
234+
if anchored:
235+
# Root-anchored: only ancestor paths measured from the root.
236+
for i in range(1, len(parts)):
237+
if rx.match('/'.join(parts[:i])):
238+
return True
239+
else:
240+
# Non-anchored: the pattern (single- or multi-segment) may sit at
241+
# any depth → test every sub-path that both starts and ends on a
242+
# segment boundary. This matches `target/` against `src/target/x`
243+
# and `build/keep/` against `build/keep/x`, while whole-segment
244+
# boundaries keep `build/` from matching `build-tools/`.
245+
n = len(parts)
246+
for i in range(n):
247+
for j in range(i + 1, n + 1):
248+
if rx.match('/'.join(parts[i:j])):
249+
return True
235250
return False
236251

237252

0 commit comments

Comments
 (0)