sow add
sow add imports packages into the selected Dists and builds their local indexes. It reads package format and architecture from the package headers, then applies each Dist’s policy. Use --skip to import several batches before one build. To update a remote target, run sow publish after the build.
Synopsis
Options
| Flag | Description | Default |
|---|---|---|
-R, --recursive |
Descend into subdirectories of a PATH directory |
off (top level only) |
--skip |
Update Desired state only; do not build | off |
-j, --jobs N |
Parallel workers for parsing, hashing and rendering | logical CPU count |
-C, --workdir DIR |
Workspace discovery start directory | current directory |
-r, --repo NAME |
Select a repository | selection rules |
-d, --dist NAME |
Select a distribution; repeatable | selection rules |
-T, --timeout DUR |
Maximum lock wait; 0 waits indefinitely |
0 |
-N, --no-wait |
Fail immediately when the lock is held | false |
--json |
Output JSON | false |
Inputs and targets
PATH can be a file or a directory. A directory is scanned top level only unless you pass -R.
Select one Repository and one or more Dists. Use -r and -d, or the directory-based defaults. In a mixed RPM/DEB batch, each package goes only to Dists of its format. A package with no compatible target fails.
Choose Dists that match the package’s intended distribution. SOW checks package format and architecture; it does not test operating-system or dependency compatibility.
The summary reports the Operation ID, item counts, and membership changes. It also shows the Desired Revision, Built Generation, and dirty state. Each input then has one item line, in stable order.
Item statuses
Each item line carries an overall status plus a per-Dist verdict in dists=.
| Status | Meaning |
|---|---|
accepted |
New Package Object created and at least one Membership added |
reused |
The content already exists in this Repository; only Membership references may change |
excluded |
Policy removed it from every target Dist — see the dists= field for excluded vs limited |
failed |
The package was rejected; the error= field says why |
reused is content idempotence: adding the same file twice never creates a second object or a
duplicate Membership. A repeated add also builds the selected Dist by default. If it is already
current, the Generation stays unchanged. If an earlier --skip or configuration change left it dirty, SOW completes the build and may advance the Generation:
The same object added to a second Dist is also reused — the pool keeps one copy and gains a second
Membership. Use --skip again to postpone the build.
Package architecture
add reads format and native architecture from the package header, then checks the Workspace permit
list. An unsupported architecture or one outside the configured list rejects that package:
RPM noarch and DEB all are architecture-neutral. They create one Package Object and one
Membership, and render into every effective architecture view of the target Dist. Only the selected Dists receive them.
Policy: exclude and limit
After merging into the target Memberships, SOW re-evaluates exclude and then limit over the
complete Dist candidate set. A package removed by policy is reported, not treated as a parse failure.
Here trixielim has exclude: [{kind: [dbgsym]}] and limit: 1. The dbgsym package was excluded by
rule; libpq5 18.2-1 lost to 18.3-1 under the version limit and is reported as limited. Both
appear as excluded in the top-level status, and the dists= field distinguishes them.
Limit groups by (binary name, canonical architecture), so 18.3-1:amd64 and 18.3-1:arm64 both
survive a limit: 1. A package can be accepted by one Dist and skipped by another in the same run.
To restore a package after relaxing exclude or limit, run sow add again. Policy applies to Desired membership, not every file left in pool/.
Partial batches
Valid, conflict-free packages are committed even when siblings fail. Failed inputs stay where they
are, each with its own error, and the command exits 3:
If every input fails, the operation exits 6; Desired memberships and public content
remain unchanged. Human output includes each failed input and its reason, and JSON includes
them in result.items:
Policy-excluded inputs are not input failures; an entirely excluded batch can succeed even
when the Dist was empty. If you interrupt the command with SIGINT or SIGTERM, it returns 130. Rerun it with the original input files; recovery preserves committed membership changes.
For changed package content, use a new version and filename. A previously published pool path remains reserved after local GC. A path conflict rejects that input; other valid inputs can still succeed.
Keep filename capitalization consistent when adding the same package again. Paths that differ only by case conflict. On a case-insensitive filesystem, source-package directory names must also be distinct; see Workspace filesystem.
–skip
--skip commits Desired membership and leaves pool/, dists/, and the Built Generation unchanged. New package files stay in private pending storage until a build needs them. The Repository is dirty when the resulting Desired state differs from Built state; reusing an unchanged member can leave it clean.
pending=4/2326 is four objects totalling 2326 bytes waiting in the private store. They never appear
in sow changes — only a successful build promotes them into the
deliverable tree.
Use --skip for bulk imports, then build once:
Processing order
SOW inspects the packages and signs new RPMs when configured. It applies exclude and limit, records the resulting membership, then builds unless --skip is set.
Input files remain unchanged. Signing uses private copies.
RPM signing modes
Managed RPM package signing is configured in sow.yml under signing.rpm.packages.mode; there is no
command-line override.
| Mode | Behavior |
|---|---|
never |
Keep the input bytes exactly |
fill |
Sign when unsigned or when the signature is not trusted; keep bytes when a trusted_keys signature verifies. Default when a key is configured |
always |
Ensure the final package is validly signed by the configured key; re-sign a stage copy otherwise |
Without a configured key only never is available.
Repeated imports reuse identical package content. They can also reuse an RPM whose only difference is its signature, if the stored package satisfies the current signing policy. A changed payload or an incompatible stored signature causes a coordinate conflict. See Signing Model for the matching rules.
Exit codes
| Code | Trigger |
|---|---|
0 |
Inputs processed, including policy-excluded inputs; build completed or skipped |
1 |
Runtime I/O, parser, renderer or signing failure |
2 |
Usage error, Workspace not found, or ambiguous Repository/Dist selection |
3 |
Partial batch — at least one item committed and at least one failed |
4 |
Repository lock held and --no-wait given or --timeout expired |
5 |
Integrity or recovery error, including a build that failed after applied |
6 |
Every input failed, or selection/signing/state preconditions reject the operation |
See also
- sow rm — the inverse operation
- sow build — build after
--skip - Membership Policy —
excluderules andlimitsemantics in full - Signing Model — the two trust chains and key references
- Package References — the coordinate grammar printed on each item line