mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-10 07:54:14 +08:00
fix: handle files in newly moved monitor directories
This commit is contained in:
@@ -159,6 +159,7 @@ class LocalDirectoryWatcher:
|
||||
将 watchfiles 原始变更转换为目录监控事件。
|
||||
:param changes: watchfiles 返回的变更集合
|
||||
"""
|
||||
changes = self._expand_added_directories(changes)
|
||||
for change_type, path_str in sorted(changes, key=lambda item: item[1]):
|
||||
if change_type not in self._HANDLE_CHANGES:
|
||||
continue
|
||||
@@ -180,6 +181,30 @@ class LocalDirectoryWatcher:
|
||||
except Exception as err:
|
||||
logger.error(f"处理本地目录监控事件失败: {path_str} - {err}")
|
||||
|
||||
def _expand_added_directories(self, changes: set[tuple[Change, str]]) -> set[tuple[Change, str]]:
|
||||
"""
|
||||
将整体移入监控范围的新增目录展开为内部文件事件。
|
||||
:param changes: watchfiles 返回的变更集合
|
||||
:return: 包含目录内新增文件的变更集合
|
||||
"""
|
||||
expanded_changes = set(changes)
|
||||
for change_type, path_str in changes:
|
||||
if change_type != Change.added:
|
||||
continue
|
||||
event_path = Path(path_str)
|
||||
try:
|
||||
if not event_path.is_dir():
|
||||
continue
|
||||
for nested_path in event_path.rglob("*"):
|
||||
if not nested_path.is_file():
|
||||
continue
|
||||
nested_path_str = nested_path.as_posix()
|
||||
if self._watch_filter(Change.added, nested_path_str):
|
||||
expanded_changes.add((Change.added, nested_path_str))
|
||||
except OSError as err:
|
||||
logger.debug(f"扫描新增目录失败: {event_path} - {err}")
|
||||
return expanded_changes
|
||||
|
||||
@staticmethod
|
||||
def _build_event(change_type: Change, event_path: Path) -> Optional[DirectoryChangeEvent]:
|
||||
"""
|
||||
|
||||
@@ -86,6 +86,36 @@ def test_handle_changes_skips_missing_paths(tmp_path):
|
||||
assert callback.events == []
|
||||
|
||||
|
||||
def test_handle_changes_expands_added_directory_files(tmp_path):
|
||||
"""
|
||||
整体移入的新增目录应递归转换成内部文件事件且不重复分发。
|
||||
"""
|
||||
added_dir = tmp_path / "task"
|
||||
nested_dir = added_dir / "season"
|
||||
nested_dir.mkdir(parents=True)
|
||||
movie_file = added_dir / "movie.mkv"
|
||||
episode_file = nested_dir / "episode.mkv"
|
||||
ignored_file = added_dir / ".DS_Store"
|
||||
movie_file.write_bytes(b"movie")
|
||||
episode_file.write_bytes(b"episode")
|
||||
ignored_file.write_bytes(b"ignored")
|
||||
|
||||
callback = CallbackRecorder()
|
||||
watcher = LocalDirectoryWatcher(tmp_path, callback=callback, force_polling=False)
|
||||
watcher._handle_changes({
|
||||
(Change.added, added_dir.as_posix()),
|
||||
(Change.added, movie_file.as_posix()),
|
||||
})
|
||||
|
||||
assert [
|
||||
(event.change_type, event_path, file_size)
|
||||
for event, _, event_path, file_size in callback.events
|
||||
] == [
|
||||
(Change.added, movie_file.as_posix(), 5),
|
||||
(Change.added, episode_file.as_posix(), 7),
|
||||
]
|
||||
|
||||
|
||||
def test_event_handler_routes_file_events_to_transfer_handler():
|
||||
"""
|
||||
文件事件应继续按 local 存储交给整理流程。
|
||||
|
||||
Reference in New Issue
Block a user