Skip to content

fix(mods): 软链接安装的 Mod 文件夹现在会显示在管理列表并可启用/禁用 - #82

Merged
std-microblock merged 1 commit into
std-microblock:masterfrom
std-external:fix/80-symlink-mod-folder
Oct 8, 2026
Merged

std-microblock merged 1 commit into
std-microblock:masterfrom
std-external:fix/80-symlink-mod-folder

Conversation

@std-external

Copy link
Copy Markdown
Contributor

Fixes #80

问题

macOS 上把 Mod 以软链接(symlink)的方式放进 Mods/ 是很常见的开发/试皮肤做法,例如:

Mods/hilda_skinmod -> ~/ghq/github.com/user/hilda_skinmod

游戏本身能正常加载,但 CeleMod 的管理列表里完全看不到这个 Mod,因此无法启用/禁用;于是出现「左边列表只有 3 个、右边皮肤预设却有 5 个」的对不上现象。

根因

src-tauri/src/backend.rs 的安装列表扫描用 DirEntry::file_type() 判断条目类型,而它不会跟随软链接,返回的是链接本身:

  • src-tauri/src/backend.rs:2064(修复前):软链接目录的 is_dir() 为 false,于是走到 zip 分支;
  • 该分支要求路径有扩展名(hilda_skinmod 没有),Unable to get the extension 出错;
  • 错误被 src-tauri/src/backend.rs:2153 的 if let Err(e) = res 吞掉并打日志跳过条目 —— 这就是列表里看不到它的位置。

同样的原因,src-tauri/src/mods_watch.rs:120 的目录监听快照也无法识别软链接 Mod,运行中新加/删掉软链接 Mod 不会触发列表自动刷新。

改动

  • 新增 resolved_entry_file_type()(src-tauri/src/backend.rs):软链接条目按链接目标判定类型,非软链接行为不变。
  • get_installed_mods_sync_with_catalog 与 mods_watch::mods_snapshot 改用它,所以软链接文件夹 Mod 会正常出现在已安装列表里(isDirectory: true),启用/禁用沿用现有的 profile/blacklist 逻辑。
  • mod_path_stats 改为跟随软链接:软链接文件夹现在上报 0 字节(和其他文件夹 Mod 一致)和目标目录的修改时间,而不是链接自身的字节长度(截图里那种 19 字节)。
  • 软链接指向 zip 的情况也顺带覆盖:即使链接名没有 .zip 扩展名,也会按目标类型走文件夹/压缩包分支。

验证

先加测试复现(修复前失败):

test backend::mods_watch::tests::snapshot_reports_symlinked_directory_mods ... FAILED
  left: []  right: ["LinkedMod"]
test backend::local_package_tests::lists_symlinked_directory_mods ... FAILED
  [ WARNING ] Failed to parse "hilda_skinmod": Unable to get the extension
  left: 0  right: 1

修复后:

cd src-tauri && cargo test --lib
test result: ok. 107 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

(基线 105 个 + 新增 2 个;cargo fmt -- --check 无输出;cargo clippy --lib --tests 只剩仓库里原有的 7 条告警,均不在本次改动范围内。)

新增测试同时断言:清理 Mods 目录只会删掉链接,不会碰被链接的源码目录。软链接测试在 unix 用 symlink、Windows 用 symlink_dir,平台不允许创建软链接时(Windows 未开开发者模式)跳过。

未改动前端代码,行为变化全部在 Rust 侧。

`DirEntry::file_type` reports the link itself instead of its target, so a
Mod installed as a symlinked folder was classified as a plain file and
skipped: the installed list never showed it, which also made it impossible
to enable or disable it from the manage page.

Resolve the link target when classifying Mods folder entries, in the
installed list and in the folder watcher snapshot. `mod_path_stats` now
follows symlinks too, so a linked Mod reports its folder size (0) and its
target's mtime instead of the link's own byte length.

Fixes std-microblock#80
@std-microblock
std-microblock merged commit 3c56abd into std-microblock:master Oct 8, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

希望支持软链接文件夹的 mod 能在管理列表操作

2 participants