跳转到主要内容

sow repo

列出、创建、查看与删除仓库 —— 锁、事务与 Generation 的边界。

一个仓库(Repository)独占一份 pool/、一份 dists/、一个 SQLite 数据库与一个私有状态目录。它是 锁、事务恢复、Generation 编号与 Changeset 的边界——跨仓库不去重,也不承诺跨仓库原子提交。 sow repo 管理的就是这条边界。

语法

sow repo ls [-C DIR] [--json]
sow repo new NAME [-C DIR] [-T DUR | -N] [--json]
sow repo show [NAME] [-C DIR] [-r NAME] [--json]
sow repo migrate [NAME] [--abort] [-j N] [-C DIR] [-r NAME] [-T DUR | -N] [--json]
sow repo rm NAME [-f|--force] [-C DIR] [-T DUR | -N] [--json]

命名

仓库名必须匹配 [a-z0-9][a-z0-9._-]*,且不能是 ....sowpooldists,也不能与工作区 保留文件冲突。

sow repo new .sow
operation rejected: managed: operation rejected: name ".sow" must match [a-z0-9][a-z0-9._-]*

路径不可指定。仓库永远位于 <workspace>/<NAME>/

sow repo ls

只读列出工作区里的全部仓库。

sow repo ls
NAME	PROTECTED	DISTS	GENERATION	STATUS	PACKAGES	MEMBERSHIPS
infra	true	1	1	clean	0	0
pgsql	false	2	2	clean	0	0
参数 说明 默认
-C, --workdir DIR 工作区发现的起始目录 当前目录
--json 输出版本化 JSON envelope false

STATUS 取值为 cleandirtyrecoveringerror。各状态对客户端意味着什么,见 事务与恢复

sow repo new

原子更新 sow.yml,然后创建 <workspace>/<NAME>/{pool,dists}、SQLite 数据库与私有状态目录。新仓库 处于 Generation 0、clean 状态。

sow repo new pigsty
created pigsty: path=/srv/repo/pigsty protected=false dists=0 generation=0 status=clean packages=0 memberships=0
参数 说明 默认
-C, --workdir DIR 工作区发现的起始目录 当前目录
-T, --timeout DUR 等待锁的最长时间;0 无限等待 0
-N, --no-wait 锁被占用时立即失败 false
--json 输出版本化 JSON envelope false

repo new 取的是工作区锁而不是仓库锁——此时仓库数据库还不存在。它不接受 -r,位置参数已经指明了 目标。

对已存在的仓库再跑一次是收敛型 no-op,只报告当前状态,因此在 provisioning 脚本里是安全的。

sow repo show

只读显示一个仓库的细节。省略 NAME 时按 CLI 全局约定 中的仓库选择规则 解析。

sow repo show pigsty
repository pigsty:
  path: /srv/repo/pigsty
  protected: false
  dists: 2
  generation: 6
  desired_revision: 6
  status: clean
  packages: 5
  memberships: 8
  config: {"protected":false,"signing":{"rpm":{"packages":{"mode":"never"}}},"dists":{"el9":{"format":"rpm","architectures":["x86_64","aarch64"],"limit":1,"exclude":[{"kind":["debuginfo","debugsource"]}]},"trixie":{"format":"deb","architectures":["x86_64","aarch64"],"limit":0,"exclude":null}}}
  dirty_reasons: []
  recent_operation: id=4142220455201181493 kind=add state=done error_class= created_at=2026-08-04T04:09:24.995538Z updated_at=2026-08-04T04:09:25.332772Z
参数 说明 默认
-C, --workdir DIR 工作区发现的起始目录 当前目录
-r, --repo NAME 省略 NAME 时用它选择仓库 按选择规则
--json 输出版本化 JSON envelope false

同时给出 NAME-r 时两者必须一致;不一致会在读取任何状态前失败:

sow repo show demo -r empty
operation rejected: repo show NAME "demo" and --repo "empty" select different repositories

sow repo migrate

这是专用维护命令,不属于全新的 0.4 Managed 工作流。由 SOW 0.4 创建的 Repository 已经使用 当前单包体布局与 Schema。

