mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-10-25 17:36:29 +08:00
fix(search): honor directory filters without ripgrep
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
This commit is contained in:
2 files changed
+55
No files matched your search
@@ -523,6 +523,10 @@ class SearchFiles(BaseTool):
|
||||
|
||||
# ------------------------------------------------------------ grep backend
|
||||
def _backend_grep(self, opts: "_SearchOptions") -> "_BackendResult":
|
||||
# grep --include matches basenames, so a directory filter would silently
|
||||
# return no matches. Reuse the path-aware fallback for these filters.
|
||||
if "/" in opts.file_glob:
|
||||
return self._backend_python(opts)
|
||||
# -H forces filename even for a single-file target; -r recurses; -E = ERE
|
||||
# (aligns alternation/quantifier syntax with rg). -n is added only in
|
||||
# content mode — mixing it with -c/-l corrupts their output.
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Exercise directory filters through the native grep-only tool entry point."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
from agent.tools.search_files.search_files import SearchFiles
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def grep_tool(tmp_path, monkeypatch):
|
||||
binary = shutil.which("grep")
|
||||
if os.name == "nt" or not binary:
|
||||
pytest.skip("native POSIX grep required")
|
||||
source = tmp_path / "source"
|
||||
source.mkdir()
|
||||
for path in ["root.py", "src/direct.py", "src/nested/deep.py", "src/note.txt", "other/outside.py"]:
|
||||
file = source / path
|
||||
file.parent.mkdir(parents=True, exist_ok=True)
|
||||
file.write_text("needle\nneedle again\n", encoding="utf-8")
|
||||
bin_dir = tmp_path / "bin"
|
||||
bin_dir.mkdir()
|
||||
(bin_dir / "grep").symlink_to(binary)
|
||||
monkeypatch.setenv("PATH", str(bin_dir))
|
||||
tool = SearchFiles({"cwd": str(source)})
|
||||
assert tool._pick_backend().__name__ == "_backend_grep"
|
||||
return tool
|
||||
|
||||
|
||||
@pytest.mark.parametrize("file_glob, expected", [
|
||||
("src/*.py", ["src/direct.py"]),
|
||||
("src/**/*.py", ["src/direct.py", "src/nested/deep.py"]),
|
||||
("src/**/*.{py,txt}", ["src/direct.py", "src/nested/deep.py", "src/note.txt"]),
|
||||
("missing/*.py", []),
|
||||
("*.py", ["other/outside.py", "root.py", "src/direct.py", "src/nested/deep.py"]),
|
||||
])
|
||||
@pytest.mark.parametrize("mode", ["files", "content", "count"])
|
||||
def test_grep_only_path_filter(grep_tool, file_glob, expected, mode):
|
||||
result = grep_tool.execute({"pattern": "needle", "file_glob": file_glob, "output_mode": mode})
|
||||
assert result.status == "success", result.result
|
||||
data = result.result
|
||||
if mode == "files":
|
||||
actual = data["files"]
|
||||
elif mode == "count":
|
||||
actual = [row["file"] for row in data["counts"]]
|
||||
assert all(row["count"] == 2 for row in data["counts"])
|
||||
else:
|
||||
actual = sorted({row["file"] for row in data["matches"]})
|
||||
assert all(row["line"] in (1, 2) for row in data["matches"])
|
||||
assert actual == expected
|
||||
Reference in new issue
Block a user