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 pathlib import Path
from typing import Set from typing import Set, Optional
from watchfiles import watch from watchfiles import watch
from pathspec import PathSpec
from pathspec.patterns import GitWildMatchPattern
def is_source_file(path: Path) -> bool: 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 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. Watch for changes to source files in the given directory and its subdirectories.
Returns a set of changed file paths whenever changes are detected. 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) root = Path(directory)
gitignore_spec = None
# Create a filter function that only accepts source files if gitignore:
gitignore_spec = load_gitignore(Path(gitignore))
# Create a filter function that only accepts source files and respects gitignore
def filter_func(change_type, path): 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 # Watch the directory for changes
for changes in watch(root, watch_filter=filter_func): for changes in watch(root, watch_filter=filter_func):
@ -61,16 +84,18 @@ def watch_source_files(directory: str) -> Set[str]:
def main(): def main():
"""Example usage of the file watcher""" """Example usage of the file watcher"""
import sys import sys
import argparse
if len(sys.argv) != 2: parser = argparse.ArgumentParser(description="Watch source files for changes")
print("Usage: python watch.py <directory>") parser.add_argument("directory", help="Directory to watch")
sys.exit(1) parser.add_argument("--gitignore", help="Path to .gitignore file")
args = parser.parse_args()
directory = sys.argv[1] directory = args.directory
print(f"Watching source files in {directory}...") print(f"Watching source files in {directory}...")
try: try:
for changed_files in watch_source_files(directory): for changed_files in watch_source_files(directory, args.gitignore):
print("\nChanged files:") print("\nChanged files:")
for file in sorted(changed_files): for file in sorted(changed_files):
print(f" {file}") print(f" {file}")