fix(coexist): 复审 r1 返工——帮助文案跟上新落点 + 「替换了清单」进人读通道 + 导入建实例绑到内容目录(M216 P2/P3/§5)
P2-1 ② 改了缺省落点,CLI 自己的文档还在写旧行为 - `cli/help.rs`「目标目录缺省 = 数据根的共享游戏目录(.minecraft/)」→ 新实例目录 `<数据根>/instances/<实例名>`(并登记实例); - `cli/model.rs` 的 `PackImportArgs::target` 字段文档同步。 - 用例 `help_describes_the_new_default_target`(断言帮助含新落点、不含旧落点)。 P2-2 ③ 的「显式说明」进不了任何人读通道 - CLI:`human_lines` 原只遍历 `plan.warnings`,而运行期告警(含「已替换版本清单 …旧的那份 备份在 …」)在 `report.warnings` 里 ⇒ `ull install` 人读输出从没说过这句话。现在有 report 就 报 report.warnings(它开头就是 plan 告警的副本),`manifest=Replaced` 再单独打一行备份路径。 - GUI:`install.rs` 新增 `Job::journal_report`(把 `report.warnings` 与 `manifest` 的备份路径写进 安装日志),`install/routes.rs` 两处 `ensure_complete` 之前各加一行调用(tower 批的两行)。 此前 `report.manifest` 全仓零消费者。 - 用例 `a_replaced_manifest_is_said_out_loud_in_the_human_output`(走真 `InstallPlan` 排版)。 P3-1 缺省目录被占的 hint 删掉不成立的 `--overwrite` 那半句(它绕过不了这条预检)。 P3-2 GUI 落点改成委托 core 的 `pack_dir::instance_dir`(此前 presenter 自己拼 `data()/instances/…`); `convert::dir_name` 缩成 `#[cfg(test)]` 的委托入口(生产侧已无调用点,留着继续钉归一化判据)。 P3-3 补 `the_default_target_is_a_new_instance_dir_and_the_instance_is_bound_to_it`:不带 `--target` 跑通整条 CLI,断言落点、内容、登记、以及实例设置里的 `isolation`/`gameDir`。 §5 导入建出来的实例原先「导入成功但内容永远不会被启动用到」 - 新增 `pack_dir::bind_instance_dir`(`InstanceConfig.isolation = Custom` + `game_dir = 导入目录`) 与 `pack_dir::bind_created_instance`(判据+文案,CLI 与 GUI 同一份); - CLI 在缺省建实例后、GUI 在 `import.rs::run` 里各调一次;只在「我们新建了实例目录且档案是新建」 时绑(显式 `--target` / `--no-register` / 复用已有档案都不动); - 运行目录 = 导入目录(saves/mods/logs/config),**versions/libraries/assets 仍按 D20 恒共享**; - 未改 `derive_game_dir`。 - 用例:正向 `binding_an_imported_instance_points_it_at_the_import_dir`、反向 `a_freshly_registered_instance_still_inherits_the_global_mode`。
This commit is contained in:
1 parent
96f15c79fb
commit
4e1323212b
10 files changed
+359
-45
No files matched your search
@@ -343,10 +343,14 @@ pub(super) fn pack_stem(pack: &Path) -> String {
|
||||
unlucky_core::game::install::pack_dir::pack_stem(pack)
|
||||
}
|
||||
|
||||
/// **实例目录名**(判据见 core 的 [`pack_dir::instance_dir_name`]):本函数现在只有委托,
|
||||
/// 保留它是因为 presenter 侧五个调用点按 `convert::dir_name` 这个名字取。
|
||||
/// **实例目录名**(判据见 core 的 [`pack_dir::instance_dir_name`]):本函数只有一行委托。
|
||||
///
|
||||
/// **只剩 presenter 自己的用例在调它**(生产侧落点已改成 `pack_dir::instance_dir`,见 M216
|
||||
/// P3-2),所以挂 `cfg(test)`:它是那组既有判据(空格折 `-`、中文补 `-<hash8>`、两个中文名
|
||||
/// 不塌成同一个目录)继续钉住归一化规则的入口,生产构建里不需要它。
|
||||
///
|
||||
/// [`pack_dir::instance_dir_name`]: unlucky_core::game::install::pack_dir::instance_dir_name
|
||||
#[cfg(test)]
|
||||
pub(super) fn dir_name(name: &str) -> String {
|
||||
unlucky_core::game::install::pack_dir::instance_dir_name(name)
|
||||
}
|
||||
|
||||
@@ -16,11 +16,13 @@ use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use unlucky_core::addon::import::report::ImportIssue;
|
||||
use unlucky_core::addon::import::{
|
||||
import_pack, scan_pack_online, DownloadEngineFetcher, ImportCancel, ImportProgress,
|
||||
ImportProgressSink, ImportRequest,
|
||||
};
|
||||
use unlucky_core::download::blocking::block_on;
|
||||
use unlucky_core::game::install::pack_dir;
|
||||
|
||||
use crate::dto::{ImportRequestView, PackEvent};
|
||||
use unlucky_core::addon::import::ImportStatus;
|
||||
@@ -196,7 +198,15 @@ pub(super) fn run(
|
||||
core_request = core_request.with_registration(&env.layout, Some(&pack_name));
|
||||
}
|
||||
|
||||
let report = block_on(import_pack(&core_request));
|
||||
let mut report = block_on(import_pack(&core_request));
|
||||
// **§5**:导入建出来的实例要绑到它的内容目录(`isolation=custom` + `gameDir`),否则运行
|
||||
// 目录由全局档派生成 `<game>/versions/<version_id>`,这批 mods/config 永远不会被启动用到。
|
||||
// 判据与文案在 core(与 CLI 同一份);失败不把整次导入判失败,但要让用户看见。
|
||||
if let Some(note) = pack_dir::bind_created_instance(&env.layout, &target, register, &report) {
|
||||
report
|
||||
.warnings
|
||||
.push(ImportIssue::new("instance_binding", note));
|
||||
}
|
||||
// 取消标记要**在管线返回之后**再读一次:取消可能来得太晚(管线已经跑完),这一读就是
|
||||
// "太晚"的唯一证据(`finish` 用它把报告标成 `TooLate`)。
|
||||
let cancel_requested = cancel.load(Ordering::SeqCst);
|
||||
@@ -270,11 +280,9 @@ pub(super) fn target_of(
|
||||
.clone()
|
||||
.filter(|name| !name.trim().is_empty())
|
||||
.unwrap_or_else(|| convert::pack_stem(&request.pack));
|
||||
let target = env
|
||||
.layout
|
||||
.data()
|
||||
.join("instances")
|
||||
.join(convert::dir_name(&name));
|
||||
// **M216 P3-2**:落点也委托 core(`pack_dir::instance_dir`)——此前这里自己拼
|
||||
// `<data>/instances/<dir_name>`,core 改了目录语义时 GUI 不会跟着走。
|
||||
let target = pack_dir::instance_dir(&env.layout, &name);
|
||||
if target.exists() {
|
||||
// 空目录(多半是上一次失败的残留)**可以复用**,否则重试永远报「已存在」
|
||||
let mut entries = std::fs::read_dir(&target)
|
||||
|
||||
@@ -51,6 +51,23 @@ struct Job<'a> {
|
||||
}
|
||||
|
||||
impl Job<'_> {
|
||||
/// 把 core 的运行期告警与「清单被替换」写进安装日志(**M216 P2-2**)。
|
||||
///
|
||||
/// 面板只有一行、Toast 4 秒就消失,安装日志是用户事后能自己回看的唯一渠道:动了共享
|
||||
/// `.minecraft` 里那份 `versions/<id>/<id>.json` 这件事必须先落在这里(issue #M216 复审
|
||||
/// P2-2:`report.manifest` 以前零消费者,GUI 侧对用户完全静默)。
|
||||
fn journal_report(&self, report: &InstallReport) {
|
||||
for warning in &report.warnings {
|
||||
self.journal.line(warning);
|
||||
}
|
||||
if let Some(backup) = report.manifest.as_ref().and_then(|write| write.backup()) {
|
||||
self.journal.line(&format!(
|
||||
"版本清单已替换,旧的那份备份在 {}",
|
||||
backup.display()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// processor 段的进度出口(同一套 channel/meter/journal)。
|
||||
fn reporter(&self) -> install_processors::Reporter<'_> {
|
||||
install_processors::Reporter {
|
||||
|
||||
@@ -86,6 +86,7 @@ pub(super) fn install_vanilla(
|
||||
)
|
||||
.await
|
||||
.map_err(|error| job_error(job, error))?;
|
||||
job.journal_report(&report);
|
||||
ensure_complete(&report)?;
|
||||
Ok::<String, String>(version.to_string())
|
||||
})
|
||||
@@ -178,6 +179,7 @@ pub(super) fn install_loader(
|
||||
.await
|
||||
})
|
||||
.map_err(|error| job_error(job, error))?;
|
||||
job.journal_report(&report);
|
||||
ensure_complete(&report)?;
|
||||
Ok(release.version_id)
|
||||
}
|
||||
Reference in new issue
Block a user