refactor: route sidecar/preview path derivation through sidecar_paths helpers

Phase 1 of #1045 (optional centralized sidecar storage): introduce
py/utils/sidecar_paths.py as the single place that resolves .metadata.json
and preview locations, and replace all inline splitext-based derivations
across scanners, services, download manager, and route handlers.

No behavior change: the default 'alongside' storage mode resolves every
path exactly as before. .civitai.info (third-party sidecar) derivation is
intentionally left co-located.
This commit is contained in:
Will Miao
2026-09-26 09:02:37 +08:00
parent ede15032ce
commit 297d8787bd
14 changed files with 302 additions and 57 deletions
+20 -10
View File
@@ -38,6 +38,7 @@ from ..utils.preview_selection import resolve_mature_threshold, select_preview_m
from ..utils.utils import calculate_filename_for_model, sanitize_folder_name
from ..utils.exif_utils import ExifUtils
from ..utils.metadata_manager import MetadataManager
from ..utils.sidecar_paths import get_metadata_path, get_preview_dir
from .service_registry import ServiceRegistry
from .download_routing import is_diffusion_model_download, resolve_other_download_sub_type
from .settings_manager import get_settings_manager
@@ -831,7 +832,7 @@ class DownloadManager:
)
for file_path in target_files:
metadata_path = os.path.splitext(file_path)[0] + ".metadata.json"
metadata_path = get_metadata_path(file_path)
deleted = await self._delete_file_with_retries(metadata_path)
if not deleted and os.path.exists(metadata_path):
logger.error(f"Error deleting metadata file: {metadata_path}")
@@ -2447,7 +2448,7 @@ class DownloadManager:
return {"success": False, "error": save_path}
part_path = save_path + ".part"
metadata_path = os.path.splitext(save_path)[0] + ".metadata.json"
metadata_path = get_metadata_path(save_path)
pause_control = self._pause_events.get(download_id) if download_id else None
@@ -2503,7 +2504,10 @@ class DownloadManager:
if media_type == "video":
preview_ext = _extension_from_url(preview_url, ".mp4")
preview_path = os.path.splitext(save_path)[0] + preview_ext
preview_path = os.path.join(
get_preview_dir(save_path),
os.path.splitext(os.path.basename(save_path))[0] + preview_ext,
)
rewritten_url, rewritten = rewrite_preview_url(
preview_url, media_type="video"
)
@@ -2530,7 +2534,10 @@ class DownloadManager:
)
if rewritten and rewritten_url:
preview_ext = _extension_from_url(preview_url, ".png")
preview_path = os.path.splitext(save_path)[0] + preview_ext
preview_path = os.path.join(
get_preview_dir(save_path),
os.path.splitext(os.path.basename(save_path))[0] + preview_ext,
)
success, _ = await downloader.download_file(
rewritten_url, preview_path, use_auth=False
)
@@ -2557,8 +2564,9 @@ class DownloadManager:
temp_file_handle.write(
content if isinstance(content, bytes) else content.encode("utf-8")
)
preview_path = (
os.path.splitext(save_path)[0] + ".webp"
preview_path = os.path.join(
get_preview_dir(save_path),
os.path.splitext(os.path.basename(save_path))[0] + ".webp",
)
optimized_data, _ = ExifUtils.optimize_image(
@@ -2788,9 +2796,7 @@ class DownloadManager:
entry = cast(Any, adjusted_entry)
metadata_entries[index] = entry
metadata_file_path = (
os.path.splitext(entry.file_path)[0] + ".metadata.json"
)
metadata_file_path = get_metadata_path(entry.file_path)
metadata_files_for_cleanup.append(metadata_file_path)
await MetadataManager.save_metadata(entry.file_path, entry)
@@ -3049,7 +3055,11 @@ class DownloadManager:
extension = os.path.splitext(preview_path)[1] or ".webp"
targets = [
os.path.splitext(entry.file_path)[0] + extension for entry in entries
os.path.join(
get_preview_dir(entry.file_path),
os.path.splitext(os.path.basename(entry.file_path))[0] + extension,
)
for entry in entries
]
if not targets: