Package References

The five ways to name a package on the command line, and how ambiguity is resolved.

sow rm, sow show, and sow where all take a PACKAGE argument. This page defines what you may write there. The same grammar applies to all three commands; only the handling of an ambiguous name differs.

Nothing here applies to sow add, which takes filesystem paths, not references.

The five forms

FormExampleMatches
Content digestsha256:d06d7f23b9cf...b98b1229Exactly one package object
RPM coordinaterpm:pev2-0:1.23.0-1.noarchExactly one RPM
DEB coordinatedeb:libpq5=18.3-1.pgdg12+1:amd64Exactly one DEB
Filenamepev2-1.23.0-1.noarch.rpmThe package stored under that filename
Bare namepev2Every version and architecture of that name

The first three are exact: they name one object and either hit it or fail. The last two are conveniences that may match more than one object.

You never have to construct these by hand. sow ls prints the digest and the coordinate of every package, in a form you can paste straight back into another command:

sow ls -d el9
repository=pigsty dists=el9 dirty=false
SHA256	COORDINATE	DISTS	BUILT_DISTS	POOL_PATH
sha256:ceb1b8660f8bc1fe59fb7a28e750e19a1ccd010a254a50e82328adb5818a5943	rpm:blackbox_exporter-0:0.28.0-1.aarch64	el9	el9	pool/b/blackbox_exporter/blackbox_exporter-0.28.0-1.aarch64.rpm
sha256:5759c643a789631346e3ed315a696a0118f81f7cc3c65e5a4385a876983d3a18	rpm:blackbox_exporter-0:0.28.0-1.x86_64	el9	el9	pool/b/blackbox_exporter/blackbox_exporter-0.28.0-1.x86_64.rpm
sha256:d06d7f23b9cfc6aedaab7b60c8e890cda020efe84f1f246243414862b98b1229	rpm:pev2-0:1.23.0-1.noarch	el9	el9	pool/p/pev2/pev2-1.23.0-1.noarch.rpm

Content digest

sha256:<64 lowercase hex digits>

The SHA-256 of the complete stored package bytes. This is the strongest reference SOW has: it is the object’s identity, so it can never be ambiguous.

sow where sha256:d06d7f23b9cfc6aedaab7b60c8e890cda020efe84f1f246243414862b98b1229
{"reference":"sha256:d06d7f23...b98b1229","locations":[{"repository":"pigsty","dists":["el9"],"built_dists":["el9"],"sha256":"d06d7f23...b98b1229","coordinate":"rpm:pev2-0:1.23.0-1.noarch"}]}

The digest must be complete and lowercase. There is no prefix matching and no case-folding — a short or uppercase digest is a usage rejection, not a failed lookup:

operation rejected: managed: operation rejected: sha256 reference requires 64 lowercase hexadecimal digits

Note that this digest covers the bytes as stored. If a repository re-signs RPM payloads, the digest of the object differs from the digest of the file you handed to sow add.

RPM coordinate

rpm:<name>-<epoch>:<version>-<release>.<arch>

The full NEVRA, prefixed with rpm:. Every component is required, including the epoch — 0 when the package has none.

sow where 'rpm:pev2-0:1.23.0-1.noarch'

Quote it in a shell: NEVRA contains a colon, and history expansion or path completion can otherwise mangle it.

Both the prefix and the epoch are load-bearing. Dropping either turns the string into a bare-name lookup that finds nothing:

sow where 'rpm:pev2-1.23.0-1.noarch'
operation rejected: managed: operation rejected: package reference "rpm:pev2-1.23.0-1.noarch" was not found in the selected Workspace scope

The architecture component is the one from the RPM header: x86_64, aarch64, or noarch. It is not the canonical family — a noarch package is written noarch here, even though SOW classifies it internally as neutral.

DEB coordinate

deb:<package>=<version>:<architecture>

The Debian identity triple, prefixed with deb:. The version is the complete Debian version including epoch and revision; the architecture is the ecosystem name (amd64, arm64, all), not the canonical family.

sow where 'deb:libpq5=18.3-1.pgdg12+1:amd64'

