mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 14:57:38 +00:00
批 1,不含 SDK 仓与目录改名。 - go.mod 第 1 行 module 路径 - 366 个 .go 文件的完整前缀 github.com/JianFeeeee/HomeAgent 机械替换 (857 处,仅完整前缀;展示名/注释里的 HomeAgent 字样留给批 5) - 未改:third_party 目录名、SDK 自身 go.mod module、go.mod replace 目标、 homed/waiter 可执行名、.hmap 后缀
95 lines
3.2 KiB
Go
95 lines
3.2 KiB
Go
// Package modules 是内核模块的**登记表**(不含任何具体模块的实现)。
|
||
//
|
||
// ## 设计意图(用户设计)
|
||
//
|
||
// > 每个内核模块显式各自声明依赖 … 最先初始化的 core 自然不依赖任何模块,
|
||
// > 下一步初始化的依赖 core 以此类推
|
||
//
|
||
// ## 怎么加一个新模块(这是本设计的**验收标准**)
|
||
//
|
||
// ① 新建一个文件(如 modules/mymod.go)
|
||
// ② 写一个类型,实现 kernelboot.Module(Name/Requires/Provides/Init)
|
||
// ③ 在同文件的 init() 里调 modules.Register(&MyMod{})
|
||
// ④ 在 modules/imports.go 加一行 `_ "...modules"` —— **仅此而已**
|
||
//
|
||
// **不需要**编辑任何中央清单:依赖写在模块**自己**的 Requires() 里。
|
||
//
|
||
// ★ 为何要"防漏 import"的判据(见 registry_test.go):
|
||
// 忘了 import ⇒ 模块**根本不登记** ⇒ 它不参与装配 ⇒ 依赖它的模块报
|
||
// "缺依赖"(响亮),但**不依赖它的模块会静默少了那个设施**
|
||
// (如插件注册表没建 ⇒ 插件全部加载不了,而错误信息指向插件而非根因)。
|
||
// ⇒ 判据必须自动扫描目录,要求每个模块文件都被 import。
|
||
package modules
|
||
|
||
import (
|
||
"fmt"
|
||
"sort"
|
||
"sync"
|
||
|
||
"github.com/JianFeeeee/HologramAgent/internal/kernelboot"
|
||
)
|
||
|
||
var (
|
||
regMu sync.Mutex
|
||
registry []kernelboot.Module
|
||
seenName = map[string]bool{}
|
||
)
|
||
|
||
// Register 由模块在自己的 init() 里调用(自注册)。
|
||
//
|
||
// 重复注册同一模块名会**记录**并在 BuildModules 时报错 —— 不用 panic:
|
||
// panic 发生在 init 阶段,栈信息对使用者毫无意义(他只想知道哪个模块重名)。
|
||
func Register(m kernelboot.Module) {
|
||
if m == nil {
|
||
return
|
||
}
|
||
regMu.Lock()
|
||
defer regMu.Unlock()
|
||
if seenName[m.Name()] {
|
||
dupErr = append(dupErr, m.Name())
|
||
return
|
||
}
|
||
seenName[m.Name()] = true
|
||
registry = append(registry, m)
|
||
}
|
||
|
||
// dupErr 累积重名模块(BuildModules 时统一报告)。
|
||
var dupErr []string
|
||
|
||
// BuildModules 返回全部已登记模块(按名字排序,保证可复现)。
|
||
//
|
||
// ## 为什么排序
|
||
//
|
||
// 分层结果的**层内顺序**若依赖 map/切片顺序,同一份声明两次构建会得到
|
||
// 不同顺序 ⇒ 不可审计(设计 §2.5:图要能进 PR diff 比对)。
|
||
// 排序让结果稳定。
|
||
func BuildModules() ([]kernelboot.Module, error) {
|
||
regMu.Lock()
|
||
defer regMu.Unlock()
|
||
if len(dupErr) > 0 {
|
||
names := append([]string(nil), dupErr...)
|
||
sort.Strings(names)
|
||
return nil, fmt.Errorf("kernelboot/modules: 模块名重复注册: %v"+
|
||
"(同一个模块被 import 了两次?或两个模块取了同名)", names)
|
||
}
|
||
out := append([]kernelboot.Module(nil), registry...)
|
||
sort.Slice(out, func(i, j int) bool { return out[i].Name() < out[j].Name() })
|
||
if len(out) == 0 {
|
||
return nil, fmt.Errorf("kernelboot/modules: 没有任何模块被登记 —— " +
|
||
"通常是没有 import 模块包(见本文件顶部的'怎么加一个新模块')")
|
||
}
|
||
return out, nil
|
||
}
|
||
|
||
// Names 返回已登记模块名(诊断/判据用)。
|
||
func Names() []string {
|
||
regMu.Lock()
|
||
defer regMu.Unlock()
|
||
out := make([]string, 0, len(registry))
|
||
for _, m := range registry {
|
||
out = append(out, m.Name())
|
||
}
|
||
sort.Strings(out)
|
||
return out
|
||
}
|