Skip to content

02 · 总体架构与依赖边界

Mole 的关键边界不是 Shell 与 Go,而是“路由、策略、采集、交互、副作用”五种职责之间的依赖方向。

仓库分层

mole / mo                      CLI 路由与版本
├── bin/*.sh                   命令入口:clean / uninstall / optimize / ...
│   ├── lib/clean/*            清理目标发现
│   ├── lib/uninstall/*        应用身份、残留与批处理
│   ├── lib/optimize/*         诊断、任务目录、结果模型
│   └── lib/core/*             安全、权限、超时、日志、UI
├── cmd/analyze                磁盘分析 TUI / JSON
│   └── internal/analyze/*     扫描、缓存、删除、视图
├── cmd/status                 系统状态 TUI / JSON / NDJSON
│   └── internal/status/*      采集、评分、历史、视图
├── install.sh + lib/manage/*  安装、更新、移除
└── tests + scripts + workflows 质量与发布

bin/analyze.shbin/status.sh 只是适配器:找到安装目录里的 Go 二进制后直接 exec。这让顶层 mole 保持统一命令面,同时把 TUI 的生命周期交给 Go 进程。

依赖方向

Shell 公共运行时由 lib/core/common.sh 按固定顺序加载:基础变量与临时目录先建立,之后才是日志、超时、文件操作、UI、应用保护、Bundle 解析、安装收据与 sudo。

顺序很重要。例如文件操作要调用日志和保护函数;应用保护的数据表又应当与判断逻辑分离。若每个命令自行 source 一组文件,很容易形成“某命令少了一层保护”的隐性分叉。

两条执行路径

路径生命周期典型状态
Shell 命令一次性批处理环境变量、数组、临时目录、操作日志
Go TUI长生命周期事件循环Bubble Tea model、消息、缓存、采集历史

它们没有共享删除实现。Shell 的 mole_delete 需要处理 sudo、AppleScript、root staging;Analyze 的 Go 删除器则优先使用 /usr/bin/trash,随后尝试同卷原子 rename,最后使用 Finder。两边共享的是产品契约:保护关键路径、默认可恢复、失败不偷偷永久删除。

控制面与数据面

  • 控制面mole 路由、菜单、命令参数、Optimize 目录、保护规则。
  • 数据面:文件扫描、大小计算、系统指标采集、删除执行。
  • 证据面:预览、结果汇总、operations/deletions 日志、JSON 输出。

把证据面单独看待很重要。对于维护工具,“实际做了什么”必须能被机器读取或事后解释,不能只靠一行绿色成功提示。

构建产物

Makefile 将两个 Go 程序构建为本地 analyze-go / status-go;发布时用 CGO_ENABLED=0 生成 darwin-amd64darwin-arm64。Shell 文件和 Go 二进制由安装器一起装入配置目录,再由薄适配器寻找。

关键源码索引

下一章从用户输入开始,追踪顶层路由如何决定 source、exec 与交互菜单。

独立源码研究笔记 · 非 Mole 官方文档