feat: add gitignore support to file watcher

This commit is contained in:
Paul Gauthier (aider) 2024-10-25 09:42:47 -07:00
parent 21876e72fe
commit 45e95d1d00

View file

@ -1,7 +1,9 @@
from pathlib import Path
from typing import Set
from typing import Set, Optional
from watchfiles import watch
from pathspec import PathSpec
from pathspec.patterns import GitWildMatchPattern
def is_source_file(path: Path) -> bool:
@ -40,16 +42,37 @@ def is_source_file(path: Path) -> bool:
return path.suffix.lower() in COMMENT_STYLE_EXTENSIONS
def watch_source_files(directory: str) -> Set[str]:
def load_gitignore(gitignore_path: Path) -> Optional[PathSpec]:
"""Load and parse a .gitignore file"""
if not gitignore_path.exists():
return None
with open(gitignore_path) as f:
patterns = f.readlines()
return PathSpec.from_lines(GitWildMatchPattern, patterns)
def watch_source_files(directory: str, gitignore: str = None) -> Set[str]:
"""
Watch for changes to source files in the given directory and its subdirectories.
Returns a set of changed file paths whenever changes are detected.
Args:
directory: Root directory to watch
gitignore: Path to .gitignore file (optional)
"""
root = Path(directory)
gitignore_spec = None
if gitignore:
gitignore_spec = load_gitignore(Path(gitignore))
# Create a filter function that only accepts source files
# Create a filter function that only accepts source files and respects gitignore
def filter_func(change_type, path):
return is_source_file(Path(path))
path_obj = Path(path)
if gitignore_spec and gitignore_spec.match_file(str(path_obj.relative_to(root))):
return False
return is_source_file(path_obj)
# Watch the directory for changes
for changes in watch(root, watch_filter=filter_func):
@ -61,16 +84,18 @@ def watch_source_files(directory: str) -> Set[str]:
def main():
"""Example usage of the file watcher"""
import sys
import argparse
parser = argparse.ArgumentParser(description="Watch source files for changes")
parser.add_argument("directory", help="Directory to watch")
parser.add_argument("--gitignore", help="Path to .gitignore file")
args = parser.parse_args()
if len(sys.argv) != 2:
print("Usage: python watch.py <directory>")
sys.exit(1)
directory = sys.argv[1]
directory = args.directory
print(f"Watching source files in {directory}...")
try:
for changed_files in watch_source_files(directory):
for changed_files in watch_source_files(directory, args.gitignore):
print("\nChanged files:")
for file in sorted(changed_files):
print(f" {file}")