diff --git a/docs/cli.md b/docs/cli.md index 6fa6706e8..5a4046d31 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -41,6 +41,8 @@ curl -fsSL https://raw.githubusercontent.com/jxxghp/MoviePilot/v3/scripts/bootst - macOS:`~/Library/Application Support/MoviePilot` - Linux:`${XDG_CONFIG_HOME:-~/.config}/moviepilot` +从程序目录内的旧 `config/` 迁移配置时,仅复制目标目录中缺失的文件或目录,不覆盖已有内容。只有实际复制了内容才显示“已将现有本地配置迁移到”提示;重复执行且无需复制时不再提示。 + 如果在交互式终端中执行一键安装脚本,或直接执行 `moviepilot setup` / `moviepilot init` 且未传入 `--config-dir`,程序会先询问配置目录,并把上面的默认路径作为默认值展示出来。 可以在安装或初始化时手动指定: diff --git a/moviepilot b/moviepilot index 453f5a3c6..c06e9b087 100755 --- a/moviepilot +++ b/moviepilot @@ -160,6 +160,7 @@ Options: 说明: - Rust 加速扩展通过 moviepilot-rust PyPI 依赖安装 - 可在前端“高级设置 - 实验室”中关闭或重新开启 Rust 加速 + - 旧配置仅补充目标目录缺失的内容,实际复制后才显示迁移提示 EOF } diff --git a/scripts/local_setup.py b/scripts/local_setup.py index cae553153..cee2e8975 100644 --- a/scripts/local_setup.py +++ b/scripts/local_setup.py @@ -419,6 +419,7 @@ def _seed_default_config_files(target_dir: Path) -> None: def _migrate_legacy_config_if_needed(target_dir: Path) -> None: + """补充目标目录缺失的旧配置,仅在实际复制后提示迁移成功。""" target_dir = target_dir.expanduser().resolve() if target_dir == LEGACY_CONFIG_DIR.resolve(): return @@ -427,6 +428,7 @@ def _migrate_legacy_config_if_needed(target_dir: Path) -> None: return target_dir.mkdir(parents=True, exist_ok=True) + migrated = False for source in sorted(LEGACY_CONFIG_DIR.iterdir()): target = target_dir / source.name if target.exists(): @@ -435,7 +437,9 @@ def _migrate_legacy_config_if_needed(target_dir: Path) -> None: shutil.copytree(source, target) else: shutil.copy2(source, target) - print_step(f"已将现有本地配置迁移到 {target_dir}") + migrated = True + if migrated: + print_step(f"已将现有本地配置迁移到 {target_dir}") def configure_config_dir( diff --git a/tests/test_local_setup_migration.py b/tests/test_local_setup_migration.py new file mode 100644 index 000000000..a8d2cd59d --- /dev/null +++ b/tests/test_local_setup_migration.py @@ -0,0 +1,59 @@ +"""本地配置迁移的重复执行与提示回归测试。""" + +import importlib.util +from pathlib import Path + +import pytest + + +@pytest.fixture +def setup_module_copy(tmp_path, monkeypatch): + """加载独立安装模块,将配置读写限制在临时目录。""" + monkeypatch.setenv("CONFIG_DIR", str(tmp_path / "external")) + module_path = Path(__file__).resolve().parents[1] / "scripts" / "local_setup.py" + spec = importlib.util.spec_from_file_location("local_setup_migration", module_path) + assert spec is not None and spec.loader is not None + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + legacy_dir = tmp_path / "legacy" + legacy_dir.mkdir() + monkeypatch.setattr(module, "LEGACY_CONFIG_DIR", legacy_dir) + return module + + +def test_migration_only_reports_actual_copies(setup_module_copy, tmp_path, capsys): + """首次迁移提示成功,重复运行保持静默且保留用户修改。""" + module = setup_module_copy + legacy_dir = module.LEGACY_CONFIG_DIR + (legacy_dir / "app.env").write_text("PORT=3001\n", encoding="utf-8") + (legacy_dir / "logs").mkdir() + (legacy_dir / "logs" / "old.log").write_text("old log", encoding="utf-8") + target_dir = tmp_path / "external" + + module.configure_config_dir(target_dir, prefer_external=True) + + assert f"已将现有本地配置迁移到 {target_dir.resolve()}" in capsys.readouterr().out + assert (target_dir / "app.env").read_text(encoding="utf-8") == "PORT=3001\n" + assert (target_dir / "logs" / "old.log").read_text(encoding="utf-8") == "old log" + (target_dir / "app.env").write_text("PORT=3002\n", encoding="utf-8") + + module.configure_config_dir(target_dir, prefer_external=True) + + assert capsys.readouterr().out == "" + assert (target_dir / "app.env").read_text(encoding="utf-8") == "PORT=3002\n" + + +def test_migration_reports_missing_directory_copy(setup_module_copy, tmp_path, capsys): + """已有配置只补充缺失目录时仍应提示,且不覆盖目标文件。""" + module = setup_module_copy + (module.LEGACY_CONFIG_DIR / "app.env").write_text("old", encoding="utf-8") + (module.LEGACY_CONFIG_DIR / "logs").mkdir() + target_dir = tmp_path / "external" + target_dir.mkdir() + (target_dir / "app.env").write_text("current", encoding="utf-8") + + module.configure_config_dir(target_dir, prefer_external=True) + + assert "已将现有本地配置迁移到" in capsys.readouterr().out + assert (target_dir / "logs").is_dir() + assert (target_dir / "app.env").read_text(encoding="utf-8") == "current"