sow add
sow add 将软件包导入指定 Dist,并构建本地索引。它从包头读取格式与架构,再应用各 Dist 的成员策略。需要分批导入后统一构建时,使用 --skip。需要更新远程目标时,在构建后运行 sow publish。
语法
参数
| 参数 | 说明 | 默认 |
|---|---|---|
-R, --recursive |
递归进入 PATH 目录的子目录 |
关闭(只扫顶层) |
--skip |
只更新期望状态,不构建 | 关闭 |
-j, --jobs N |
解析、哈希与渲染的并发工作线程数 | 逻辑 CPU 数 |
-C, --workdir DIR |
工作区发现的起始目录 | 当前目录 |
-r, --repo NAME |
选择一个仓库 | 按选择规则 |
-d, --dist NAME |
选择一个 Dist;可重复 | 按选择规则 |
-T, --timeout DUR |
等待锁的最长时间;0 无限等待 |
0 |
-N, --no-wait |
锁被占用时立即失败 | false |
--json |
输出 JSON | false |
输入与目标
PATH 可以是文件或目录。目录默认只扫描顶层,除非你加 -R。
选择一个仓库和一个或多个 Dist。可用 -r、-d 指定,也可按当前目录自动选择。混合添加 RPM 与 DEB 时,每个包只进入格式相同的 Dist。没有兼容目标的包会被拒绝。
根据软件包适用的发行版选择 Dist。SOW 检查包格式与架构,不测试操作系统或依赖兼容性。
汇总行给出操作记录 ID、逐项计数、成员增减、新的期望状态修订号、构建快照,以及仓库是否
留在 dirty 状态。随后是每个输入一行 item,顺序稳定。
逐项状态
每行 item 带一个总体 status,以及 dists= 中的逐 Dist 判定。
| 状态 | 含义 |
|---|---|
accepted |
新建软件包对象,且至少增加一条成员关系 |
reused |
内容已存在于本仓库;可能只是新增了成员关系引用 |
excluded |
策略把它从所有目标 Dist 中移除——看 dists= 区分是 excluded 还是 limited |
failed |
该包被拒绝,error= 字段说明原因 |
reused 表示复用已有内容:同一个文件加两次不会产生第二个对象或重复成员关系。默认重复执行
add 时还会构建所选 Dist。Dist 已是最新状态时,构建快照不变。先前 --skip 或配置变更留下
dirty 状态时,SOW 会补做构建,并可能生成新的构建快照:
把同一个对象加进第二个 Dist 同样是 reused——包池只保留一份,只是多了一条成员关系。
需要继续延后构建时,再次使用 --skip。
软件包架构
add 从包头读取格式与原生架构,再对照工作区许可表。架构不受支持或不在配置的许可表中时,该包会被拒绝:
RPM 的 noarch 与 DEB 的 all 是架构中性(neutral)的。它们只产生一个软件包对象与一条
成员关系,但会渲染进目标 Dist 的每个有效架构视图。只有所选 Dist 会包含这些包。
策略:exclude 与 limit
SOW 将输入包与 Dist 的现有成员合并,先执行 exclude,再执行 limit。被策略移除的包会显示为 excluded,不算解析失败。
这里 trixielim 配了 exclude: [{kind: [dbgsym]}] 与 limit: 1。dbgsym 包被规则排除;
libpq5 18.2-1 因版本上限被移除并报告为 limited,18.3-1 被保留。两者的顶层状态都是 excluded,
用 dists= 字段区分。
limit 按 (二进制包名, 规范架构) 分组,因此 18.3-1:amd64 与 18.3-1:arm64 在 limit: 1 下都能
留下。同一次运行中,一个包可以被某个 Dist 接受、被另一个 Dist 跳过。
放宽 exclude 或 limit 后,需要重新运行 sow add 来恢复软件包。策略作用于期望成员,而不是 pool/ 中的全部残留文件。
部分成功的批次
即使同批有失败项,合法且无冲突的包依然会提交。失败的输入原地不动,各自带自己的错误信息,命令退出
3:
如果每个输入都失败,操作以退出码 6 被拒绝,期望成员与公开内容保持原样。人类输出会列出
每个失败输入及其原因,JSON 则在 result.items 中保留这些信息:
被策略排除不属于输入失败;全部被排除的批次可以正常成功,包括首次向空 Dist 添加时。
使用 SIGINT 或 SIGTERM 中断命令时,命令返回 130。使用原始输入文件重新执行;恢复会保留已经提交的成员变更。
包内容改变时,使用新的版本与文件名。本地 GC 后,已发布的包池路径仍然保留。路径冲突只拒绝对应输入,其他有效输入仍可成功。
重新添加同一个包时,保持文件名大小写一致。仅大小写不同的路径会产生冲突。在大小写不敏感的文件系统上,源码包目录名也必须可以区分,详见工作区文件系统。
–skip
--skip 提交期望成员,保持 pool/、dists/ 与构建快照不变。新包存放在私有待构建目录,供后续构建使用。期望状态与已构建状态不同时,仓库为 dirty;重复添加未变化的成员可以保持 clean。
pending=4/2326 表示有 4 个包、共 2326 字节等待构建。构建成功后,实际采用的包进入公开目录,并出现在 sow changes 的结果中。
批量导入时用 --skip,最后构建一次:
处理顺序
SOW 检查软件包,并按配置为新 RPM 签名。随后执行 exclude 与 limit,记录最终成员;未设置 --skip 时,继续构建。
输入文件保持原样,签名在私有副本上完成。
RPM 签名模式
Managed 模式的 RPM 包签名在 sow.yml 的 signing.rpm.packages.mode 中配置,命令行没有覆盖开关。
| 模式 | 行为 |
|---|---|
never |
完整保留输入字节 |
fill |
无签名或签名不受信任时用配置密钥签名;已有能被 trusted_keys 验证的签名则保持字节。配置了密钥时的默认值 |
always |
确保最终包由配置密钥有效签名;否则对暂存副本重签 |
没有配置密钥时只能用 never。
重复导入时,SOW 复用内容相同的软件包。如果 RPM 只有签名不同,且已有包满足当前签名策略,也可以复用。包内容改变或已有签名不符合策略时,会产生坐标冲突。完整匹配规则见签名模型。
退出码
| 码 | 触发条件 |
|---|---|
0 |
输入处理完成,包括按策略排除的输入;构建完成或已跳过 |
1 |
运行时 I/O、解析器、渲染器或签名失败 |
2 |
用法错误、工作区未找到,或仓库/Dist 选择有歧义 |
3 |
部分批次——至少一项已提交,至少一项失败 |
4 |
仓库锁被占用,且给了 --no-wait 或 --timeout 到期 |
5 |
完整性或恢复错误,包括在 applied 之后构建失败 |
6 |
全部输入失败,或选择范围、签名、状态前提不允许执行操作 |
参见
- sow rm —— 反向操作
- sow build ——
--skip之后构建 - 成员策略 ——
exclude规则与limit语义详解 - 签名模型 —— 两条信任链与密钥引用
- 包引用 —— item 行中坐标的写法