diff --git a/fastcode/loader.py b/fastcode/loader.py index 87977b9..6d2272e 100644 --- a/fastcode/loader.py +++ b/fastcode/loader.py @@ -10,10 +10,11 @@ from typing import Dict, List, Optional, Any import logging from git import Repo, GitCommandError +from pathspec import PathSpec +from pathspec.patterns import GitWildMatchPattern from .utils import ( is_supported_file, - should_ignore_path, get_repo_name_from_url, normalize_path, ensure_dir, @@ -228,19 +229,39 @@ def scan_files(self) -> List[Dict[str, Any]]: files = [] total_size = 0 max_file_size_bytes = self.max_file_size_mb * 1024 * 1024 - + ignore_spec = PathSpec.from_lines(GitWildMatchPattern, effective_ignore) + + def is_ignored_repo_relative(rel_path: str, *, is_dir: bool = False) -> bool: + """Match ignore patterns against normalized repo-relative paths.""" + normalized = normalize_path(rel_path) + if ignore_spec.match_file(normalized): + return True + # Directory-style patterns (e.g. "output/" or ".venv/") are most + # reliable with a trailing slash candidate. + if is_dir and ignore_spec.match_file(f"{normalized}/"): + return True + return False + for root, dirs, filenames in os.walk(self.repo_path): - # Filter out ignored directories - dirs[:] = [d for d in dirs if not should_ignore_path( - os.path.join(root, d), effective_ignore - )] + # Filter ignored directories using repo-relative paths so gitwildmatch + # patterns like "output/" or ".venv/" match consistently. + filtered_dirs = [] + for d in dirs: + abs_dir_path = os.path.join(root, d) + rel_dir_path = normalize_path( + os.path.relpath(abs_dir_path, self.repo_path) + ) + if is_ignored_repo_relative(rel_dir_path, is_dir=True): + continue + filtered_dirs.append(d) + dirs[:] = filtered_dirs for filename in filenames: file_path = os.path.join(root, filename) - relative_path = os.path.relpath(file_path, self.repo_path) + relative_path = normalize_path(os.path.relpath(file_path, self.repo_path)) # Check if should ignore - if should_ignore_path(relative_path, effective_ignore): + if is_ignored_repo_relative(relative_path): continue # Check if supported extension @@ -347,4 +368,3 @@ def cleanup(self): def __del__(self): """Cleanup on deletion""" self.cleanup() -