All three parts are required. deb:libpq5=18.3-1.pgdg12+1 without an architecture does not match anything.

Filename

The complete filename of the package as stored, including the extension:

sow where 'pev2-1.23.0-1.noarch.rpm'
sow where 'libpq5_18.3-1.pgdg12+1_amd64.deb'

This is the easiest form to type when you are looking at a directory listing. It is not an identity, though: filename is not what SOW uses to tell packages apart, and two distinct objects could in principle carry the same name. Prefer a coordinate or a digest in scripts.

Bare name

Just the binary package name:

sow where pev2

What this means depends on the command:

  • sow rm treats it as every version and native architecture of that name in the selected distributions. This is intentional — removing a package usually means removing all of it. Preview first with -c:

    sow rm libpq5 -d trixie -c
    
    {"repository":"pigsty","desired_revision":10,"built_generation":10,"dirty":false,"check":true,
     "removed":[{"dist":"trixie","sha256":"310611d0...","coordinate":"deb:libpq5=18.2-1.pgdg12+1:amd64","name":"libpq5"},
                {"dist":"trixie","sha256":"4b526223...","coordinate":"deb:libpq5=18.3-1.pgdg12+1:amd64","name":"libpq5"},
                {"dist":"trixie","sha256":"cadeb929...","coordinate":"deb:libpq5=18.3-1.pgdg12+1:arm64","name":"libpq5"}], ...}
    
  • sow show and sow where require it to identify exactly one object. They describe a single package, so a name matching several is refused with the candidate list:

    operation rejected: managed: operation rejected: package reference "libpq5" is ambiguous: deb:libpq5=18.2-1.pgdg12+1:amd64 sha256:310611d0fea1ce82644f48d90d485c60738b21e52ab5a60e1de43875bdfef601, deb:libpq5=18.3-1.pgdg12+1:amd64 sha256:4b5262231787caf1f367f5c8705a8a03d3176c31a15e6096946d50514db128be, deb:libpq5=18.3-1.pgdg12+1:arm64 sha256:cadeb9294901ac5ae6228bd3471c444cc288d9894af0dd0730909596d9dfcefb
    

    Every candidate is printed with both its coordinate and its digest, so the fix is to copy one of them back onto the command line.

What does not work

A NEVRA without the rpm: prefix looks like a coordinate but is parsed as a bare name, and bare names do not contain epochs or architectures:

sow rm 'pev2-0:1.23.0-1.noarch' -d el9 -c
operation rejected: managed: operation rejected: package reference not found: package reference "pev2-0:1.23.0-1.noarch" matches no Desired Membership

There is also no glob, no regex, no version range, and no --all flag. If you want to select a set of packages by pattern, that is membership policy in sow.yml, not a command-line selector. The command line only ever names packages that already exist.

Scope

A reference is resolved within a scope, and the scope is set by the usual selection flags, not by the reference:

CommandDefault scopeNarrow with
sow rmThe selected distributions of the selected repository-r, -d (required when several exist)
sow showThe selected repository-r, -d
sow whereEvery repository in the workspace-r, -d

sow where is the one that searches broadly — use it when you know a package exists somewhere but not where. sow show describes one object in one repository in full detail.

The two commands also word their misses differently, which tells you which one you ran:

# rm — the reference resolved, but nothing in the selected dists matches it
operation rejected: ... package reference "nosuchpkg" matches no Desired Membership

# show / where — nothing in the searched scope matches at all
operation rejected: ... package reference "nosuchpkg" was not found in the selected Workspace scope

Coordinates and identity

The coordinate forms above are the logical identity of a package, and SOW enforces that one coordinate maps to at most one content object inside a repository. Adding a different file under a coordinate that already exists is a hard conflict — SOW will not silently pick a winner, and there is no --replace.

Two packages that differ only in signature therefore still collide, because the coordinate is the same. If you re-sign a package for real, bump its release; if you are re-adding the identical input, SOW recognizes it and reports reused.

See also

Last modified: 2026-08-08: init commit (fe725aa)