-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwatcher.py
More file actions
81 lines (66 loc) · 2.57 KB
/
watcher.py
File metadata and controls
81 lines (66 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# SPDX-License-Identifier: MIT
import logging
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from threading import Timer
from .recorder import Recorder
from . import path_utils
logger = logging.getLogger(__name__)
class DebouncedEventHandler(FileSystemEventHandler):
"""Handles file system events with debouncing to prevent excessive snapshots.
Attributes:
recorder: The Recorder instance to use for snapshots.
debounce_interval: Time in seconds to wait before processing a change.
timers: Dictionary of active timers for each file.
"""
def __init__(self, recorder: Recorder, debounce_interval: float = 2.0):
self.recorder = recorder
self.debounce_interval = debounce_interval
self.timers = {}
def on_modified(self, event):
if event.is_directory:
return
filepath = event.src_path
# Ignore .git directory.
if path_utils.is_git_directory(filepath):
return
# Check if ignored by git.
try:
if self.recorder.repo.ignored(filepath):
logger.debug(f"Ignoring {filepath} (git ignored)")
return
except Exception as e:
logger.warning(f"Failed to check ignore status for {filepath}: {e}")
if filepath in self.timers:
self.timers[filepath].cancel()
timer = Timer(self.debounce_interval, self._snapshot, [filepath])
self.timers[filepath] = timer
timer.start()
def _snapshot(self, filepath):
try:
self.recorder.create_snapshot(filepath)
if filepath in self.timers:
del self.timers[filepath]
except Exception as e:
logger.error(f"Error snapshotting {filepath}: {e}")
class Watcher:
"""Monitors the project directory for file changes.
Attributes:
path: The root directory to watch.
recorder: The Recorder instance to handle snapshots.
observer: The watchdog Observer instance.
handler: The event handler for file changes.
"""
def __init__(self, path: str, recorder: Recorder):
self.path = path
self.recorder = recorder
self.observer = Observer()
self.handler = DebouncedEventHandler(recorder)
def start(self):
self.observer.schedule(self.handler, self.path, recursive=True)
self.observer.start()
logger.info(f"Started watching {self.path}")
def stop(self):
self.observer.stop()
self.observer.join()
logger.info("Stopped watcher")