Release SyncVito 1.0.7
This commit is contained in:
1 parent
3d6ab87ce3
commit
a04db4ee96
10 files changed
+278
-28
No files matched your search
@@ -10,7 +10,7 @@ from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from syncvito.file_locks import LockingProcess, find_locking_processes
|
||||
from syncvito.file_locks import LockingProcess, find_locking_processes, is_file_locked
|
||||
from syncvito.models import ConflictMode, DeleteMode, SyncDirection, SyncTask
|
||||
from syncvito.state_store import StateStore
|
||||
|
||||
@@ -117,12 +117,20 @@ class SyncEngine:
|
||||
for index, operation in enumerate(operations, start=1):
|
||||
try:
|
||||
self._execute(operation, result)
|
||||
except PermissionError as exc:
|
||||
processes = tuple(find_locking_processes(operation.target))
|
||||
result.blocked.append(BlockedFile(operation.target, processes))
|
||||
result.errors.append(f"Zugriff verweigert: {operation.target} ({exc})")
|
||||
except (OSError, shutil.Error) as exc:
|
||||
result.errors.append(f"{operation.target}: {exc}")
|
||||
failed_path = (
|
||||
Path(exc.filename2 or exc.filename)
|
||||
if isinstance(exc, OSError) and (exc.filename2 or exc.filename)
|
||||
else operation.target
|
||||
)
|
||||
blocked_path = _blocked_path(operation, exc)
|
||||
if blocked_path is not None:
|
||||
processes = tuple(find_locking_processes(blocked_path))
|
||||
result.blocked.append(BlockedFile(blocked_path, processes))
|
||||
elif isinstance(exc, PermissionError):
|
||||
result.errors.append(f"Zugriff verweigert: {failed_path} ({exc})")
|
||||
else:
|
||||
result.errors.append(f"{failed_path}: {exc}")
|
||||
if progress:
|
||||
detail = f"{operation.kind}: {operation.relative}"
|
||||
progress(round(index / total * 100), detail)
|
||||
@@ -295,6 +303,25 @@ class SyncEngine:
|
||||
}
|
||||
|
||||
|
||||
def _blocked_path(operation: _Operation, exc: OSError | shutil.Error) -> Path | None:
|
||||
"""Ordnet auch Windows-Kopierfehler ohne Dateinamen der gesperrten Seite zu."""
|
||||
winerror = getattr(exc, "winerror", None)
|
||||
if winerror not in {5, 32, 33}:
|
||||
return None
|
||||
reported = (exc.filename2 or exc.filename) if isinstance(exc, OSError) else None
|
||||
if reported and winerror in {32, 33}:
|
||||
return Path(reported)
|
||||
candidates = [Path(reported)] if reported else []
|
||||
candidates.extend(path for path in (operation.source, operation.target) if path is not None)
|
||||
for path in dict.fromkeys(candidates):
|
||||
if is_file_locked(path):
|
||||
return path
|
||||
# Eine inzwischen freigegebene Datei beim nächsten Lauf erneut versuchen.
|
||||
if winerror in {32, 33}:
|
||||
return operation.source or operation.target
|
||||
return None
|
||||
|
||||
|
||||
def _atomic_copy(source: Path, target: Path) -> None:
|
||||
temporary = target.with_name(f".{target.name}.syncvito.tmp")
|
||||
try:
|
||||
|
||||
Reference in new issue
Block a user