mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 08:15:59 +00:00
fix(file_system): handle PermissionError on scandir in gitignore walker (#1634)
Wrap os.scandir() with PermissionError guard in _iter_gitignore_files' scan() function to prevent crash when a subdirectory is not readable. Previously, PermissionError on the scandir call itself crashed the entire gitignore walker, even when the path was listed in ignored_paths. Fixes oraios/serena#1624 Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
dcbd8ce064
commit
b8a0882d29
3 files changed
+46
-2
No files matched your search
@@ -26,6 +26,7 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
(which does not correctly unpack structured output) #1042
|
||||
- Fix: Project-specific filtering of files for source files ignored the language backend.
|
||||
The check is really only possible for LSP.
|
||||
- Fix: File system permission errors during gitignore scanning were not caught #1624
|
||||
|
||||
* CLI:
|
||||
- Fix `--project-from-cwd` hijacking git worktrees nested under a Serena project. `find_project_root`
|
||||
|
||||
@@ -164,7 +164,12 @@ class GitignoreParser:
|
||||
queue: list[str] = [self.repo_root]
|
||||
|
||||
def scan(abs_path: str | None) -> Iterator[str]:
|
||||
for entry in os.scandir(abs_path):
|
||||
try:
|
||||
entries = os.scandir(abs_path)
|
||||
except PermissionError as ex:
|
||||
log.debug(f"Skipping unreadable directory {abs_path}: {ex}")
|
||||
return
|
||||
for entry in entries:
|
||||
try:
|
||||
if entry.is_dir(follow_symlinks=follow_symlinks):
|
||||
queue.append(entry.path)
|
||||
|
||||
@@ -3,7 +3,6 @@ import shutil
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
# Assuming the gitignore parser code is in a module named 'gitignore_parser'
|
||||
from pathspec import PathSpec
|
||||
|
||||
from serena.util.file_system import GitignoreParser, GitignoreSpec, match_path
|
||||
@@ -715,3 +714,42 @@ src/*.o
|
||||
|
||||
# foo.txt in other/ should NOT be ignored (outside foo/ subtree)
|
||||
assert not parser.should_ignore("other/foo.txt"), "other/foo.txt should NOT be ignored by foo/.gitignore"
|
||||
|
||||
|
||||
class TestGitignoreParserPermissionError:
|
||||
"""Test PermissionError handling in GitignoreParser."""
|
||||
|
||||
def setup_method(self):
|
||||
self.test_dir = tempfile.mkdtemp()
|
||||
self.repo_path = Path(self.test_dir)
|
||||
|
||||
def teardown_method(self):
|
||||
shutil.rmtree(self.test_dir, ignore_errors=True)
|
||||
|
||||
def test_scandir_permission_error_on_subdirectory(self):
|
||||
"""
|
||||
Test that GitignoreParser does not crash when a subdirectory
|
||||
is not readable (PermissionError on os.scandir).
|
||||
|
||||
Regression test for https://github.com/oraios/serena/issues/1624
|
||||
"""
|
||||
# Create a root .gitignore
|
||||
gitignore = self.repo_path / ".gitignore"
|
||||
gitignore.write_text("*.log\n")
|
||||
|
||||
# Create an unreadable subdirectory
|
||||
unreadable = self.repo_path / "unreadable_dir"
|
||||
unreadable.mkdir()
|
||||
|
||||
# Remove read permissions (Unix only; on Windows this is a no-op)
|
||||
old_mode = os.stat(unreadable).st_mode
|
||||
os.chmod(unreadable, 0o000)
|
||||
|
||||
try:
|
||||
# This should not raise PermissionError
|
||||
parser = GitignoreParser(str(self.repo_path))
|
||||
# Parser should still function
|
||||
assert parser.should_ignore("test.log")
|
||||
finally:
|
||||
# Restore permissions so teardown can clean up
|
||||
os.chmod(unreadable, old_mode)
|
||||
Reference in new issue
Block a user