mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 07:27:15 +08:00
fix: 完善插件恢复与运行态收敛 (#6376)
This commit is contained in:
Vendored
+22
-4
@@ -12,6 +12,7 @@ import tempfile
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
import uuid
|
||||
import zipfile
|
||||
from pathlib import Path, PurePosixPath, PureWindowsPath
|
||||
from typing import Dict, List, Optional, Tuple, Set, Callable, Awaitable, Sequence
|
||||
@@ -1129,21 +1130,38 @@ class PluginHelper(metaclass=WeakSingleton):
|
||||
|
||||
backup_root = settings.CONFIG_PATH / "plugins_backup"
|
||||
backup_dir = backup_root / pid.lower()
|
||||
staging_dir = backup_root / f".{pid.lower()}.tmp-{uuid.uuid4().hex}"
|
||||
previous_dir = backup_root / f".{pid.lower()}.old-{uuid.uuid4().hex}"
|
||||
try:
|
||||
backup_root.mkdir(parents=True, exist_ok=True)
|
||||
if backup_dir.exists():
|
||||
shutil.rmtree(backup_dir, ignore_errors=True)
|
||||
shutil.copytree(
|
||||
plugin_dir,
|
||||
backup_dir,
|
||||
dirs_exist_ok=True,
|
||||
staging_dir,
|
||||
ignore=shutil.ignore_patterns("__pycache__", "*.pyc", ".DS_Store")
|
||||
)
|
||||
if backup_dir.exists():
|
||||
backup_dir.replace(previous_dir)
|
||||
staging_dir.replace(backup_dir)
|
||||
if previous_dir.exists():
|
||||
shutil.rmtree(previous_dir, ignore_errors=True)
|
||||
logger.info(f"已刷新插件备份: {pid}")
|
||||
return True
|
||||
except Exception as e:
|
||||
if not backup_dir.exists() and previous_dir.exists():
|
||||
try:
|
||||
previous_dir.replace(backup_dir)
|
||||
except Exception as rollback_error:
|
||||
logger.error(
|
||||
f"恢复插件旧备份失败,已保留恢复材料 {previous_dir}: "
|
||||
f"{rollback_error}"
|
||||
)
|
||||
logger.error(f"刷新插件备份失败: {pid} - {e}")
|
||||
return False
|
||||
finally:
|
||||
if staging_dir.exists():
|
||||
shutil.rmtree(staging_dir, ignore_errors=True)
|
||||
if backup_dir.exists() and previous_dir.exists():
|
||||
shutil.rmtree(previous_dir, ignore_errors=True)
|
||||
|
||||
def __collect_plugin_wheels_dirs(self) -> List[Path]:
|
||||
"""
|
||||
|
||||
@@ -297,6 +297,39 @@ class PluginDependencyInstaller:
|
||||
logger.error(f"收集所有需要安装或更新的依赖项时发生错误:{err}")
|
||||
return []
|
||||
|
||||
def classify_plugins(self) -> tuple[list[str], list[str], list[str]]:
|
||||
"""按源码和依赖状态划分已安装插件。"""
|
||||
ready: list[str] = []
|
||||
missing_dependencies: list[str] = []
|
||||
missing_source: list[str] = []
|
||||
installed_packages = self._installed_packages()
|
||||
|
||||
for plugin_id in self._installed_plugins_provider() or []:
|
||||
plugin_dir = self._plugin_dir / plugin_id.lower()
|
||||
if not plugin_dir.is_dir():
|
||||
missing_source.append(plugin_id)
|
||||
continue
|
||||
try:
|
||||
manifest = load_dependency_manifest(plugin_dir)
|
||||
requirements = [] if manifest is None else [
|
||||
requirement
|
||||
for requirement in manifest.dependencies
|
||||
if not requirement.marker or requirement.marker.evaluate()
|
||||
]
|
||||
except PluginDependencyManifestError as error:
|
||||
logger.error(f"插件 {plugin_id} 依赖清单无效:{error}")
|
||||
missing_dependencies.append(plugin_id)
|
||||
continue
|
||||
if all(
|
||||
self._requirement_satisfied(requirement, installed_packages)
|
||||
for requirement in requirements
|
||||
):
|
||||
ready.append(plugin_id)
|
||||
else:
|
||||
missing_dependencies.append(plugin_id)
|
||||
|
||||
return ready, missing_dependencies, missing_source
|
||||
|
||||
def _wheels_dirs(self) -> list[Path]:
|
||||
"""收集已安装插件附带的本地 wheels 目录。"""
|
||||
result = []
|
||||
|
||||
Reference in New Issue
Block a user