diff --git a/backend/app/tasks/scan.py b/backend/app/tasks/scan.py index 8fcbb55..4a38317 100644 --- a/backend/app/tasks/scan.py +++ b/backend/app/tasks/scan.py @@ -164,11 +164,28 @@ async def _scan_folder_async(folder_path: str, source_root_id: Optional[str], ta hidden_folder_cache[folder_row.id] = False return False + # Build a set of paths owned by OTHER users' source roots so + # the admin's scan of /photos doesn't descend into /photos/bob. + other_root_paths: set[str] = set() + if owner_user_id: + other_roots = (await session.execute( + select(SourceRoot.path) + .where(SourceRoot.is_active == True) # noqa: E712 + .where(SourceRoot.user_id != owner_user_id) + )).scalars().all() + other_root_paths = {os.path.normpath(p) for p in other_roots} + + def _should_skip_dir(dirpath: str) -> bool: + """True if dirpath is another user's source root.""" + return os.path.normpath(dirpath) in other_root_paths + # Pre-walk to compute the total file count upfront. Without this # the progress bar would jump every time a new subfolder is # encountered because the running total kept growing. total_files = 0 for _root, _dirs, files in os.walk(folder_path): + # Prune other users' directories from count + _dirs[:] = [d for d in _dirs if not _should_skip_dir(os.path.join(_root, d))] total_files += sum( 1 for f in files if Path(f).suffix.lower() in SUPPORTED_EXTENSIONS ) @@ -179,6 +196,9 @@ async def _scan_folder_async(folder_path: str, source_root_id: Optional[str], ta errors = [] for root, dirs, files in os.walk(folder_path): + # Skip directories that belong to other users' source roots + dirs[:] = [d for d in dirs if not _should_skip_dir(os.path.join(root, d))] + # Get or create folder entry folder = await get_or_create_folder(session, root, source_root_id, owner_user_id) progress_set(REDIS_KEY_CURRENT_FOLDER, root)