mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-11 15:00:00 +08:00
fix(plugin-store-downlaod): 修复插件商店下载二进制文件错误 (#2152)
* fix(plugin-store-downlaod): 修复插件商店下载二进制文件错误 * fix(plugin_store): 修复插件商店中仓库类型判断逻辑错误 当处理外部插件时,修正了仓库类型的判断条件,确保正确的仓库类型被设置。 同时修复了目录文件列表获取时传递错误的仓库类型参数问题。 * feat(repo_utils): 更新文件管理器返回类型并改进仓库URL处理 - 将 RepoFileManager 的文件内容返回类型从 bytes 改为 str, 统一字符串类型的返回值格式 - 支持在 repo_url 中直接包含 /tree/<branch> 路径, 自动解析分支信息并正确处理仓库地址 - 改进 GitHub 和阿里云仓库的优先级顺序, 现在优先尝试阿里云然后是 GitHub - 修复 clone_url 处理逻辑,确保正确的 .git 后缀添加 - 移除未使用的 Sequence 类型导入,统一使用 list[str] 类型注解 * refactor(plugin_store): 移除StoreManager中不必要的repo_type参数 移除了data_source.py文件中StoreManager类的list_directory_files方法调用时 多余的repo_type=RepoType.GITHUB参数 * feat(plugin_store): 优化插件依赖文件下载和安装逻辑 - 移动依赖文件下载逻辑到下载阶段,避免重复下载 - 使用随机数生成唯一的临时依赖文件名以避免冲突 - 添加ignore_error参数来处理依赖文件下载失败的情况 - 统一依赖文件路径变量命名,提高代码可读性 - 确保requirement.txt和requirements.txt都能正确安装 * Add repo_type parameter to list_directory_files call
This commit is contained in:
@@ -48,20 +48,20 @@ async def clean_git(cwd: Path):
|
||||
|
||||
|
||||
async def run_git_command(
|
||||
command: str, cwd: Path | None = None
|
||||
command: str | list[str], cwd: Path | None = None
|
||||
) -> tuple[bool, str, str]:
|
||||
"""
|
||||
运行git命令,实时输出 stderr 进度信息(如 git clone --progress)。
|
||||
|
||||
参数:
|
||||
command: 命令
|
||||
command: 命令字符串或参数列表
|
||||
cwd: 工作目录
|
||||
|
||||
返回:
|
||||
tuple[bool, str, str]: (是否成功, 标准输出, 标准错误)
|
||||
"""
|
||||
try:
|
||||
args = command.split()
|
||||
args = command.split() if isinstance(command, str) else list(command)
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"git",
|
||||
*args,
|
||||
@@ -190,17 +190,21 @@ def filter_files(
|
||||
async def sparse_checkout_clone(
|
||||
repo_url: str,
|
||||
branch: str,
|
||||
sparse_path: str,
|
||||
sparse_path: str | list[str],
|
||||
target_dir: Path,
|
||||
) -> None:
|
||||
) -> list[str]:
|
||||
"""
|
||||
使用 git 稀疏检出克隆指定路径到目标目录(在临时目录中操作)。
|
||||
|
||||
关键保障:
|
||||
- 在临时目录中执行所有 git 操作,避免影响 target_dir 中的现有内容
|
||||
- 只操作 target_dir/sparse_path 路径,不影响 target_dir 其他内容
|
||||
|
||||
返回:
|
||||
list[str]: 成功检出的路径
|
||||
"""
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
sparse_paths = [sparse_path] if isinstance(sparse_path, str) else list(sparse_path)
|
||||
|
||||
if not await check_git():
|
||||
raise GitUnavailableError()
|
||||
@@ -214,7 +218,7 @@ async def sparse_checkout_clone(
|
||||
if not success:
|
||||
raise RuntimeError(f"git init 失败: {err or out}")
|
||||
success, out, err = await run_git_command(
|
||||
f"remote add origin {repo_url}", temp_path
|
||||
["remote", "add", "origin", repo_url], temp_path
|
||||
)
|
||||
if not success:
|
||||
raise RuntimeError(f"添加远程失败: {err or out}")
|
||||
@@ -224,55 +228,59 @@ async def sparse_checkout_clone(
|
||||
await run_git_command("sparse-checkout init --no-cone", temp_path)
|
||||
|
||||
# 设置需要检出的路径(每次都覆盖配置)
|
||||
if not sparse_path:
|
||||
if not sparse_paths or any(not path for path in sparse_paths):
|
||||
raise RuntimeError("sparse-checkout 路径不能为空")
|
||||
|
||||
# 使用 --no-cone 模式,直接指定要检出的具体路径
|
||||
success, out, err = await run_git_command(
|
||||
f"sparse-checkout set {sparse_path}/", temp_path
|
||||
["sparse-checkout", "set", "--", *sparse_paths], temp_path
|
||||
)
|
||||
if not success:
|
||||
raise RuntimeError(f"配置稀疏路径失败: {err or out}")
|
||||
|
||||
# 强制拉取并同步到远端
|
||||
success, out, err = await run_git_command(
|
||||
f"fetch --force --depth 1 origin {branch}", temp_path
|
||||
["fetch", "--force", "--depth", "1", "origin", branch], temp_path
|
||||
)
|
||||
if not success:
|
||||
raise RuntimeError(f"fetch 失败: {err or out}")
|
||||
|
||||
# 使用远端强制更新本地分支并覆盖工作区
|
||||
success, out, err = await run_git_command(
|
||||
f"checkout -B {branch} origin/{branch}", temp_path
|
||||
["checkout", "-B", branch, f"origin/{branch}"], temp_path
|
||||
)
|
||||
if not success:
|
||||
# 回退方案
|
||||
success2, out2, err2 = await run_git_command(
|
||||
f"checkout {branch}", temp_path
|
||||
["checkout", branch], temp_path
|
||||
)
|
||||
if not success2:
|
||||
raise RuntimeError(f"checkout 失败: {(err or out) or (err2 or out2)}")
|
||||
|
||||
# 强制对齐工作区
|
||||
await run_git_command(f"reset --hard origin/{branch}", temp_path)
|
||||
await run_git_command(["reset", "--hard", f"origin/{branch}"], temp_path)
|
||||
await run_git_command("clean -xdf", temp_path)
|
||||
|
||||
# 将检出的文件移动到目标位置
|
||||
source_path = temp_path / sparse_path
|
||||
if source_path.exists():
|
||||
# 确保目标路径存在
|
||||
target_path = target_dir / sparse_path
|
||||
target_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
# 将成功检出的文件复制到 staging,缺失路径由调用方决定是否忽略
|
||||
downloaded_paths = []
|
||||
for path in sparse_paths:
|
||||
source_path = temp_path / path
|
||||
if not source_path.exists():
|
||||
continue
|
||||
|
||||
# 如果目标路径已存在,先清理
|
||||
target_path = target_dir / path
|
||||
target_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if target_path.exists():
|
||||
if target_path.is_dir():
|
||||
shutil.rmtree(target_path)
|
||||
else:
|
||||
target_path.unlink()
|
||||
|
||||
# 移动整个目录结构到目标位置
|
||||
shutil.move(str(source_path), str(target_path))
|
||||
if source_path.is_dir():
|
||||
shutil.copytree(source_path, target_path)
|
||||
else:
|
||||
shutil.copy2(source_path, target_path)
|
||||
downloaded_paths.append(path)
|
||||
return downloaded_paths
|
||||
|
||||
|
||||
def prepare_aliyun_url(repo_url: str, group_name: str | None = None) -> str:
|
||||
|
||||
Reference in New Issue
Block a user