release: v0.2.4 里程碑快照(孤儿提交,无父;树 = dev 68362e5)
CI / fmt (rustfmt --check) (push) Waiting to run
CI / clippy (ubuntu-latest) (push) Waiting to run
CI / clippy (windows-latest) (push) Waiting to run
CI / test (ubuntu-latest) (push) Waiting to run
CI / test (windows-latest) (push) Waiting to run
CI / build release (ubuntu-latest) (push) Waiting to run
CI / build release (windows-latest) (push) Waiting to run
CI / runtime smoke (ubuntu x64, xvfb) (push) Waiting to run
CI / runtime smoke (macos arm64, probe) (push) Skipped
CI / update-e2e (windows x64) (push) Waiting to run
GPU evidence / GPU 判据自测(不需 GPU;跳过 ≠ 已验证) (push) Waiting to run
GPU evidence / GPU 证据 — 探测可用产物与硬件适配器 (push) Waiting to run
Guards / core 零 UI 守门 (push) Waiting to run
Guards / presenter 零 UI 守门 (push) Waiting to run
Guards / design 零第三方依赖守门 (push) Waiting to run
Guards / unsafe 落点守门(集合必须恰好等于期望) (push) Waiting to run
Guards / 文件行数 ≤400 守门 (push) Waiting to run
Guards / 依赖许可与来源(cargo-deny) (push) Waiting to run
Release guard / 发布标记语义守门(push tag → 稳定版) (push) Waiting to run
Signing status(播报,不是门禁) / 判据自测(三行/退出码/变异重放/接线) (push) Waiting to run
Signing status(播报,不是门禁) / 签名就绪度(播报) (push) Waiting to run
Release / 选槽位(默认四个:Windows 两档 + Linux 两档) (push) Waiting to run

本批内容见 CHANGELOG.md 的 0.2.4 段。按 D41 用孤儿快照推 main,保留「公开史只有里程碑」的模型。
This commit is contained in:
AskaEth committed 2026-11-11 21:41:38 +08:00
commit a5d1dec495
1580 files changed
+320938

No files matched your search

@@ -0,0 +1,84 @@
//! `instances scan` / `instances adopt` 共用的 JSON 与错误投影。
//!
//! 两条命令输出同一种候选形状(`candidate` 对象),错误也走同一份映射——分两份写迟早漂。
use serde_json::{json, Value};
use unlucky_core::game::adopt::{AdoptCandidate, AdoptError, AdoptProblem};
use crate::error::CliError;
/// 候选 → `--json` 里的 `candidate` 对象。
pub(super) fn candidate_json(candidate: &AdoptCandidate) -> Value {
json!({
"version_id": candidate.version_id,
"version_dir": candidate.version_dir.display().to_string(),
"manifest_path": candidate.manifest_path.display().to_string(),
"jar_present": candidate.jar_present,
"manifest_id": candidate.manifest_id,
"inherits": candidate.inherits,
"registered": candidate.registered.iter().map(|item| json!({
"id": item.id,
"name": item.name,
})).collect::<Vec<Value>>(),
"adoptable": candidate.adoptable(),
"problems": problems_json(&candidate.problems),
})
}
/// 问题清单 → 结构化数组(`code` 稳定、`message` 人读)。
pub(super) fn problems_json(problems: &[AdoptProblem]) -> Value {
Value::Array(
problems
.iter()
.map(|problem| {
json!({
"code": problem.code(),
"message": problem.to_string(),
})
})
.collect(),
)
}
/// `AdoptError` → CLI 错误:稳定 code + 逐条问题进 `detail`(脚本不必解析散文)。
pub(super) fn map_error(error: AdoptError) -> CliError {
let code = error.code();
let message = error.to_string();
let cli = CliError::user(code, message);
let hint = match &error {
AdoptError::DuplicateName { .. } => {
Some("换个展示名:%prog% instances adopt <version-id> --name <新名字>")
}
AdoptError::NotAdoptable { .. } => Some(
"这些版本要么清单坏了、要么缺父版本、要么越界:先在原来的启动器里把它修好,\
或 `%prog% install <version>` 让本启动器自己装一份",
),
AdoptError::AlreadyRegistered { .. } => {
Some("用 `%prog% instances list` 看已有实例;要第二个实例请换 --name")
}
AdoptError::TargetNotEmpty { .. } => {
Some("换一个名字(缺省目录按名字派生),或用 --isolation custom --game-dir <空目录>")
}
AdoptError::UnknownVersion { .. } => Some("先看有哪些可用:%prog% instances scan"),
AdoptError::NoFreeRunDir { .. } => Some(
"换一个 --name(缺省目录按名字派生),或用 --isolation custom --game-dir <空目录>",
),
AdoptError::WriteSurfaceInGameTree { .. } => Some(
"数据目录(.ULL / --data-dir)和游戏树重叠了:把它指到游戏树之外的目录再登记 (整体迁移到别处是允许的,默认登记不会把实例数据写进别人的 .minecraft)",
),
AdoptError::ConfigSurfaceUnsafe { .. } => Some(
"数据根里的 config/ 或 config/instances/ 被链到别处了:先把它恢复成真实目录再登记 (整体迁移请把整个 .ULL 目录一起搬走,别只链其中一层)",
),
AdoptError::VersionsDirUnreadable { .. } => Some(
"游戏根/versions 入口存在但读不出来:检查它是不是断链的符号链接/目录联接, 或把它指回真实目录后再扫",
),
_ => None,
};
let cli = match hint {
Some(hint) => cli.with_hint(hint),
None => cli,
};
cli.with_detail(json!({
"problems": problems_json(error.problems()),
}))
}