fix(paths): normalize separators for organized and downloaded paths

The Windows job has been red since the workflow auto-organize feature (#1177) landed: two assertions expected one separator form while the code produced another on Windows.

- download_manager joined the posix relative path ("SDXL 1.0/utility") onto a native root, so save_dir came out mixed-separated. Normalize the joined directory with normpath.
- auto-organize's flat-template branch returned the native root while the templated branch returned a posix path; ModelMoveService.move_model had the same split. Normalize both to the posix form the scanner stores.

Linux-only runs cannot catch either because os.sep == "/".
This commit is contained in:
Will Miao
2026-11-07 11:52:32 +08:00
parent d2dd855cd2
commit b445bd16bb
2 changed files with 11 additions and 4 deletions
+3 -1
View File
@@ -2200,7 +2200,9 @@ class DownloadManager:
return {"success": False, "error": "No save directory specified"}
if relative_path:
base_save_dir = save_dir
save_dir = os.path.join(save_dir, relative_path)
# relative_path is posix-normalized ("SDXL 1.0/utility"), so
# normalize the joined directory back to native separators.
save_dir = os.path.normpath(os.path.join(save_dir, relative_path))
# Security: validate path containment after joining
resolved_dir = os.path.abspath(os.path.normpath(save_dir))
base_dir = os.path.abspath(os.path.normpath(base_save_dir))
+8 -3
View File
@@ -494,8 +494,10 @@ class ModelFileService:
# Check if already in root directory
if os.path.normpath(current_dir) == os.path.normpath(current_root):
return None # Signal to skip
return current_root
# Match the templated branch (and the scanner's stored paths):
# one separator form regardless of the configured layout.
return current_root.replace(os.sep, '/')
else:
# Calculate new relative path based on settings
new_relative_path = calculate_relative_path_for_model(model, self.model_type)
@@ -1153,7 +1155,7 @@ class ModelMoveService:
from ..utils.utils import calculate_relative_path_for_model
relative_path = calculate_relative_path_for_model(model_data, self.model_type)
if relative_path:
target_path = os.path.join(target_path, relative_path).replace(os.sep, '/')
target_path = os.path.join(target_path, relative_path)
elif not get_settings_manager().get_download_path_template(self.model_type):
# Flat structure, target_path remains the root
pass
@@ -1161,6 +1163,9 @@ class ModelMoveService:
# Could not calculate relative path (e.g. missing metadata)
# Fallback to manual target_path or skip?
pass
# Expose one form for both the flat and templated layouts;
# the scanner stores file paths posix-normalized.
target_path = target_path.replace(os.sep, '/')
source_dir = os.path.dirname(file_path)
if os.path.normpath(source_dir) == os.path.normpath(target_path):