From 993df0c25c090b76e64c69c868f261159c769a88 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Mon, 30 Jun 2025 19:40:05 +0200 Subject: [PATCH] Bugfix: match_path for gitignores was not working with anchored patterns --- src/serena/agent.py | 1 + src/serena/util/file_system.py | 15 +++++++++++---- src/solidlsp/ls.py | 15 +-------------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/serena/agent.py b/src/serena/agent.py index 7da88e1f..0098e83a 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -1563,6 +1563,7 @@ class FindFileTool(Tool): recursive=True, is_ignored_dir=self.agent.path_is_gitignored, is_ignored_file=is_ignored_file, + relative_to=self.get_project_root(), ) result = json.dumps({"files": files}) diff --git a/src/serena/util/file_system.py b/src/serena/util/file_system.py index 4e88a9a0..f16b46a1 100644 --- a/src/serena/util/file_system.py +++ b/src/serena/util/file_system.py @@ -276,12 +276,19 @@ class GitignoreParser: self._load_gitignore_files() -def match_path(path: str, path_spec: PathSpec) -> bool: - path = os.path.abspath(path) - normalized_path = str(path).replace(os.path.sep, "/") +def match_path(relative_path: str, path_spec: PathSpec) -> bool: + normalized_path = str(relative_path).replace(os.path.sep, "/") + + # We can have patterns like /src/..., which would only match corresponding paths from the repo root + # Unfortunately, pathspec can't know whether a relative path is relative to the repo root or not, + # so it will never match src/... + # The fix is to just always assume that the input path is relative to the repo root and to + # prefix it with /. + if not normalized_path.startswith("/"): + normalized_path = "/" + normalized_path # pathspec can't handle the matching of directories if they don't end with a slash! # see https://github.com/cpburnz/python-pathspec/issues/89 - if os.path.isdir(normalized_path) and not normalized_path.endswith("/"): + if os.path.isdir(relative_path) and not normalized_path.endswith("/"): normalized_path = normalized_path + "/" return path_spec.match_file(normalized_path) diff --git a/src/solidlsp/ls.py b/src/solidlsp/ls.py index aa3879bc..f77ed994 100644 --- a/src/solidlsp/ls.py +++ b/src/solidlsp/ls.py @@ -318,20 +318,7 @@ class SolidLanguageServer(ABC): if self.is_ignored_dirname(part): return True - # Use pathspec for gitignore-style pattern matching - # Normalize path separators for pathspec (it expects forward slashes) - normalized_path = str(rel_path).replace(os.path.sep, "/") - - # pathspec can't handle the matching of directories if they don't end with a slash! - # see https://github.com/cpburnz/python-pathspec/issues/89 - if os.path.isdir(os.path.join(self.repository_root_path, normalized_path)) and not normalized_path.endswith("/"): - normalized_path = normalized_path + "/" - - # Use the pathspec matcher to check if the path matches any ignore pattern - if self.get_ignore_spec().match_file(normalized_path): - return True - - return False + return match_path(relative_path, self.get_ignore_spec()) def _shutdown(self, timeout: float = 5.0): """