mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-07-05 00:41:17 -03:00
fix(settings): migrate all settings subdirectories on portable mode switch
This commit is contained in:
@@ -1568,7 +1568,7 @@ class SettingsManager:
|
|||||||
previous_dir = os.path.dirname(previous_path) or target_dir
|
previous_dir = os.path.dirname(previous_path) or target_dir
|
||||||
|
|
||||||
if os.path.abspath(previous_path) != os.path.abspath(target_path):
|
if os.path.abspath(previous_path) != os.path.abspath(target_path):
|
||||||
self._copy_model_cache_directory(previous_dir, target_dir)
|
self._migrate_settings_directory_content(previous_dir, target_dir)
|
||||||
logger.info("Switching settings file to: %s", target_path)
|
logger.info("Switching settings file to: %s", target_path)
|
||||||
|
|
||||||
self._pending_portable_switch = {"other_path": other_path}
|
self._pending_portable_switch = {"other_path": other_path}
|
||||||
@@ -1603,46 +1603,52 @@ class SettingsManager:
|
|||||||
finally:
|
finally:
|
||||||
self._pending_portable_switch = None
|
self._pending_portable_switch = None
|
||||||
|
|
||||||
def _copy_model_cache_directory(self, source_dir: str, target_dir: str) -> None:
|
def _migrate_settings_directory_content(
|
||||||
"""Copy model_cache artifacts when switching storage locations."""
|
self, source_dir: str, target_dir: str
|
||||||
|
) -> None:
|
||||||
|
"""Migrate settings directory subdirectories when switching storage locations.
|
||||||
|
|
||||||
|
Copies the canonical subdirectories (cache, backups, logs, stats, wildcards)
|
||||||
|
from the old settings directory to the new one. Legacy cache artifacts
|
||||||
|
(model_cache, recipe_cache, etc.) are migrated lazily by
|
||||||
|
``resolve_cache_path_with_migration`` on first access.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
source_dir: The previous settings directory path.
|
||||||
|
target_dir: The new settings directory path.
|
||||||
|
"""
|
||||||
|
|
||||||
if not source_dir or not target_dir:
|
if not source_dir or not target_dir:
|
||||||
return
|
return
|
||||||
|
|
||||||
source_cache_dir = os.path.join(source_dir, "model_cache")
|
def _copy_dir(name: str) -> None:
|
||||||
target_cache_dir = os.path.join(target_dir, "model_cache")
|
source = os.path.join(source_dir, name)
|
||||||
if os.path.isdir(source_cache_dir) and os.path.abspath(
|
target = os.path.join(target_dir, name)
|
||||||
source_cache_dir
|
if os.path.isdir(source) and os.path.abspath(source) != os.path.abspath(
|
||||||
) != os.path.abspath(target_cache_dir):
|
target
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
shutil.copytree(
|
shutil.copytree(
|
||||||
source_cache_dir,
|
source,
|
||||||
target_cache_dir,
|
target,
|
||||||
dirs_exist_ok=True,
|
dirs_exist_ok=True,
|
||||||
ignore=shutil.ignore_patterns("*.sqlite-shm", "*.sqlite-wal"),
|
ignore=shutil.ignore_patterns("*.sqlite-shm", "*.sqlite-wal"),
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Failed to copy model_cache directory from %s to %s: %s",
|
"Failed to copy directory %s from %s to %s: %s",
|
||||||
source_cache_dir,
|
name,
|
||||||
target_cache_dir,
|
source,
|
||||||
|
target,
|
||||||
exc,
|
exc,
|
||||||
)
|
)
|
||||||
|
|
||||||
source_cache_file = os.path.join(source_dir, "model_cache.sqlite")
|
# Managed subdirectories under settings_dir
|
||||||
target_cache_file = os.path.join(target_dir, "model_cache.sqlite")
|
_copy_dir("cache")
|
||||||
if os.path.isfile(source_cache_file) and os.path.abspath(
|
_copy_dir("backups")
|
||||||
source_cache_file
|
_copy_dir("logs")
|
||||||
) != os.path.abspath(target_cache_file):
|
_copy_dir("stats")
|
||||||
try:
|
_copy_dir("wildcards")
|
||||||
shutil.copy2(source_cache_file, target_cache_file)
|
|
||||||
except Exception as exc:
|
|
||||||
logger.warning(
|
|
||||||
"Failed to copy model_cache.sqlite from %s to %s: %s",
|
|
||||||
source_cache_file,
|
|
||||||
target_cache_file,
|
|
||||||
exc,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_user_config_directory(self) -> str:
|
def _get_user_config_directory(self) -> str:
|
||||||
"""Return the user configuration directory, falling back to ~/.config."""
|
"""Return the user configuration directory, falling back to ~/.config."""
|
||||||
|
|||||||
@@ -200,52 +200,97 @@ def _setup_storage_paths(tmp_path, monkeypatch):
|
|||||||
return project_root, user_dir, user_settings_path
|
return project_root, user_dir, user_settings_path
|
||||||
|
|
||||||
|
|
||||||
def _populate_cache(root_dir, marker_name, db_text):
|
def _populate_settings_dir(root_dir):
|
||||||
cache_dir = root_dir / "model_cache"
|
"""Create test data for all managed subdirectories under a settings directory."""
|
||||||
cache_dir.mkdir(exist_ok=True)
|
(root_dir / "cache" / "symlink").mkdir(parents=True, exist_ok=True)
|
||||||
marker_file = cache_dir / marker_name
|
(root_dir / "cache" / "symlink" / "symlink_map.json").write_text(
|
||||||
marker_file.write_text(marker_name, encoding="utf-8")
|
'{"migrated": true}', encoding="utf-8"
|
||||||
(root_dir / "model_cache.sqlite").write_text(db_text, encoding="utf-8")
|
)
|
||||||
|
(root_dir / "backups").mkdir(parents=True, exist_ok=True)
|
||||||
|
(root_dir / "backups" / "backup_test.zip").write_text(
|
||||||
|
"backup", encoding="utf-8"
|
||||||
|
)
|
||||||
|
(root_dir / "logs").mkdir(parents=True, exist_ok=True)
|
||||||
|
(root_dir / "logs" / "session.log").write_text("log", encoding="utf-8")
|
||||||
|
(root_dir / "stats").mkdir(parents=True, exist_ok=True)
|
||||||
|
(root_dir / "stats" / "stats.json").write_text(
|
||||||
|
'{"stats": true}', encoding="utf-8"
|
||||||
|
)
|
||||||
|
(root_dir / "wildcards").mkdir(parents=True, exist_ok=True)
|
||||||
|
(root_dir / "wildcards" / "test.txt").write_text("wildcard", encoding="utf-8")
|
||||||
|
|
||||||
|
|
||||||
def test_switch_to_portable_mode_copies_cache(tmp_path, monkeypatch):
|
def test_switch_to_portable_mode_copies_subdirectories(tmp_path, monkeypatch):
|
||||||
project_root, user_dir, user_settings = _setup_storage_paths(tmp_path, monkeypatch)
|
project_root, user_dir, user_settings = _setup_storage_paths(tmp_path, monkeypatch)
|
||||||
_populate_cache(user_dir, "user_marker.txt", "user_db")
|
_populate_settings_dir(user_dir)
|
||||||
|
|
||||||
manager = SettingsManager()
|
manager = SettingsManager()
|
||||||
|
|
||||||
manager.set("use_portable_settings", True)
|
manager.set("use_portable_settings", True)
|
||||||
|
|
||||||
assert manager.settings_file == str(project_root / "settings.json")
|
assert manager.settings_file == str(project_root / "settings.json")
|
||||||
marker_copy = project_root / "model_cache" / "user_marker.txt"
|
# Managed subdirectories should all be migrated
|
||||||
assert marker_copy.read_text(encoding="utf-8") == "user_marker.txt"
|
assert (
|
||||||
assert (project_root / "model_cache.sqlite").read_text(
|
project_root / "cache" / "symlink" / "symlink_map.json"
|
||||||
|
).read_text(encoding="utf-8") == '{"migrated": true}'
|
||||||
|
assert (
|
||||||
|
project_root / "backups" / "backup_test.zip"
|
||||||
|
).read_text(encoding="utf-8") == "backup"
|
||||||
|
assert (project_root / "logs" / "session.log").read_text(
|
||||||
encoding="utf-8"
|
encoding="utf-8"
|
||||||
) == "user_db"
|
) == "log"
|
||||||
|
assert (project_root / "stats" / "stats.json").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
) == '{"stats": true}'
|
||||||
|
assert (project_root / "wildcards" / "test.txt").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
) == "wildcard"
|
||||||
assert user_settings.exists()
|
assert user_settings.exists()
|
||||||
|
|
||||||
|
|
||||||
def test_switching_back_to_user_config_moves_cache(tmp_path, monkeypatch):
|
def test_switching_back_to_user_config_moves_subdirectories(tmp_path, monkeypatch):
|
||||||
project_root, user_dir, user_settings = _setup_storage_paths(tmp_path, monkeypatch)
|
project_root, user_dir, user_settings = _setup_storage_paths(tmp_path, monkeypatch)
|
||||||
_populate_cache(user_dir, "user_marker.txt", "user_db")
|
_populate_settings_dir(user_dir)
|
||||||
|
|
||||||
manager = SettingsManager()
|
manager = SettingsManager()
|
||||||
manager.set("use_portable_settings", True)
|
manager.set("use_portable_settings", True)
|
||||||
|
|
||||||
project_cache_dir = project_root / "model_cache"
|
# Populate project-root managed subdirectories
|
||||||
project_cache_dir.mkdir(exist_ok=True)
|
(project_root / "cache" / "model").mkdir(parents=True, exist_ok=True)
|
||||||
(project_cache_dir / "project_marker.txt").write_text(
|
(project_root / "cache" / "model" / "default.sqlite").write_text(
|
||||||
"project_marker", encoding="utf-8"
|
"project_db", encoding="utf-8"
|
||||||
|
)
|
||||||
|
(project_root / "backups" / "project_backup.zip").write_text(
|
||||||
|
"project_backup", encoding="utf-8"
|
||||||
|
)
|
||||||
|
(project_root / "logs" / "project.log").write_text(
|
||||||
|
"project_log", encoding="utf-8"
|
||||||
|
)
|
||||||
|
(project_root / "stats" / "project_stats.json").write_text(
|
||||||
|
'{"project": true}', encoding="utf-8"
|
||||||
|
)
|
||||||
|
(project_root / "wildcards" / "project.txt").write_text(
|
||||||
|
"project_wildcard", encoding="utf-8"
|
||||||
)
|
)
|
||||||
(project_root / "model_cache.sqlite").write_text("project_db", encoding="utf-8")
|
|
||||||
|
|
||||||
manager.set("use_portable_settings", False)
|
manager.set("use_portable_settings", False)
|
||||||
|
|
||||||
assert manager.settings_file == str(user_settings)
|
assert manager.settings_file == str(user_settings)
|
||||||
assert (user_dir / "model_cache" / "project_marker.txt").read_text(
|
assert (user_dir / "cache" / "model" / "default.sqlite").read_text(
|
||||||
encoding="utf-8"
|
encoding="utf-8"
|
||||||
) == "project_marker"
|
) == "project_db"
|
||||||
assert (user_dir / "model_cache.sqlite").read_text(encoding="utf-8") == "project_db"
|
assert (user_dir / "backups" / "project_backup.zip").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
) == "project_backup"
|
||||||
|
assert (user_dir / "logs" / "project.log").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
) == "project_log"
|
||||||
|
assert (user_dir / "stats" / "project_stats.json").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
) == '{"project": true}'
|
||||||
|
assert (user_dir / "wildcards" / "project.txt").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
) == "project_wildcard"
|
||||||
|
|
||||||
|
|
||||||
def test_download_path_template_parses_json_string(manager):
|
def test_download_path_template_parses_json_string(manager):
|
||||||
|
|||||||
Reference in New Issue
Block a user