fix(presenter): junction 夹具改走 platform::child::quiet,两处副本收成一份共享 helper(M291)

This commit is contained in:
AskaEth committed 2026-11-13 00:28:32 +08:00
1 parent 5617709792
commit 27980cf5b3
2 files changed
+30 -35

No files matched your search

+27 -18
View File
@@ -38,7 +38,8 @@
//! # 只读
//!
//! 本模块只 `is_dir()` / `canonicalize()`:不建目录、不写一个字节。官方启动器那个根上尤其要紧
//! ——那是**别人的**目录。
//! ——那是**别人的**目录。(唯一的例外是 `#[cfg(test)]` 的 [`make_dir_link`]:它只在用例自己的
//! 临时目录里造链接,不属于任何产品路径。)
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
@@ -131,6 +132,31 @@ pub(in crate::host) fn key_of(path: &Path) -> String {
}
}
/// 造一个目录链接:Windows 用 junction(无管理员权限也能建),Unix 用符号链接。造不出来返回 `false`。
///
/// 模块级而不是 `mod tests` 里,因为 [`super::tests_multiroot`] 的判据②也要造链接(M291):两处
/// 各写一份一字不差的 `cmd /c mklink /J` 只是把同一个坑埋两遍,`child_quiet_guard` 也是一次抓两处。
/// 可见性只开到 `crate::host`——调用方就这两个用例模块。
///
/// 走 [`unlucky_core::platform::child::quiet`]:本仓库的 exe 是 GUI 程序(PE Subsystem = 2),
/// spawn `cmd.exe` 这种控制台程序时 Windows 会新开一块控制台(桌面上「黑框闪一下」)。
/// 语义不变:只看退出码(`.status()`),不读输出,失败一律 `false`。
#[cfg(all(test, windows))]
pub(in crate::host) fn make_dir_link(link: &Path, target: &Path) -> bool {
unlucky_core::platform::child::quiet("cmd")
.args(["/c", "mklink", "/J"])
.arg(link)
.arg(target)
.status()
.map(|status| status.success())
.unwrap_or(false)
}
#[cfg(all(test, not(windows)))]
pub(in crate::host) fn make_dir_link(link: &Path, target: &Path) -> bool {
std::os::unix::fs::symlink(target, link).is_ok()
}
#[cfg(test)]
mod tests {
use super::*;
@@ -186,21 +212,4 @@ mod tests {
);
std::fs::remove_dir_all(&root).ok();
}
/// 造一个目录链接:Windows 用 junction(无管理员权限也能建),Unix 用符号链接。
#[cfg(windows)]
fn make_dir_link(link: &Path, target: &Path) -> bool {
std::process::Command::new("cmd")
.args(["/c", "mklink", "/J"])
.arg(link)
.arg(target)
.status()
.map(|status| status.success())
.unwrap_or(false)
}
#[cfg(not(windows))]
fn make_dir_link(link: &Path, target: &Path) -> bool {
std::os::unix::fs::symlink(target, link).is_ok()
}
}
@@ -77,22 +77,8 @@ fn write_world(root: &Path, name: &str) {
std::fs::write(dir.join("level.dat"), b"fixture").expect("level.dat");
}
/// 目录链接(Windows 用 junction:不需要管理员;其它平台符号链接)。造不出来返回 `false`。
#[cfg(windows)]
fn link_dir(link: &Path, target: &Path) -> bool {
std::process::Command::new("cmd")
.args(["/c", "mklink", "/J"])
.arg(link)
.arg(target)
.status()
.map(|status| status.success())
.unwrap_or(false)
}
#[cfg(not(windows))]
fn link_dir(link: &Path, target: &Path) -> bool {
std::os::unix::fs::symlink(target, link).is_ok()
}
// 目录链接夹具走 `host::game::roots::make_dir_link`——一份代码两处共用(M291)。别在这里再写一份
// `cmd /c mklink /J`:多一个 spawn 点就多一个绕过 `platform::child::quiet` 的机会。
// ------------------------------------------------------------------ 判据①:两个根各一条
@@ -194,7 +180,7 @@ fn a_junction_to_the_configured_root_is_not_a_second_root() {
let mut env = HostEnv::at_root(&root.0);
write_version(&env.game, "A");
let link = root.0.join("linked");
if !link_dir(&link, env.game.root()) {
if !super::roots::make_dir_link(&link, env.game.root()) {
// 造不出链接就**不假绿**:这一条判据在造不出链接的盘上等于没验。
eprintln!("跳过:这个环境造不出目录链接({})", link.display());
return;