From 7f0f5a1b5a9cfc7780c8931178e2ff30c99ec65f Mon Sep 17 00:00:00 2001 From: Osamaali313 Date: Sun, 19 Jul 2026 23:57:34 +0300 Subject: [PATCH] Fix nested .gitignore directory patterns not excluding under --exclude-gitignore `matches_gitignore` computes `relative_path = os.path.relpath(subpath, gi_path)` so it can be matched against the gitignore spec (gitignore patterns are relative to the .gitignore's directory). But it then passes that same gi_path-relative string to `fscache.isdir(...)`, which resolves paths relative to the process cwd. When the matched `.gitignore` lives in a scanned subdirectory (`gi_path != cwd`), `relative_path` does not resolve on the real filesystem, so `isdir` returns False, the trailing "/" is never appended, and directory-only patterns (e.g. `build/`, `node_modules/`) fail to exclude the directory. The sibling `matches_exclude` in the same file does this correctly: it builds the match string with `os.path.relpath(subpath)` but calls `fscache.isdir(subpath)` on the original path. Match `matches_gitignore` to that: stat the original `subpath`, keep using `relative_path` only for the gitignore-spec match. --- mypy/modulefinder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/modulefinder.py b/mypy/modulefinder.py index baa521afbb122..c5ec268752c6c 100644 --- a/mypy/modulefinder.py +++ b/mypy/modulefinder.py @@ -711,7 +711,7 @@ def matches_gitignore(subpath: str, fscache: FileSystemCache, verbose: bool) -> dir, _ = os.path.split(subpath) for gi_path, gi_spec in find_gitignores(dir): relative_path = os.path.relpath(subpath, gi_path) - if fscache.isdir(relative_path): + if fscache.isdir(subpath): relative_path = relative_path + "/" if gi_spec.match_file(relative_path): if verbose: