fix(download): M294 r1 —— JDK 下载页与 CLI 也接上源选择,文档同步
复审 p1:发布版 GUI 的「下载 JDK」页是第二处 DownloadEngine::new(要 with_progress 拿走引擎),此前只读了 gh_proxy,region / mirror_preference 到不了那里;报告却把 GUI 写成「已接」。复审 p2:CLI 四条命令同样不认这两个键 —— 同一份 launcher.json 在 GUI 与 CLI 上表现不同,等于把「设置项说假话」挪到 CLI 侧。 - app-iced downloads/engine.rs:新增 SourceSelection(只读键、不翻译)+ engine_with(.., &SourceSelection),在 gh-proxy 三态之前叠 DownloadTuning::with_source_selection(..).apply_source_selection(..) - Request 加 source_selection 字段,构造点(app/update/settings/java/downloads.rs) 用 SourceSelection::of_config(&config) 显式传值(不从缓存根反推配置路径: 反推失败会静默按 auto 收场,正是本 mission 要消灭的形状) - cli download.rs 的 tuning():链 .with_source_selection(..),四条命令共用这一处装配 - core 的 summary():把「地区 / 镜像偏好」两档印进 CLI 那行生效值(CLI 既然读了, 少印两项就是新的半真话) - shared.rs 注释说清「共享引擎」与本文件的第二处装配点;app-iced 模块头补对照表 - 新判据:JDK 下载页与 CLI 各一条断候选源顺序的用例,均配变异验证(换回裸 EngineConfig::default() / 裸 tuning 即红);补一条 region=cn + gh_proxy=off 的 叠加次序守卫(复审 P3-2) - docs/download-settings.md:§1 表格两行、§5 拆「已接 / 未接」、新增 §3.1.1 覆盖面 表、§6 补 M14-M16 三条变异、§7 补「镜像可达性没验」 连带(不加就编不过,已报备 tower):downloads/tests.rs 的 Request 字面量 +1 行、 downloads/tests/gh_proxy.rs 两处 engine_with 调用点补第四参。
This commit is contained in:
1 parent
0f64acbd05
commit
69e3e198bf
11 files changed
+395
-36
No files matched your search
@@ -14,6 +14,11 @@
|
||||
//! → shared::engine_with_tuning(<cache 根>, tuning) → 引擎的 Semaphore / attempts_for() / 三段超时
|
||||
//! ```
|
||||
//!
|
||||
//! M294 r1:`download.region` / `download.mirror_preference` 走**同一条链**(入口是
|
||||
//! [`DownloadTuning::with_source_selection`],与 presenter 的 `tuning_of` 同一个),落成引擎的
|
||||
//! `RegionProfile`(候选源的先后)。在此之前 CLI 的四条命令认不到这两个键,同一份
|
||||
//! `launcher.json` 在 GUI 与 CLI 上表现不同——「设置项说假话」只是从 GUI 挪到了 CLI。
|
||||
//!
|
||||
//! M292:`download.*` 从三个键扩到六个(多了吞吐下限 / 无进展窗口 / 单次请求上界),装配链没变,
|
||||
//! 变的是 [`tuning`] 取值的宽度与 [`engine`] 里那一行**仅在改过设置时**才打的 stderr 说明——用户在
|
||||
//! 慢链路上改完设置,得能在终端里看见引擎实际拿到了什么(P21 的验收判据;为什么不是写
|
||||
@@ -26,7 +31,7 @@ use std::sync::Arc;
|
||||
|
||||
use unlucky_core::download::config::{
|
||||
DownloadTuning, RawTuning, KEY_CHUNK_STALL, KEY_CONCURRENCY, KEY_GH_PROXY,
|
||||
KEY_RESPONSE_TIMEOUT, KEY_RETRY_LIMIT, KEY_THROUGHPUT_FLOOR,
|
||||
KEY_MIRROR_PREFERENCE, KEY_REGION, KEY_RESPONSE_TIMEOUT, KEY_RETRY_LIMIT, KEY_THROUGHPUT_FLOOR,
|
||||
};
|
||||
use unlucky_core::download::{shared, DownloadEngine};
|
||||
use unlucky_core::setting::keys::launcher_schema;
|
||||
@@ -34,7 +39,7 @@ use unlucky_core::setting::store::SettingStore;
|
||||
|
||||
use crate::context::Ctx;
|
||||
|
||||
/// 从 CLI 自己的 setting store 读下载调优(`launcher.json` 的六个 `download.*` 键)。
|
||||
/// 从 CLI 自己的 setting store 读下载调优(`launcher.json` 的八个 `download.*` 键)。
|
||||
///
|
||||
/// 读的是 `ctx.launcher_config()`——与 `ull config set download.concurrency` 的落点同一份文件
|
||||
/// (设置键的落点分流见 [`Ctx::setting_path_for`])。gh-proxy 空串 = 跟随内置默认,**不是**关。
|
||||
@@ -42,6 +47,11 @@ use crate::context::Ctx;
|
||||
/// **本函数只做「取裸值」**:默认值、区间、回落、KiB→字节的换算全在 core 的
|
||||
/// [`DownloadTuning::from_raw`](M292 起宿主不再逐个判断,也不再自己决定缺省值——那是「UI 说 8、
|
||||
/// 引擎跑 64」长回来的地方)。
|
||||
///
|
||||
/// M294 r1:`download.region` / `download.mirror_preference` 也在这里读,但**不经过
|
||||
/// [`RawTuning`]**——那两个是枚举,翻译层是 core 的 [`DownloadTuning::with_source_selection`]
|
||||
/// (未知值回落 `auto`)。CLI 与 presenter 走的是同一个入口,别在宿主里再写一份字符串匹配:
|
||||
/// 两份口径就是「GUI 认、CLI 不认」的下一次复发。
|
||||
#[must_use]
|
||||
pub(crate) fn tuning(ctx: &Ctx) -> DownloadTuning {
|
||||
let store = SettingStore::load(ctx.launcher_config(), launcher_schema());
|
||||
@@ -58,6 +68,10 @@ pub(crate) fn tuning(ctx: &Ctx) -> DownloadTuning {
|
||||
stall_timeout_secs: doc.effective_i64(KEY_CHUNK_STALL),
|
||||
response_timeout_secs: doc.effective_i64(KEY_RESPONSE_TIMEOUT),
|
||||
})
|
||||
.with_source_selection(
|
||||
doc.effective_str(KEY_REGION),
|
||||
doc.effective_str(KEY_MIRROR_PREFERENCE),
|
||||
)
|
||||
}
|
||||
|
||||
/// 生效值那一行说明,**只在改过设置时**给:`None` = 全是出厂值,没什么可说的。
|
||||
|
||||
@@ -343,3 +343,49 @@ fn the_timeout_settings_reach_the_engine_and_the_console_line() {
|
||||
assert_eq!(super::tuning(&ctx), DownloadTuning::default());
|
||||
assert!(super::announce(&super::tuning(&ctx)).is_none());
|
||||
}
|
||||
|
||||
/// 一个 URL 在 CLI 装配出来的引擎里的**源名顺序**(`plan()` 是引擎真正的选源决策点)。
|
||||
fn plan_sources(engine: &DownloadEngine) -> Vec<String> {
|
||||
let url = "https://libraries.minecraft.net/com/google/guava/guava/32.0.0/guava-32.0.0.jar";
|
||||
let dest = std::env::temp_dir().join("ull-cli-plan-guava.jar");
|
||||
let request = DownloadRequest::new(ResourceKind::Library, url.to_string(), dest);
|
||||
engine
|
||||
.plan(&request, 0)
|
||||
.into_iter()
|
||||
.map(|c| c.source)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// **M294 r1(P2-1)**:两键进 CLI 四条命令的生产装配点,终端那行说明也含它们。
|
||||
///
|
||||
/// 判据是**候选顺序**:两段都让设置与探测结论相反,没接上时必红(变异:`download-settings.md` M15)。
|
||||
#[test]
|
||||
fn the_source_selection_settings_reach_the_cli_engine() {
|
||||
use unlucky_core::download::region::{store_cached, RegionProfile};
|
||||
|
||||
let dir = TempDir::new("source-selection");
|
||||
let ctx = ctx_at(&dir);
|
||||
let cache = ctx.layout().cache();
|
||||
std::fs::create_dir_all(&cache).expect("建缓存根");
|
||||
let now = unlucky_core::download::cache::now_ms();
|
||||
let region_json = cache.join("region.json");
|
||||
|
||||
// 探测=镜像优先 + 设置 official ⇒ 官方第一条(未接线时是 bmclapi)。
|
||||
store_cached(®ion_json, &RegionProfile::mirror_first(now)).expect("档案");
|
||||
let mirror = json!({ "download": { "mirror_preference": "official" } });
|
||||
write_launcher_config(&ctx, mirror);
|
||||
let engine = crate::commands::install::build_engine(&ctx);
|
||||
assert_eq!(plan_sources(&engine), ["official", "bmclapi"], "官方第一条");
|
||||
let line = super::announce(&super::tuning(&ctx)).expect("该有一行");
|
||||
assert!(line.contains("镜像偏好=official"), "{line}");
|
||||
assert!(line.contains("地区=auto"), "{line}");
|
||||
|
||||
// 探测=直连 + 设置 cn ⇒ 镜像第一条(未接线时是 official)。
|
||||
store_cached(®ion_json, &RegionProfile::direct(now)).expect("档案");
|
||||
write_launcher_config(&ctx, json!({ "download": { "region": "cn" } }));
|
||||
let engine = crate::commands::install::build_engine(&ctx);
|
||||
assert_eq!(plan_sources(&engine), ["bmclapi", "official"], "镜像第一条");
|
||||
let line = super::announce(&super::tuning(&ctx)).expect("该有一行");
|
||||
assert!(line.contains("地区=cn"), "{line}");
|
||||
assert!(line.contains("镜像偏好=auto"), "{line}");
|
||||
}
|
||||
Reference in new issue
Block a user