mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
* ✨ feat(env): 支持git更新 * ✨ feat(aliyun): 更新阿里云URL构建逻辑,支持组织名称并优化令牌解码处理 * ✨ feat(config): 修改错误提示信息,更新基础配置文件名称为.env.example * ⚡ 插件商店支持aliyun * ✨ feat(store): 优化插件数据获取逻辑,合并插件列表和额外插件列表 * 🐛 修复非git仓库的初始化更新 * ✨ feat(update): 增强更新提示信息,添加非git源的变更文件说明 * 🎨 代码格式化 * ✨ webui与resources支持git更新 * ✨ feat(update): 更新webui路径处理逻辑 * Fix/test_runwork (#2001) * fix(test): 修复测试工作流 - 修改自动更新模块中的导入路径 - 更新插件商店模块中的插件信息获取逻辑 - 优化插件添加、更新和移除流程 - 统一插件相关错误信息的格式 - 调整测试用例以适应新的插件管理逻辑 * test(builtin_plugins): 重构插件商店相关测试 - 移除 jsd 相关测试用例,只保留 gh(GitHub)的测试 - 删除了 test_plugin_store.py 文件,清理了插件商店的测试 - 更新了 test_search_plugin.py 中的插件版本号 - 调整了 test_update_plugin.py 中的已加载插件版本 - 移除了 StoreManager 类中的 is_external 变量 - 更新了 RepoFileManager 类中的文件获取逻辑,优先使用 GitHub * ✨ feat(submodule): 添加子模块管理功能,支持子模块的初始化、更新和信息获取 * ✨ feat(update): 移除资源管理器,重构更新逻辑,支持通过ZhenxunRepoManager进行资源和Web UI的更新 * test(auto_update): 修改更新检测消息格式 (#2003) - 移除了不必要的版本号后缀(如 "-e6f17c4") - 统一了版本更新消息的格式,删除了冗余信息 * 🐛 修复web zip更新路径问题 * ⚡ 文件获取优化使用ali * Fix/test (#2008) * test: 修复bot测试 - 在 test_check_update.py 中跳过两个测试函数 - 移除 test_check.py 中的 mocked_api 参数和相关调用 - 删除 test_add_plugin.py 中的多个测试函数 - 移除 test_remove_plugin.py 中的 mocked_api 参数和相关调用 - 删除 test_search_plugin.py 中的多个测试函数 - 移除 test_update_all_plugin.py 和 test_update_plugin.py 中的 mocked_api 参数和相关调用 * 🚨 auto fix by pre-commit hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * 修复res zip更新路径问题 * 🐛 修复zhenxun更新zip占用问题 * ✨ feat(update): 优化资源更新逻辑,调整更新路径和消息处理 --------- Co-authored-by: molanp <104612722+molanp@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
557 lines
21 KiB
Python
557 lines
21 KiB
Python
"""
|
||
真寻仓库管理器
|
||
负责真寻主仓库的更新、版本检查、文件处理等功能
|
||
"""
|
||
|
||
import os
|
||
from pathlib import Path
|
||
import shutil
|
||
from typing import ClassVar, Literal
|
||
import zipfile
|
||
|
||
import aiofiles
|
||
|
||
from zhenxun.configs.path_config import DATA_PATH, TEMP_PATH
|
||
from zhenxun.services.log import logger
|
||
from zhenxun.utils.github_utils import GithubUtils
|
||
from zhenxun.utils.http_utils import AsyncHttpx
|
||
from zhenxun.utils.manager.virtual_env_package_manager import VirtualEnvPackageManager
|
||
from zhenxun.utils.repo_utils import AliyunRepoManager, GithubRepoManager
|
||
from zhenxun.utils.repo_utils.models import RepoUpdateResult
|
||
from zhenxun.utils.repo_utils.utils import check_git
|
||
|
||
LOG_COMMAND = "ZhenxunRepoManager"
|
||
|
||
|
||
class ZhenxunUpdateException(Exception):
|
||
"""资源下载异常"""
|
||
|
||
pass
|
||
|
||
|
||
class ZhenxunRepoConfig:
|
||
"""真寻仓库配置"""
|
||
|
||
# Zhenxun Bot 相关配置
|
||
ZHENXUN_BOT_GIT = "https://github.com/zhenxun-org/zhenxun_bot.git"
|
||
ZHENXUN_BOT_GITHUB_URL = "https://github.com/HibiKier/zhenxun_bot/tree/main"
|
||
ZHENXUN_BOT_DOWNLOAD_FILE_STRING = "zhenxun_bot.zip"
|
||
ZHENXUN_BOT_DOWNLOAD_FILE = TEMP_PATH / ZHENXUN_BOT_DOWNLOAD_FILE_STRING
|
||
ZHENXUN_BOT_UNZIP_PATH = TEMP_PATH / "zhenxun_bot"
|
||
ZHENXUN_BOT_CODE_PATH = Path() / "zhenxun"
|
||
ZHENXUN_BOT_RELEASES_API_URL = (
|
||
"https://api.github.com/repos/HibiKier/zhenxun_bot/releases/latest"
|
||
)
|
||
ZHENXUN_BOT_BACKUP_PATH = Path() / "backup"
|
||
# 需要替换的文件夹
|
||
ZHENXUN_BOT_UPDATE_FOLDERS: ClassVar[list[str]] = [
|
||
"zhenxun/builtin_plugins",
|
||
"zhenxun/services",
|
||
"zhenxun/utils",
|
||
"zhenxun/models",
|
||
"zhenxun/configs",
|
||
]
|
||
ZHENXUN_BOT_VERSION_FILE_STRING = "__version__"
|
||
ZHENXUN_BOT_VERSION_FILE = Path() / ZHENXUN_BOT_VERSION_FILE_STRING
|
||
|
||
# 备份杂项
|
||
BACKUP_FILES: ClassVar[list[str]] = [
|
||
"pyproject.toml",
|
||
"poetry.lock",
|
||
"requirements.txt",
|
||
".env.dev",
|
||
".env.example",
|
||
]
|
||
|
||
# WEB UI 相关配置
|
||
WEBUI_GIT = "https://github.com/HibiKier/zhenxun_bot_webui.git"
|
||
WEBUI_DIST_GITHUB_URL = "https://github.com/HibiKier/zhenxun_bot_webui/tree/dist"
|
||
WEBUI_DOWNLOAD_FILE_STRING = "webui_assets.zip"
|
||
WEBUI_DOWNLOAD_FILE = TEMP_PATH / WEBUI_DOWNLOAD_FILE_STRING
|
||
WEBUI_UNZIP_PATH = TEMP_PATH / "web_ui"
|
||
WEBUI_PATH = DATA_PATH / "web_ui" / "public"
|
||
WEBUI_BACKUP_PATH = DATA_PATH / "web_ui" / "backup_public"
|
||
|
||
# 资源管理相关配置
|
||
RESOURCE_GIT = "https://github.com/zhenxun-org/zhenxun-bot-resources.git"
|
||
RESOURCE_GITHUB_URL = (
|
||
"https://github.com/zhenxun-org/zhenxun-bot-resources/tree/main"
|
||
)
|
||
RESOURCE_ZIP_FILE_STRING = "resources.zip"
|
||
RESOURCE_ZIP_FILE = TEMP_PATH / RESOURCE_ZIP_FILE_STRING
|
||
RESOURCE_UNZIP_PATH = TEMP_PATH / "resources"
|
||
RESOURCE_PATH = Path() / "resources"
|
||
|
||
REQUIREMENTS_FILE_STRING = "requirements.txt"
|
||
REQUIREMENTS_FILE = Path() / REQUIREMENTS_FILE_STRING
|
||
|
||
PYPROJECT_FILE_STRING = "pyproject.toml"
|
||
PYPROJECT_FILE = Path() / PYPROJECT_FILE_STRING
|
||
|
||
PYPROJECT_LOCK_FILE_STRING = "poetry.lock"
|
||
PYPROJECT_LOCK_FILE = Path() / PYPROJECT_LOCK_FILE_STRING
|
||
|
||
|
||
class ZhenxunRepoManagerClass:
|
||
"""真寻仓库管理器"""
|
||
|
||
def __init__(self):
|
||
self.config = ZhenxunRepoConfig()
|
||
|
||
def __clear_folder(self, folder_path: Path):
|
||
"""
|
||
清空文件夹
|
||
|
||
参数:
|
||
folder_path: 文件夹路径
|
||
"""
|
||
if not folder_path.exists():
|
||
return
|
||
for filename in os.listdir(folder_path):
|
||
file_path = folder_path / filename
|
||
try:
|
||
if file_path.is_file():
|
||
os.unlink(file_path)
|
||
elif file_path.is_dir() and not filename.startswith("."):
|
||
shutil.rmtree(file_path)
|
||
except Exception as e:
|
||
logger.warning(f"无法删除 {file_path}", LOG_COMMAND, e=e)
|
||
|
||
def __copy_files(self, src_path: Path, dest_path: Path, incremental: bool = False):
|
||
"""
|
||
复制文件或文件夹
|
||
|
||
参数:
|
||
src_path: 源文件或文件夹路径
|
||
dest_path: 目标文件或文件夹路径
|
||
incremental: 是否增量复制
|
||
"""
|
||
if src_path.is_file():
|
||
shutil.copy(src_path, dest_path)
|
||
logger.debug(f"复制文件 {src_path} -> {dest_path}", LOG_COMMAND)
|
||
elif src_path.is_dir():
|
||
for filename in os.listdir(src_path):
|
||
file_path = src_path / filename
|
||
dest_file = dest_path / filename
|
||
dest_file.parent.mkdir(exist_ok=True, parents=True)
|
||
if file_path.is_file():
|
||
if dest_file.exists():
|
||
dest_file.unlink()
|
||
shutil.copy(file_path, dest_file)
|
||
logger.debug(f"复制文件 {file_path} -> {dest_file}", LOG_COMMAND)
|
||
elif file_path.is_dir():
|
||
if incremental:
|
||
self.__copy_files(file_path, dest_file, incremental=True)
|
||
else:
|
||
if dest_file.exists():
|
||
shutil.rmtree(dest_file, True)
|
||
shutil.copytree(file_path, dest_file)
|
||
logger.debug(
|
||
f"复制文件夹 {file_path} -> {dest_file}",
|
||
LOG_COMMAND,
|
||
)
|
||
|
||
# ==================== Zhenxun Bot 相关方法 ====================
|
||
|
||
async def zhenxun_get_version_from_repo(self) -> str:
|
||
"""从指定分支获取版本号
|
||
|
||
|
||
返回:
|
||
str: 版本号
|
||
"""
|
||
repo_info = GithubUtils.parse_github_url(self.config.ZHENXUN_BOT_GITHUB_URL)
|
||
version_url = await repo_info.get_raw_download_urls(
|
||
path=self.config.ZHENXUN_BOT_VERSION_FILE_STRING
|
||
)
|
||
try:
|
||
res = await AsyncHttpx.get(version_url)
|
||
if res.status_code == 200:
|
||
return res.text.strip()
|
||
except Exception as e:
|
||
logger.error(f"获取 {repo_info.branch} 分支版本失败", LOG_COMMAND, e=e)
|
||
return "未知版本"
|
||
|
||
async def zhenxun_write_version_file(self, version: str):
|
||
"""写入版本文件"""
|
||
async with aiofiles.open(
|
||
self.config.ZHENXUN_BOT_VERSION_FILE, "w", encoding="utf8"
|
||
) as f:
|
||
await f.write(f"__version__: {version}")
|
||
|
||
def __backup_zhenxun(self):
|
||
"""备份真寻文件"""
|
||
for filename in os.listdir(self.config.ZHENXUN_BOT_CODE_PATH):
|
||
file_path = self.config.ZHENXUN_BOT_CODE_PATH / filename
|
||
if file_path.exists():
|
||
self.__copy_files(
|
||
file_path,
|
||
self.config.ZHENXUN_BOT_BACKUP_PATH / filename,
|
||
True,
|
||
)
|
||
for filename in self.config.BACKUP_FILES:
|
||
file_path = Path() / filename
|
||
if file_path.exists():
|
||
self.__copy_files(
|
||
file_path,
|
||
self.config.ZHENXUN_BOT_BACKUP_PATH / filename,
|
||
)
|
||
|
||
async def zhenxun_get_latest_releases_data(self) -> dict:
|
||
"""获取真寻releases最新版本信息
|
||
|
||
返回:
|
||
dict: 最新版本数据
|
||
"""
|
||
try:
|
||
res = await AsyncHttpx.get(self.config.ZHENXUN_BOT_RELEASES_API_URL)
|
||
if res.status_code == 200:
|
||
return res.json()
|
||
except Exception as e:
|
||
logger.error("检查更新真寻获取版本失败", LOG_COMMAND, e=e)
|
||
return {}
|
||
|
||
async def zhenxun_download_zip(self, ver_type: Literal["main", "release"]) -> str:
|
||
"""下载真寻最新版文件
|
||
|
||
参数:
|
||
ver_type: 版本类型,main 为最新版,release 为最新release版
|
||
|
||
返回:
|
||
str: 版本号
|
||
"""
|
||
repo_info = GithubUtils.parse_github_url(self.config.ZHENXUN_BOT_GITHUB_URL)
|
||
if ver_type == "main":
|
||
download_url = await repo_info.get_archive_download_urls()
|
||
new_version = await self.zhenxun_get_version_from_repo()
|
||
else:
|
||
release_data = await self.zhenxun_get_latest_releases_data()
|
||
logger.debug(f"获取真寻RELEASES最新版本信息: {release_data}", LOG_COMMAND)
|
||
if not release_data:
|
||
raise ZhenxunUpdateException("获取真寻RELEASES最新版本失败...")
|
||
new_version = release_data.get("name", "")
|
||
download_url = await repo_info.get_release_source_download_urls_tgz(
|
||
new_version
|
||
)
|
||
if not download_url:
|
||
raise ZhenxunUpdateException("获取真寻最新版文件下载链接失败...")
|
||
if self.config.ZHENXUN_BOT_DOWNLOAD_FILE.exists():
|
||
self.config.ZHENXUN_BOT_DOWNLOAD_FILE.unlink()
|
||
if await AsyncHttpx.download_file(
|
||
download_url, self.config.ZHENXUN_BOT_DOWNLOAD_FILE, stream=True
|
||
):
|
||
logger.debug("下载真寻最新版文件完成...", LOG_COMMAND)
|
||
else:
|
||
raise ZhenxunUpdateException("下载真寻最新版文件失败...")
|
||
return new_version
|
||
|
||
async def zhenxun_unzip(self):
|
||
"""解压真寻最新版文件"""
|
||
if not self.config.ZHENXUN_BOT_DOWNLOAD_FILE.exists():
|
||
raise FileNotFoundError("真寻最新版文件不存在")
|
||
if self.config.ZHENXUN_BOT_UNZIP_PATH.exists():
|
||
shutil.rmtree(self.config.ZHENXUN_BOT_UNZIP_PATH)
|
||
tf = None
|
||
try:
|
||
tf = zipfile.ZipFile(self.config.ZHENXUN_BOT_DOWNLOAD_FILE)
|
||
tf.extractall(self.config.ZHENXUN_BOT_UNZIP_PATH)
|
||
logger.debug("解压Zhenxun Bot文件压缩包完成!", LOG_COMMAND)
|
||
self.__backup_zhenxun()
|
||
for filename in self.config.BACKUP_FILES:
|
||
self.__copy_files(
|
||
self.config.ZHENXUN_BOT_UNZIP_PATH / filename,
|
||
Path() / filename,
|
||
)
|
||
logger.debug("备份真寻更新文件完成!", LOG_COMMAND)
|
||
unzip_dir = next(self.config.ZHENXUN_BOT_UNZIP_PATH.iterdir())
|
||
for folder in self.config.ZHENXUN_BOT_UPDATE_FOLDERS:
|
||
self.__copy_files(unzip_dir / folder, Path() / folder)
|
||
logger.debug("移动真寻更新文件完成!", LOG_COMMAND)
|
||
if self.config.ZHENXUN_BOT_UNZIP_PATH.exists():
|
||
shutil.rmtree(self.config.ZHENXUN_BOT_UNZIP_PATH)
|
||
except Exception as e:
|
||
logger.error("解压真寻最新版文件失败...", LOG_COMMAND, e=e)
|
||
raise
|
||
finally:
|
||
if tf:
|
||
tf.close()
|
||
|
||
async def zhenxun_zip_update(self, ver_type: Literal["main", "release"]) -> str:
|
||
"""使用zip更新真寻
|
||
|
||
参数:
|
||
ver_type: 版本类型,main 为最新版,release 为最新release版
|
||
|
||
返回:
|
||
str: 版本号
|
||
"""
|
||
new_version = await self.zhenxun_download_zip(ver_type)
|
||
await self.zhenxun_unzip()
|
||
await self.zhenxun_write_version_file(new_version)
|
||
return new_version
|
||
|
||
async def zhenxun_git_update(
|
||
self, source: Literal["git", "ali"], branch: str = "main", force: bool = False
|
||
) -> RepoUpdateResult:
|
||
"""使用git或阿里云更新真寻
|
||
|
||
参数:
|
||
source: 更新源,git 为 git 更新,ali 为阿里云更新
|
||
branch: 分支名称
|
||
force: 是否强制更新
|
||
"""
|
||
if source == "git":
|
||
return await GithubRepoManager.update_via_git(
|
||
self.config.ZHENXUN_BOT_GIT,
|
||
Path(),
|
||
branch=branch,
|
||
force=force,
|
||
)
|
||
else:
|
||
return await AliyunRepoManager.update_via_git(
|
||
self.config.ZHENXUN_BOT_GIT,
|
||
Path(),
|
||
branch=branch,
|
||
force=force,
|
||
)
|
||
|
||
async def zhenxun_update(
|
||
self,
|
||
source: Literal["git", "ali"] = "ali",
|
||
branch: str = "main",
|
||
force: bool = False,
|
||
ver_type: Literal["main", "release"] = "main",
|
||
):
|
||
"""更新真寻
|
||
|
||
参数:
|
||
source: 更新源,git 为 git 更新,ali 为阿里云更新
|
||
branch: 分支名称
|
||
force: 是否强制更新
|
||
ver_type: 版本类型,main 为最新版,release 为最新release版
|
||
"""
|
||
if await check_git():
|
||
await self.zhenxun_git_update(source, branch, force)
|
||
logger.debug("使用git更新真寻!", LOG_COMMAND)
|
||
else:
|
||
await self.zhenxun_zip_update(ver_type)
|
||
logger.debug("使用zip更新真寻!", LOG_COMMAND)
|
||
|
||
async def install_requirements(self):
|
||
"""安装真寻依赖"""
|
||
await VirtualEnvPackageManager.install_requirement(
|
||
self.config.REQUIREMENTS_FILE
|
||
)
|
||
|
||
# ==================== 资源管理相关方法 ====================
|
||
|
||
def check_resources_exists(self) -> bool:
|
||
"""检查资源文件是否存在
|
||
|
||
返回:
|
||
bool: 是否存在
|
||
"""
|
||
if self.config.RESOURCE_PATH.exists():
|
||
font_path = self.config.RESOURCE_PATH / "font"
|
||
if font_path.exists() and os.listdir(font_path):
|
||
return True
|
||
return False
|
||
|
||
async def resources_download_zip(self):
|
||
"""下载资源文件"""
|
||
download_url = await GithubUtils.parse_github_url(
|
||
self.config.RESOURCE_GITHUB_URL
|
||
).get_archive_download_urls()
|
||
logger.debug("开始下载resources资源包...", LOG_COMMAND)
|
||
if await AsyncHttpx.download_file(
|
||
download_url, self.config.RESOURCE_ZIP_FILE, stream=True
|
||
):
|
||
logger.debug("下载resources资源文件压缩包成功!", LOG_COMMAND)
|
||
else:
|
||
raise ZhenxunUpdateException("下载resources资源包失败...")
|
||
|
||
async def resources_unzip(self):
|
||
"""解压资源文件"""
|
||
if not self.config.RESOURCE_ZIP_FILE.exists():
|
||
raise FileNotFoundError("资源文件压缩包不存在")
|
||
if self.config.RESOURCE_UNZIP_PATH.exists():
|
||
shutil.rmtree(self.config.RESOURCE_UNZIP_PATH)
|
||
tf = None
|
||
try:
|
||
tf = zipfile.ZipFile(self.config.RESOURCE_ZIP_FILE)
|
||
tf.extractall(self.config.RESOURCE_UNZIP_PATH)
|
||
logger.debug("解压文件压缩包完成...", LOG_COMMAND)
|
||
unzip_dir = next(self.config.RESOURCE_UNZIP_PATH.iterdir())
|
||
self.__copy_files(unzip_dir, self.config.RESOURCE_PATH, True)
|
||
logger.debug("复制资源文件完成!", LOG_COMMAND)
|
||
shutil.rmtree(self.config.RESOURCE_UNZIP_PATH, ignore_errors=True)
|
||
except Exception as e:
|
||
logger.error("解压资源文件失败...", LOG_COMMAND, e=e)
|
||
raise
|
||
finally:
|
||
if tf:
|
||
tf.close()
|
||
|
||
async def resources_zip_update(self):
|
||
"""使用zip更新资源文件"""
|
||
await self.resources_download_zip()
|
||
await self.resources_unzip()
|
||
|
||
async def resources_git_update(
|
||
self, source: Literal["git", "ali"], branch: str = "main", force: bool = False
|
||
) -> RepoUpdateResult:
|
||
"""使用git或阿里云更新资源文件
|
||
|
||
参数:
|
||
source: 更新源,git 为 git 更新,ali 为阿里云更新
|
||
branch: 分支名称
|
||
force: 是否强制更新
|
||
"""
|
||
if source == "git":
|
||
return await GithubRepoManager.update_via_git(
|
||
self.config.RESOURCE_GIT,
|
||
self.config.RESOURCE_PATH,
|
||
branch=branch,
|
||
force=force,
|
||
)
|
||
else:
|
||
return await AliyunRepoManager.update_via_git(
|
||
self.config.RESOURCE_GIT,
|
||
self.config.RESOURCE_PATH,
|
||
branch=branch,
|
||
force=force,
|
||
)
|
||
|
||
async def resources_update(
|
||
self,
|
||
source: Literal["git", "ali"] = "ali",
|
||
branch: str = "main",
|
||
force: bool = False,
|
||
):
|
||
"""更新资源文件
|
||
|
||
参数:
|
||
source: 更新源,git 为 git 更新,ali 为阿里云更新
|
||
branch: 分支名称
|
||
force: 是否强制更新
|
||
"""
|
||
if await check_git():
|
||
await self.resources_git_update(source, branch, force)
|
||
logger.debug("使用git更新资源文件!", LOG_COMMAND)
|
||
else:
|
||
await self.resources_zip_update()
|
||
logger.debug("使用zip更新资源文件!", LOG_COMMAND)
|
||
|
||
# ==================== Web UI 管理相关方法 ====================
|
||
|
||
def check_webui_exists(self) -> bool:
|
||
"""检查 Web UI 资源是否存在"""
|
||
return bool(
|
||
self.config.WEBUI_PATH.exists() and os.listdir(self.config.WEBUI_PATH)
|
||
)
|
||
|
||
async def webui_download_zip(self):
|
||
"""下载 WEBUI_ASSETS 资源"""
|
||
download_url = await GithubUtils.parse_github_url(
|
||
self.config.WEBUI_DIST_GITHUB_URL
|
||
).get_archive_download_urls()
|
||
logger.info("开始下载 WEBUI_ASSETS 资源...", LOG_COMMAND)
|
||
if await AsyncHttpx.download_file(
|
||
download_url, self.config.WEBUI_DOWNLOAD_FILE, follow_redirects=True
|
||
):
|
||
logger.info("下载 WEBUI_ASSETS 成功!", LOG_COMMAND)
|
||
else:
|
||
raise ZhenxunUpdateException("下载 WEBUI_ASSETS 失败", LOG_COMMAND)
|
||
|
||
def __backup_webui(self):
|
||
"""备份 WEBUI_ASSERT 资源"""
|
||
if self.config.WEBUI_PATH.exists():
|
||
if self.config.WEBUI_BACKUP_PATH.exists():
|
||
logger.debug(
|
||
f"删除旧的备份webui文件夹 {self.config.WEBUI_BACKUP_PATH}",
|
||
LOG_COMMAND,
|
||
)
|
||
shutil.rmtree(self.config.WEBUI_BACKUP_PATH)
|
||
shutil.copytree(self.config.WEBUI_PATH, self.config.WEBUI_BACKUP_PATH)
|
||
|
||
async def webui_unzip(self):
|
||
"""解压 WEBUI_ASSETS 资源
|
||
|
||
返回:
|
||
str: 更新结果
|
||
"""
|
||
if not self.config.WEBUI_DOWNLOAD_FILE.exists():
|
||
raise FileNotFoundError("webui文件压缩包不存在")
|
||
tf = None
|
||
try:
|
||
self.__backup_webui()
|
||
self.__clear_folder(self.config.WEBUI_PATH)
|
||
tf = zipfile.ZipFile(self.config.WEBUI_DOWNLOAD_FILE)
|
||
tf.extractall(self.config.WEBUI_UNZIP_PATH)
|
||
logger.debug("Web UI 解压文件压缩包完成...", LOG_COMMAND)
|
||
unzip_dir = next(self.config.WEBUI_UNZIP_PATH.iterdir())
|
||
self.__copy_files(unzip_dir, self.config.WEBUI_PATH)
|
||
logger.debug("Web UI 复制 WEBUI_ASSETS 成功!", LOG_COMMAND)
|
||
shutil.rmtree(self.config.WEBUI_UNZIP_PATH, ignore_errors=True)
|
||
except Exception as e:
|
||
if self.config.WEBUI_BACKUP_PATH.exists():
|
||
self.__copy_files(self.config.WEBUI_BACKUP_PATH, self.config.WEBUI_PATH)
|
||
logger.debug("恢复备份 WEBUI_ASSETS 成功!", LOG_COMMAND)
|
||
shutil.rmtree(self.config.WEBUI_BACKUP_PATH, ignore_errors=True)
|
||
logger.error("Web UI 更新失败", LOG_COMMAND, e=e)
|
||
raise
|
||
finally:
|
||
if tf:
|
||
tf.close()
|
||
|
||
async def webui_zip_update(self):
|
||
"""使用zip更新 Web UI"""
|
||
await self.webui_download_zip()
|
||
await self.webui_unzip()
|
||
|
||
async def webui_git_update(
|
||
self, source: Literal["git", "ali"], branch: str = "dist", force: bool = False
|
||
) -> RepoUpdateResult:
|
||
"""使用git或阿里云更新 Web UI
|
||
|
||
参数:
|
||
source: 更新源,git 为 git 更新,ali 为阿里云更新
|
||
branch: 分支名称
|
||
force: 是否强制更新
|
||
"""
|
||
if source == "git":
|
||
return await GithubRepoManager.update_via_git(
|
||
self.config.WEBUI_GIT,
|
||
self.config.WEBUI_PATH,
|
||
branch=branch,
|
||
force=force,
|
||
)
|
||
else:
|
||
return await AliyunRepoManager.update_via_git(
|
||
self.config.WEBUI_GIT,
|
||
self.config.WEBUI_PATH,
|
||
branch=branch,
|
||
force=force,
|
||
)
|
||
|
||
async def webui_update(
|
||
self,
|
||
source: Literal["git", "ali"] = "ali",
|
||
branch: str = "dist",
|
||
force: bool = False,
|
||
):
|
||
"""更新 Web UI
|
||
|
||
参数:
|
||
source: 更新源,git 为 git 更新,ali 为阿里云更新
|
||
"""
|
||
if await check_git():
|
||
await self.webui_git_update(source, branch, force)
|
||
logger.debug("使用git更新Web UI!", LOG_COMMAND)
|
||
else:
|
||
await self.webui_zip_update()
|
||
logger.debug("使用zip更新Web UI!", LOG_COMMAND)
|
||
|
||
|
||
ZhenxunRepoManager = ZhenxunRepoManagerClass()
|