但从既有 v0.3 Workspace 升级时,迁移是强制步骤:先停止全部 Workspace 写入并完成备份,再在 执行普通读写之前逐个迁移所有已配置 Repository。

cp -a /srv/sow /srv/sow.backup-before-0.4.0
sow repo migrate pigsty -C /srv/sow
sow repo migrate pgsql -C /srv/sow

0.4 Transition 会安装 Schema v11 与 v12:按全部 Dist 重新派生 Repository 状态;在不猜测缺失 历史签名者的前提下修复 Publication 与 Generation Signer Projection;移除陈旧 abandoned-object evidence;并回填 append-only publication-target binding ledger 的 Revision 1。v0.3 未记录的历史 Signer 保持显式未验证,不能进入 Current Head,也不能成为 retained trust assertion。

Schema Transition 完成后不可逆,不要再用 SOW 0.3 打开数据库,也不要手工修改 PRAGMA user_version--abort 只适用于诊断出的 pre-commit layout-maintenance attempt,不能 撤销已经完成的 Schema Migration。除升级或 SOW 明确诊断外,不要试探性执行 migrate。

参数 含义 默认值
-j, --jobs N 并行校验/渲染 worker 逻辑 CPU 数
--abort 在提交决策前放弃维护尝试 false
-C, --workdir DIR 工作区发现起点 当前目录
-r, --repo NAME 省略 NAME 时选择仓库 选择规则
-T, --timeout DUR 最长锁等待;0 无限等待 0
-N, --no-wait 锁被占用时立即失败 false
--json 输出版本化 JSON envelope false

sow repo rm

删除一个仓库:它在 sow.yml 中的条目、数据库、pool/dists/ 与私有状态。绝不跟随符号链接, 也绝不越出固定的仓库路径。

不加 -f 时,只能删除空仓库——没有 Dist、没有 Membership、没有 Package Object:

sow repo rm infra
removed repository infra
sow repo rm pgsql
operation rejected: managed: operation rejected: repository "pgsql" is not empty; use --force
sow repo rm pgsql -f
removed repository pgsql
参数 说明 默认
-f, --force 删除非空的、未 protected 的仓库 false
-C, --workdir DIR 工作区发现的起始目录 当前目录
-T, --timeout DUR 等待锁的最长时间;0 无限等待 0
-N, --no-wait 锁被占用时立即失败 false
--json 输出版本化 JSON envelope false

-f 到底降级了什么

-f 只放宽为空这一个前置条件。它不绕过路径安全检查、不绕过符号链接拒绝、也不绕过 protected 门禁。

protected

sow.yml 中的 protected: true 直接封死仓库删除,加 -f 也不行:

sow repo rm alpha -f
operation rejected: managed: operation rejected: repository "alpha" is protected

要删除受保护的仓库,必须先改 sow.yml,通过 sow config check,再重试。没有 --yes,也没有临时覆盖开关。

protected 只作用于仓库删除。受保护仓库上的包级操作不受影响——addrmbuild,乃至 dist rm 都照常工作:

sow dist rm el9 -r alpha -f
removed dist el9 from alpha

示例

为两层结构创建仓库:

sow repo new infra
sow repo new pgsql

在 cron 任务中快速失败,而不是排队等另一个写者:

sow repo new nightly -N || echo "另一个写者持有工作区锁"

一行一个仓库地做审计:

sow repo ls --json | jq -r '.result.repositories[] | "\(.name)\t\(.status)\tgen=\(.generation)"'

退出码

触发条件
0 列出、创建、显示、迁移、放弃 pre-commit transition 或删除成功;或 repo new 收敛了已存在的仓库
1 创建或删除目录树时的运行时 I/O 错误
2 用法错误、工作区未找到,或仓库选择有歧义
4 工作区锁被占用,且给了 --no-wait--timeout 到期
5 工作区 journal 的完整性或恢复错误
6 名称非法、仓库不存在、非空但未给 -fprotected,或 NAME-r 冲突

参见