release: v0.2.5
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
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
This commit is contained in:
commit
0522a41a52
1587 files changed
+323674
No files matched your search
@@ -0,0 +1,79 @@
|
||||
//! 安装过程的可回溯日志(`.ULL/logs/install.log`,一轮一行)。
|
||||
//!
|
||||
//! 起因(M45):Forge/NeoForge 装失败时,GUI 只有一行 Toast,processor 的 stderr 尾部
|
||||
//! 与「哪一步挂了」在面板一关就没了。这里把安装过程按行追加到 `.ULL/logs/`
|
||||
//! (与 `auth.jsonl` 同一分区),失败文案里带上日志路径,用户能自己回看。
|
||||
//!
|
||||
//! 三条纪律(与 auth 日志同源):
|
||||
//! 1. **只追加**,不轮转、不截断(体积由「一行一条、只记诊断字段」控制);
|
||||
//! 2. **只记诊断字段**:阶段、processor 坐标、退出码、已脱敏的 stderr 尾部(core 侧脱敏);
|
||||
//! 3. **写盘尽力而为**:开不了文件就静默跳过,绝不让日志失败连累安装。
|
||||
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use unlucky_core::launch::time;
|
||||
|
||||
use super::env::HostEnv;
|
||||
|
||||
/// 日志文件名(在 `.ULL/logs/` 下)。
|
||||
pub const INSTALL_LOG_FILE: &str = "install.log";
|
||||
|
||||
/// 一轮安装的日志句柄(`Clone` 很便宜:只有一个路径)。
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Journal {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl Journal {
|
||||
/// 按数据根打开(`logs/` 不存在就补建;建不出来只是没有日志)。
|
||||
pub fn open(env: &HostEnv) -> Self {
|
||||
let dir = env.layout.logs();
|
||||
let _ = std::fs::create_dir_all(&dir);
|
||||
Self {
|
||||
path: dir.join(INSTALL_LOG_FILE),
|
||||
}
|
||||
}
|
||||
|
||||
/// 日志路径(失败文案里给用户看)。
|
||||
pub fn path(&self) -> &Path {
|
||||
&self.path
|
||||
}
|
||||
|
||||
/// 追加一行(自动补 RFC3339 时间戳;写失败静默)。
|
||||
pub fn line(&self, text: &str) {
|
||||
let Ok(mut file) = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&self.path)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let _ = writeln!(
|
||||
file,
|
||||
"[{}] {text}",
|
||||
time::format_rfc3339_millis(time::now())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lines_are_appended_with_a_timestamp() {
|
||||
let root = std::env::temp_dir().join(format!("ull-install-journal-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
let env = HostEnv::at_root(&root);
|
||||
let journal = Journal::open(&env);
|
||||
journal.line("第一行");
|
||||
journal.line("第二行");
|
||||
let text = std::fs::read_to_string(journal.path()).expect("日志存在");
|
||||
assert!(text.contains("第一行") && text.contains("第二行"), "{text}");
|
||||
assert_eq!(text.lines().count(), 2);
|
||||
assert!(text.starts_with("[2"), "带时间戳:{text}");
|
||||
assert_eq!(journal.path(), env.layout.logs().join(INSTALL_LOG_FILE));
|
||||
std::fs::remove_dir_all(&root).ok();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user