sow repo
A Repository owns one pool/, one dists/, one SQLite database and one private state directory. It
is the boundary of locking, transaction recovery, Generation numbering and Changesets — nothing is
deduplicated across Repositories and no cross-Repository commit is atomic. sow repo manages that
boundary.
Synopsis
Naming
A Repository name must match [a-z0-9][a-z0-9._-]* and may not be ., .., .sow, pool,
dists, or collide with a Workspace reserved file.
You cannot choose the path. A Repository always lives at <workspace>/<NAME>/.
sow repo ls
Read-only listing of every Repository in the Workspace.
| Flag | Description | Default |
|---|---|---|
-C, --workdir DIR |
Workspace discovery start directory | current directory |
--json |
Emit the versioned JSON envelope | false |
STATUS is one of clean, dirty, recovering or error. See
Transactions & Recovery for what each one implies for clients.
sow repo new
Atomically updates sow.yml, then creates <workspace>/<NAME>/{pool,dists}, the SQLite database and
the private state directory. A new Repository is Generation 0 and clean.
| Flag | Description | Default |
|---|---|---|
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-T, --timeout DUR |
Maximum lock wait; 0 waits indefinitely |
0 |
-N, --no-wait |
Fail immediately when the lock is held | false |
--json |
Emit the versioned JSON envelope | false |
repo new takes the Workspace lock, not a Repository lock — the Repository database does not exist
yet. It does not accept -r; the positional argument already names the target.
Running it again on an existing Repository is a converging no-op that reports the current state, so it is safe in a provisioning script.
sow repo show
Read-only detail for one Repository. With NAME omitted, the usual
Repository selection rules apply.
| Flag | Description | Default |
|---|---|---|
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-r, --repo NAME |
Select the repository when NAME is omitted |
selection rules |
--json |
Emit the versioned JSON envelope | false |
If you give both NAME and -r, they must agree; disagreement fails before any state is read:
sow repo migrate
This is a specialized maintenance command, not part of a fresh 0.5 Managed workflow. New 0.5 Repositories use schema v13 and the current single-payload layout. Upgrading an existing v0.3 or v0.4 Workspace requires explicit migration: stop all Workspace writers, take a backup, and run the command once for every configured Repository before ordinary reads or writes.
The backup must preserve hard links (DEB by-hash entries are hard links); macOS cp -a
does not. The output reports the schema change, for example
migrated repository pigsty: single-payload-v1 -> single-payload-v1 schema=12->13 …; JSON has
schema_from and schema_to, and a repeated migration reports schema=13->13. Until a
Repository is migrated, its write commands exit 5 with
repository schema v12 predates this binary (v13); back up the workspace, then run `sow repo migrate NAME`.
Schema v13 adds indexes for candidate pool-path ownership lookups, avoiding full publication-history
scans on each add. Index creation costs time and private database space once during migration.
Run sow build and sow check afterwards to refresh affected RPM authentication and APT metadata
contracts. A v0.3 database also receives the v11/v12 repairs: it recomputes Repository status from every Dist,
repairs publication and Generation signer projections without guessing a missing historical
signer, removes stale abandoned-object evidence, and backfills revision 1 of the append-only
publication-target binding ledger. An unrecorded v0.3 historical signer remains explicitly
unverified; it cannot reach the current head or become a retained trust assertion.
The completed schema transition is one-way. Do not reopen the database with an older SOW binary, and do not edit
PRAGMA user_version. --abort applies only to a diagnosed pre-commit layout-maintenance attempt;
it does not undo a completed schema migration. Outside an upgrade or an explicit SOW diagnostic,
do not run migration speculatively.
Starting a new conversion from a pre-release C2 layout is unsupported. Preserve its files and rebuild
with a supported release. An already recorded layout transition may still complete its bound plan,
but the result is not a supported 0.5 Repository: the next write may still build one Generation,
after which the Repository reports status=error. Rebuild it from the original packages.
| Flag | Description | Default |
|---|---|---|
-j, --jobs N |
Parallel verification/render workers | logical CPUs |
--abort |
Abandon a maintenance attempt before its commit decision | false |
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-r, --repo NAME |
Select the repository when NAME is omitted |
selection rules |
-T, --timeout DUR |
Maximum lock wait; 0 waits indefinitely |
0 |
-N, --no-wait |
Fail immediately when the lock is held | false |
--json |
Emit the versioned JSON envelope | false |
sow repo rm
Removes a Repository: its sow.yml entry, database, pool/, dists/ and private state. It never
follows symlinks and never steps outside the fixed Repository path.
Without -f, only an empty Repository — no Dists, no Memberships, no Package Objects — can be
removed:
| Flag | Description | Default |
|---|---|---|
-f, --force |
Remove a non-empty unprotected repository | false |
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-T, --timeout DUR |
Maximum lock wait; 0 waits indefinitely |
0 |
-N, --no-wait |
Fail immediately when the lock is held | false |
--json |
Emit the versioned JSON envelope | false |
What -f actually downgrades
-f only relaxes the emptiness precondition. It does not bypass path safety, symlink refusal, or
the protected gate.
protected
protected: true in sow.yml blocks Repository deletion outright, -f included:
To remove a protected Repository you must edit sow.yml, pass
sow config check, and try again. There is no --yes and no
temporary override.
protected scopes to Repository deletion only. Package-level work on a protected Repository is
unaffected — add, rm, build, and even dist rm, all continue to work:
Examples
Create the Repositories for a two-tier layout:
Fail fast in a cron job rather than queue behind another writer:
Audit every Repository in one line each:
Exit codes
| Code | Trigger |
|---|---|
0 |
Listed, created, shown, migrated, abandoned a pre-commit transition, or removed; or repo new converged an existing Repository |
1 |
Runtime I/O error creating or removing the tree |
2 |
Usage error, Workspace not found, or an ambiguous Repository selection |
4 |
Workspace lock held and --no-wait given or --timeout expired |
5 |
Integrity or recovery error in the Workspace journal |
6 |
Invalid name, unknown Repository, non-empty without -f, protected, or NAME conflicting with -r |
See also
- sow dist — the layer below
- Managed Workspaces — the three-layer model and discovery rules
- Transactions & Recovery — lock scopes and the
recoveringstate - sow.yml Reference —
protectedand per-Repository signing - Repository Layout — the fixed directory structure