feat(core): M150 新增 GitHub Releases 更新源(D50)
D50 定案 GitHub Releases 为唯一更新源,清单地址固定为 `releases/latest/download/manifest.json`。此前 update 模块只有对拍用的 DirSource,这次把真实源补上。 - `update::github::GitHubReleaseSource` 实现 `UpdateSource`:清单从 `<base>/<owner>/<repo>/releases/latest/download/manifest.json` 取, 产物按 D49 命名规则(文件名)拼到同一条 latest/download 路径下;清单里 已写完整 http(s) 地址的原样使用。 - 网络全走 `core::download`,不新造栈:包体交给引擎 `download()`(镜像展开 → 地区判定 → 健康度排序 → 退避 → 续传 → 原子落盘),清单走引擎的 `plan()` + 共享 client 逐候选取文本(与 `game::java` 的一锤子 GET 同一手法)。 两条路径都吃到 mirrors.json 与地区档案里生效的 gh-proxy 前缀。 - 可配置面只有 owner/repo(默认 AskaEth/Unlucky-Launcher)与 base(默认 https://github.com,测试指向本地假服务);渠道只有 stable 有清单, beta/alpha/nightly 返回 Ok(None)(D50「先只发 stable」),清单 404 也算 「还没发布」而不是错误。 - `UpdateErrorKind` 新增 `Network`:远端取字节失败(连不上/超时/5xx/候选全挂) 与本地 IO 分开——前者可重试,后者重试无意义。引擎把逐源失败压成 AllSourcesFailed,本源从失败摘要里还原「所有源都 404」为 SourceMissing (产物没上传不该被报成网络抖动)。 - 校验仍只有一处:包体请求只带 expected_size,长度/摘要双检留在 `update::verify`(与 DirSource 同口径)。 - 单测 13 条,全程离线(假 HTTP 服务在 127.0.0.1):固定清单地址、产物 URL 解析、自定义 base/owner/repo、清单 404/非 JSON/字段非法/渠道不符/5xx 各自 归到白名单分类、产物下载、产物 404 → SourceMissing、镜像优先下 gh-proxy 前缀(清单与产物都验)、与 DirSource 同清单同产物选择结果一致。
This commit is contained in:
1 parent
afdbc9fd51
commit
f001b93942
7 files changed
+945
-18
No files matched your search
@@ -22,6 +22,11 @@ pub enum UpdateErrorKind {
|
||||
SourceMissing,
|
||||
/// 更新源协议不支持(例如本地目录源里出现了 `http://` 地址)。
|
||||
UnsupportedSource,
|
||||
/// 远端源取字节失败:连不上、超时、5xx、所有候选源(含镜像)全挂。
|
||||
///
|
||||
/// 与 [`Self::Io`] 分开是因为处置不同:网络失败值得隔一会儿重试/换镜像,
|
||||
/// 本地 IO 失败(盘满、没权限)重试多少次都一样。
|
||||
Network,
|
||||
/// 本地 IO 失败:读源、写暂存、替换落盘。
|
||||
Io,
|
||||
/// 摘要不符:拿到的字节与清单声明的不是同一份。
|
||||
@@ -40,6 +45,7 @@ impl UpdateErrorKind {
|
||||
Self::ChannelMismatch => "channel_mismatch",
|
||||
Self::SourceMissing => "source_missing",
|
||||
Self::UnsupportedSource => "unsupported_source",
|
||||
Self::Network => "network",
|
||||
Self::Io => "io",
|
||||
Self::DigestMismatch => "digest_mismatch",
|
||||
Self::SizeMismatch => "size_mismatch",
|
||||
@@ -48,11 +54,14 @@ impl UpdateErrorKind {
|
||||
|
||||
/// 换个源 / 重下一次是否可能变好(调用方据此决定重试,别在这里写死重试次数)。
|
||||
///
|
||||
/// 清单本身不合法、协议不支持、目标平台无权写盘这三类换多少源都一样,
|
||||
/// 所以只有字节层(摘要/长度)与 IO(可能是瞬时占用)算可重试。
|
||||
/// 清单本身不合法、协议不支持、渠道不符这几类换多少源都一样,所以只有字节层
|
||||
/// (摘要/长度)、网络(可能是瞬时抖动)与 IO(可能是瞬时占用)算可重试。
|
||||
#[must_use]
|
||||
pub const fn is_retryable(self) -> bool {
|
||||
matches!(self, Self::DigestMismatch | Self::SizeMismatch | Self::Io)
|
||||
matches!(
|
||||
self,
|
||||
Self::DigestMismatch | Self::SizeMismatch | Self::Network | Self::Io
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user