Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/dirmonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,73 @@ def walk(self, root: str) -> Iterator[tuple[str, os.stat_result]]:
yield from self.walk(path)

class _DirectorySnapshotDiff(DirectorySnapshotDiff):
def __init__(
self,
ref: DirectorySnapshot,
snapshot: DirectorySnapshot,
*,
ignore_device: bool = False,
) -> None:
super().__init__(ref, snapshot, ignore_device=ignore_device)
created = snapshot.paths - ref.paths
deleted = ref.paths - snapshot.paths

if ignore_device:

def get_inode(directory: DirectorySnapshot, full_path: bytes | str) -> int | tuple[int, int]:
return directory.inode(full_path)[0]

else:

def get_inode(directory: DirectorySnapshot, full_path: bytes | str) -> int | tuple[int, int]:
return directory.inode(full_path)

# check that all unchanged paths have the same inode
for path in ref.paths & snapshot.paths:
if get_inode(ref, path) != get_inode(snapshot, path):
created.add(path)
deleted.add(path)

# find moved paths
moved: set[tuple[bytes | str, bytes | str]] = set()
for path in set(deleted):
inode = ref.inode(path)
new_path = snapshot.path(inode)
if new_path and ref.mtime(path) == snapshot.mtime(new_path):
# file is not deleted but moved
deleted.remove(path)
moved.add((path, new_path))

for path in set(created):
inode = snapshot.inode(path)
old_path = ref.path(inode)
if old_path and ref.mtime(old_path) == snapshot.mtime(path):
created.remove(path)
moved.add((old_path, path))

# find modified paths
# first check paths that have not moved
modified: set[bytes | str] = set()
for path in ref.paths & snapshot.paths:
if get_inode(ref, path) == get_inode(snapshot, path) and (
ref.mtime(path) != snapshot.mtime(path) or ref.size(path) != snapshot.size(path)
):
modified.add(path)

for old_path, new_path in moved:
if ref.mtime(old_path) != snapshot.mtime(new_path) or ref.size(old_path) != snapshot.size(new_path):
modified.add(old_path)

self._dirs_created = [path for path in created if snapshot.isdir(path)]
self._dirs_deleted = [path for path in deleted if ref.isdir(path)]
self._dirs_modified = [path for path in modified if ref.isdir(path)]
self._dirs_moved = [(frm, to) for (frm, to) in moved if ref.isdir(frm)]

self._files_created = list(created - set(self._dirs_created))
self._files_deleted = list(deleted - set(self._dirs_deleted))
self._files_modified = list(modified - set(self._dirs_modified))
self._files_moved = list(moved - set(self._dirs_moved))

@property
def files_moved(self) -> list[dict[str, bytes | str]]:
"""重写 files_moved 方法,直接构造moved所需要的字典"""
Expand Down