能力总览

SOW 在两条运行路径、两种包格式、签名与平台上的完整覆盖面,以及与 createrepo_c、reprepro 的对标结论。

SOW 是一个自包含的软件仓库管理器:一个纯静态 Go 二进制(CGO_ENABLED=0),在 Linux 与 macOS 上创建并维护 APT(DEB)与 YUM(RPM)软件仓库。它不调用 createrepo_cdpkg-scanpackagesreprepromodifyrepo_c,也不需要常驻进程。本页是覆盖面的地图,后续各页解释每一块是怎么实现的。

当前版本为 sow 0.2.0-dev

两条运行路径

SOW 提供两种建仓方式,二者刻意相互隔离。除底层的包解析器、渲染器、版本比较、锁和安全文件原语外,它们不共享任何东西。

Plain 平面模式Managed 托管模式
入口命令sow createsow init / repo / dist / add / build
输入一个装着 .rpm / .deb 的目录按路径 add 进工作区的包
产出布局平面 —— 包与索引同目录Debian 风格 pool/ + dists/ 发布视图
持久状态无(仅操作期间的临时 journal)sow.yml + 每个仓库一个 SQLite
配置无 —— 不读任何配置文件sow.yml,严格校验
多架构全部架构落进同一份平面索引每个 Dist 每个架构一份渲染视图
历史单调 Generation 与操作账本
对标createrepo_c + dpkg-scanpackagesreprepro

手里已有一目录包、只想给它建个索引 —— 用 Plain。同一个仓库要按策略持续维护数月、并且需要审计线索 —— 用 Managed。

两条路径都不理解远端。建好的仓库目录就是一堆文件:用任意 Web 服务器托管,或用 rsync 复制走。参见对外服务

格式覆盖

能力RPM / YUMDEB / APT
生成的索引文件repodata/,含 primaryfilelistsotherrepomd.xmlPackagesPackages.gzRelease
校验和SHA-256,metadata 文件按 checksum 命名仅 SHA-256(不输出 MD5Sum/SHA1)
包事实来源RPM 包头(绝不看文件名).deb 内的 control
坐标(身份)NEVRAname=version:arch
架构视图(Managed)x86_64aarch64binary-amd64binary-arm64
免架构包noarchall
by-hash 索引拉取不适用支持,Acquire-By-Hash: yes
元数据签名repodata/repomd.xml.ascInReleaseRelease.gpg
包体签名嵌入式 OpenPGP 签名,fill / always 模式不适用

一条命令同时处理两种格式。Plain 模式下,同时含 .rpm.deb 的目录在一次操作里生成 repodata/Packages。Managed 模式下,一个 Repository 可以同时拥有 RPM Dist 和 DEB Dist,共用同一个 pool/

签名覆盖

存在两条彼此独立、分别配置的信任链,完整说明见签名模型

信任链Plain 模式Managed 模式客户端用什么验证
仓库元数据不提供signing.rpm.metadata.keysigning.deb.metadata.keydnf repo_gpgcheck=1、apt Signed-By
RPM 包体create -S KEY [--overwrite]signing.rpm.packages.mode: fill | alwaysdnf gpgcheck=1

file://env:// 给出的元数据密钥由进程内 Go signer 使用,不需要外部工具。RPM 包体签名和 agent:// 密钥引用会调用环境中的 rpmgpg

平台覆盖

二进制可构建 darwinlinuxamd64 / arm64 版本。运行时不依赖包管理器、数据库服务或 Python 环境。

SOW 唯一会调用的外部程序是 rpm(RPM 包体签名)与 gpg(agent:// 密钥引用)。如果仓库不签名,或只用 file:///env:// 元数据密钥,那么除了 sow 二进制本身之外什么都不用装。

Managed 模式有一条硬性要求:仓库的 pool/dists/ 视图必须位于同一个 POSIX 文件系统,因为视图是硬链接投影。跨设备是硬失败,绝不静默降级为复制。参见包池与架构视图

客户端兼容

下表每一行都在真实客户端上跑过:

客户端版本结果
AlmaLinux 8 / 9 / 10 dnfdnf4repo_gpgcheck=1 + gpgcheck=1makecacheinstall 通过
CentOS 7 yum3.4.3makecache 通过,多版本 NEVRA 解析正确
Debian 13 apt3.0.3update(InRelease 验签 + by-hash 拉取)与 install 通过
Debian 12 apt2.6.1同上;平面仓库经 [trusted=yes] 亦可用
dnf reposyncEL9pool/ 布局完整镜像

完整矩阵(含 APT ≥ 1.2 的 by-hash 要求)见兼容性

与 createrepo_c、reprepro 对标

这两个工具是 SOW 的对标基准。下表来自同一批包的并排实测,不是文档宣称。

维度SOWcreaterepo_creprepro
RPM 元数据primary/filelists/other,语义等价基准
sqlite repodata不生成(明确非目标)默认生成
DEB Packages 字段等价,仅 SHA-256基准,输出 MD5Sum + SHA1 + SHA256
by-hash支持(Acquire-By-Hash: yes)不支持
包池布局pool/<首字母>/<source>/(无 component 层)pool/main/<首字母>/<source>/
每架构 Release 存根不生成(apt 不需要)生成
平台Linux 与 macOS,单二进制实际只在 Linux 上用仅 Linux
事务与崩溃恢复journal 前滚/回滚数据库易损
审计操作账本 + JSONL 导出日志有限

有两个细节值得单独说明,因为迁移的人常会问:

createrepo_c 0.20.1 在 9 个测试包 + 87 个真实生产包上并排比对,primaryfilelistsother 的全部字段语义一致 —— name、arch、EVR、checksum、各类 size、provides、requires flags、files、changelog、header range 都对得上。唯一差异:当某个 RPM 包头里 /bin/sh 同时以 pre 和非 pre 两个上下文出现时,SOW 去重保留一条,createrepo_c 保留两条。

dpkg-scanpackages 比对,Packages 字段一致,差别在于 SOW 只输出 SHA256(现代 APT 客户端不需要别的),并且对缺失字段(如 Section)直接省略而不是写空值。

如果你要迁移既有仓库,先读从 createrepo_c / reprepro 迁移:就地接管一个目录会把旧工具的文件留在磁盘上,需要你自己清理。

性能锚点

macOS arm64 冷启动实测:

操作规模墙上时间
sow create9 个 RPM0.31 s
sow create87 个 RPM,2.9 GB(全量 SHA-256)10.7 s
sow add + 自动 build9 个 RPM,31 MB约 1.3 s
sow check(八层全过)16 包工作区0.12 s

需要解析、哈希、渲染或校验的命令都接受 -j/--jobs N,默认取逻辑 CPU 数。并行不改变输出:最终序列化按固定顺序完成,相同输入永远产生相同字节。

明确的非目标

以下不是"还没做完的功能",而是设计上排除的东西 —— 不会有空命令或隐藏 flag 假装它们存在:

  • modulemd 的生成、注入与透传
  • sqlite repodata 与 zchunk
  • SRPM / DSC 源码索引
  • 远端发布、CDN、对象存储,以及任何形式的 endpoint 配置
  • 多写者与多机部署
  • 垃圾回收、跨仓库去重
  • 常驻服务或 Web UI
  • 造包

SOW 在本地磁盘上管理仓库,交给你一个目录。用什么把这个目录运出去,是你的选择。

继续阅读

最后修改:2026-08-08: init commit (fe725aa)