mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-02 21:34:32 +08:00
fix(plugin): restore compatible history lookup
This commit is contained in:
@@ -9,7 +9,7 @@ from fastapi import Depends, Header, HTTPException, Security
|
||||
from starlette import status
|
||||
from starlette.responses import StreamingResponse
|
||||
|
||||
from app.adapters.external.market import PluginHelper
|
||||
from app.adapters.external.market import VERSION_BACKWARD_COMPATIBLE_FLAGS, PluginHelper
|
||||
from app.adapters.external.server import MoviePilotServerHelper
|
||||
from app.adapters.web.security.access import (
|
||||
resource_token_cookie,
|
||||
@@ -101,33 +101,32 @@ async def _get_market_plugin_from_repo(
|
||||
force: bool,
|
||||
) -> Optional[_SchemaPlugin]:
|
||||
"""
|
||||
只读取指定插件仓库的市场元数据,避免单插件详情触发全部市场刷新。
|
||||
"""
|
||||
market_plugins = await plugin_manager.async_get_plugins_from_market(
|
||||
repo_url, get_api_runtime_config_snapshot().version_flag, force
|
||||
)
|
||||
market_plugin = next(
|
||||
(
|
||||
plugin
|
||||
for plugin in market_plugins or []
|
||||
if plugin.id == plugin_id
|
||||
),
|
||||
None,
|
||||
)
|
||||
if market_plugin or not get_api_runtime_config_snapshot().version_flag:
|
||||
return market_plugin
|
||||
按当前代际、向后兼容代际和基础索引顺序读取指定仓库的市场元数据。
|
||||
|
||||
compatible_plugins = await plugin_manager.async_get_plugins_from_market(
|
||||
repo_url, None, force
|
||||
)
|
||||
return next(
|
||||
(
|
||||
plugin
|
||||
for plugin in compatible_plugins or []
|
||||
if plugin.id == plugin_id
|
||||
),
|
||||
None,
|
||||
)
|
||||
单插件详情只访问可信绑定仓库,避免触发全部市场刷新;代际顺序必须与
|
||||
全量插件目录保持一致,否则仅存在于 package.v2.json 的插件会丢失历史说明。
|
||||
"""
|
||||
version_flag = get_api_runtime_config_snapshot().version_flag
|
||||
package_versions = [version_flag] if version_flag else []
|
||||
package_versions.extend(VERSION_BACKWARD_COMPATIBLE_FLAGS.get(version_flag, []))
|
||||
package_versions.append(None)
|
||||
|
||||
for package_version in dict.fromkeys(package_versions):
|
||||
market_plugins = await plugin_manager.async_get_plugins_from_market(
|
||||
repo_url, package_version, force
|
||||
)
|
||||
market_plugin = next(
|
||||
(
|
||||
plugin
|
||||
for plugin in market_plugins or []
|
||||
if plugin.id == plugin_id
|
||||
),
|
||||
None,
|
||||
)
|
||||
if market_plugin:
|
||||
return market_plugin
|
||||
|
||||
return None
|
||||
|
||||
|
||||
async def _refresh_plugin_release_versions(plugin_id: str, repo_url: str) -> None:
|
||||
|
||||
@@ -286,6 +286,41 @@ def test_plugin_history_merges_remote_metadata():
|
||||
)
|
||||
|
||||
|
||||
def test_plugin_history_falls_back_to_backward_compatible_package():
|
||||
"""已绑定来源的插件在当前索引缺失时仍读取向后兼容代际的历史。"""
|
||||
installed_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
plugin_name="Demo Plugin",
|
||||
plugin_version="1.0.0",
|
||||
installed=True,
|
||||
history={},
|
||||
)
|
||||
market_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
repo_url=SOURCE_URL,
|
||||
history={"v2.0.0": "兼容代际更新说明"},
|
||||
)
|
||||
plugin_manager = MagicMock()
|
||||
plugin_manager.get_installed_plugins.return_value = [installed_plugin]
|
||||
plugin_manager.get_local_repo_plugins.return_value = []
|
||||
plugin_manager.async_get_plugins_from_market = AsyncMock(
|
||||
side_effect=[[], [market_plugin]]
|
||||
)
|
||||
persistence = _persistence(_plugin_identity())
|
||||
|
||||
with (
|
||||
patch("app.api.endpoints.plugin.get_plugin_manager", return_value=plugin_manager),
|
||||
patch("app.api.endpoints.plugin.get_plugin_persistence", return_value=persistence),
|
||||
):
|
||||
result = asyncio.run(plugin_history("DemoPlugin", None, True))
|
||||
|
||||
assert result.history == {"v2.0.0": "兼容代际更新说明"}
|
||||
assert plugin_manager.async_get_plugins_from_market.await_args_list == [
|
||||
((SOURCE_URL, settings.VERSION_FLAG, True), {}),
|
||||
((SOURCE_URL, "v2", True), {}),
|
||||
]
|
||||
|
||||
|
||||
def test_runtime_status_reports_pending_and_terminal_counts():
|
||||
"""插件页摘要区分后台收敛、准备态和终态失败。"""
|
||||
plugin_manager = MagicMock()
|
||||
@@ -506,7 +541,7 @@ def test_plugin_releases_does_not_mutate_cached_release_items(monkeypatch):
|
||||
|
||||
def test_plugin_releases_falls_back_to_compatible_base_package(monkeypatch):
|
||||
"""
|
||||
当前版本 package 未包含插件时,再读取基础 package 兼容项,不扫描其他市场。
|
||||
当前版本和向后兼容 package 未包含插件时,再读取基础 package 兼容项。
|
||||
"""
|
||||
market_plugin = schemas.Plugin(
|
||||
id="DemoPlugin",
|
||||
@@ -516,7 +551,7 @@ def test_plugin_releases_falls_back_to_compatible_base_package(monkeypatch):
|
||||
)
|
||||
plugin_manager = MagicMock()
|
||||
plugin_manager.async_get_plugins_from_market = AsyncMock(
|
||||
side_effect=[[], [market_plugin]]
|
||||
side_effect=[[], [], [market_plugin]]
|
||||
)
|
||||
plugin_manager.get_local_plugin_version.return_value = None
|
||||
plugin_helper = MagicMock()
|
||||
@@ -534,6 +569,7 @@ def test_plugin_releases_falls_back_to_compatible_base_package(monkeypatch):
|
||||
assert result["latest_version"] == "1.2.3"
|
||||
assert plugin_manager.async_get_plugins_from_market.await_args_list == [
|
||||
(("https://github.com/demo/plugins", settings.VERSION_FLAG, False), {}),
|
||||
(("https://github.com/demo/plugins", "v2", False), {}),
|
||||
(("https://github.com/demo/plugins", None, False), {}),
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user