Parmo: Online Manual

← Back to the project page

NAME

parmo - package and repository maintenance operator

SYNOPSIS

parmo [OPTION]... ACTION
parmo --help
parmo --version

DESCRIPTION

Build software from source, turn it into native operating system packages, and manage repositories of those packages.

Using docker(1) or podman(1), parmo can support multiple target operating systems on a single host, by automatically maintaining build environment containers for each target. Alternatively, parmo can run in native mode without containers, supporting only the operating system it is running on.

OPTIONS

Options must be specified before the actions and arguments.

-n, --native

Only use native commands, rather than using containers. This reduces the disk space needed, but removes the isolation that containers bring, and requires the relevant tools for the chosen action to be available on the host system.

-t, --target OS

Specify the target operating system for the action. This determines the appropriate package type and build image to use when building a package, indexing a repository, or updating a build image. The OS must be one of the operating systems listed by the “targets” action.

-s, --source PATH

Specify the data source for the action. When building a package, use the file specified by PATH as the source archive. When indexing a repository, make the index out of the packages under the directory specified by PATH.

-i, --instructions PATH

Specify the location of the instructions for building the package. If building an RPM, PATH must either be an RPM spec file, or a directory containing a spec file whose name ends with “.spec”. If building a Debian package, PATH must be a directory containing, at a minimum, a file named “control”.

-d, --destination PATH

Specify the destination for the action. When building a package or indexing a repository, store the resultant files in the directory PATH.

-k, --key FILE

Specify the file containing the signing key. When building a package or indexing a repository, sign the data with the key stored in FILE.

-c, --constraint KEY=VALUE

Constrain the action to only act where KEY matches VALUE. This option may be specified more than once. The KEY must be one of:

pinned

Whether the package is pinned to a specific version in the target repository; the value may be “true” or “false”.

included

Whether the package is present in the target repository (true or false).

outdated

Whether the package in the target repository has a newer version available in the source directory (true or false).

package

Restrict to a package with this specific name.

repository

Restrict to a specific repository.

target

Restrict to a specific target operating system.

-u, --user NAME

Record actions as being performed by NAME rather than the name of the current user.

-h, --help

Display a usage message on standard output and exit successfully.

-V, --version

Display version information on standard output and exit successfully.

ACTIONS

For the simplest use case, packages are built from source for a single target operating system and placed into a package archive directory, with “build-package”. The package archive directory is then indexed with “index-repository” to form a single repository containing every package.

Where there are multiple target operating systems, or more than one repository, packages are still built with “build-package”, with one package archive directory per target operating system. The appropriate version of each package is sent to each repository with “select”.

Refer to the EXAMPLES section for specific examples.

Actions for building packages

build-package

Build a package for the target operating system specified by --target from the source archive specified by --source and the instructions specified by --instructions, placing the resultant package files in the directory specified by --destination.

If a signing key is provided with --key, the package is signed.

If no build instructions are provided, the appropriate instructions are extracted from the source archive. If the source archive contains nothing suitable, automatic instructions are generated.

Each package file is accompanied by an information file with the same name plus a “.txt” suffix, containing the OS, package name, version, architecture, summary, and description.

build-instructions

Generate instructions for building a package from the source archive specified by --source, and place them in the directory specified by --destination. These will consist of an RPM spec file and Debian control, rules, and changelog files.

Actions for indexing individual repositories

index-repository

Generate indexes for a repository for the target operating system specified by --target, from the packages in the source directory specified by --source, placing the resultant index files in the directory specified by --destination. If no destination is specified, the source directory is used.

If a signing key is provided with --key, and the target operating system supports it, the indexes are signed.

Actions for managing package archives

archive-contents

List the filename, package name, version, architecture, target operating system, and summary of the packages in the package archive directory specified by --source. If the package archive directory contains a subdirectory per target operating system, “--constraint target” may also be used.

prune COUNT

For each package in the package archive directory specified by --source, remove older versions until there are no more than COUNT remaining. This should be run periodically to keep package archives from growing without limit. If the package archive directory contains a subdirectory per target operating system, “--constraint target” may also be used.

If a repository collection is specified with --destination, then a version of a package will not be removed from the --source archive if it is found to also be present under --destination, since this means that it is potentially still in use.

Actions for managing repository collections

repository-contents

List the filename, package name, version, architecture, repository, target operating system, pin note, and summary of the packages in the repository collection directory specified by --destination which match the constraints specified by the --constraint options.

The repository collection directory is expected to contain a subdirectory per repository name, and then a further subdirectory per target operating system, such as local/almalinux9.

When the constraints “included” or “outdated” are active, then the package archive directory specified by --source is used as a reference for the packages which are available for each target operating system.

If a package for a target operating system is not included in a repository but is available in the archive, it will be shown with a version of “-”, or it will be omitted if the constraint “included=true” is active.

If a package is pinned to a version (see below), its pin note is included, otherwise its pin note will be listed as “-”.

select PACKAGE VERSION

In each repository and target operating system under the repository collection directory specified by --destination, subject to constraints specified by the --constraint options, copy the VERSION of PACKAGE from the appropriate operating system subdirectory of the package archive directory specified by --source, and remove all other versions of it from the destination.

If the VERSION is “none” or “exclude”, the package is removed from the destination.

If the package is pinned to a particular version in a repository (see below), the operation fails if the VERSION does not match.

Once the changes have been made, each affected repository is automatically indexed as if by “index-repository”.

pin PACKAGE VERSION [NOTE]

The same as “select”, except the package's pinning status is also updated.

If a NOTE is supplied, the package is pinned at that version and the note is recorded. In this case the VERSION must not be “none” or “exclude”. Once the package is pinned, its version cannot be changed with “select”.

If no NOTE is supplied, or the NOTE is “-”, the package is unpinned.

Other actions

update-image

Open the container image for building packages for the target operating system specified by --target, and apply any outstanding updates to it. This action should be run periodically to keep build images up to date.

targets

List the supported target operating systems.

EXIT STATUS

0

Action successful.

1

There was a problem with the arguments supplied on the command line.

2

The action failed due to a local problem such as a write error, a full disk, and so on.

3

The selected action is not supported on this system.

FILES

Files in a package archive

A package archive directory contains packages which have been built by the “build-package” action.

PACKAGE-ARCHIVE/.target

The target operating system for this package archive. If the file is not present, it is created by the “build-package” action. If the file is present and does not match the --target of the “build-package” action, then the action will refuse to run.

PACKAGE-ARCHIVE/*.deb
PACKAGE-ARCHIVE/*.rpm

: The packages themselves.

PACKAGE-ARCHIVE/*.deb.txt
PACKAGE-ARCHIVE/*.rpm.txt

: The information file for each package, detailing the the OS, package name, version, architecture, summary, and description.

When using parmo with multiple target operating systems, use a separate subdirectory for each target operating system - named after that target - as the --destination for the “build-package”, so that the “select” action can use the main parent directory as its --source package archive. For example:

PACKAGE-ARCHIVE/almalinux8/somepackage-1.2.3-1.el8.x86_64.rpm
PACKAGE-ARCHIVE/debian12/somepackage_1.2.3_amd64.deb

: The AlmaLinux 8 and Debian 12 instances of version 1.2.3 of the package “somepackage”, in the package archive PACKAGE-ARCHIVE.

This allows “select” to operate on multiple target operating systems at once, making it much easier to manage deployments across a heterogeneous estate.

Note that “build-package” operates directly on its --destination, so it is up to you to point it at the relevant subdirectory if using a multi-target package archive.

Files in a repository collection

A repository collection directory contains one directory per named repository, with each one having a subdirectory for each target operating system.

COLLECTION-DIR/NAME/TARGET/*.deb
COLLECTION-DIR/NAME/TARGET/*.deb.txt
COLLECTION-DIR/NAME/TARGET/*.rpm
COLLECTION-DIR/NAME/TARGET/*.rpm.txt

: The packages for operating system TARGET in repository NAME, and their information files as described above. These files are copied here from a package archive, and removed from here, by the “select” and “pin” actions.

COLLECTION-DIR/NAME/TARGET/*.deb.pinned
COLLECTION-DIR/NAME/TARGET/*.rpm.pinned

: If this file - managed by the “pin” action - exists for a package, the package is considered to be pinned to the version listed in its “.txt” file. The first line of a “.pinned” file contains the note specifying the reason. The second line contains the username of the person who pinned it.

COLLECTION-DIR/NAME/TARGET/contents.txt

The filename, package name, version, architecture, repository, target operating system, pin note (“-” if not pinned), and summary of every package selected for operating system TARGET in repository NAME.

COLLECTION-DIR/NAME/TARGET/activity.log

A log of changes made to this specific repository by the “select” and “pin” actions. Note that although this file is unlikely to grow quickly, it is advisable to instruct some other tool such as logrotate(8) to rotate it regularly, or when it reaches a particular size.

COLLECTION-DIR/NAME/TARGET/.lock

A lock file used to ensure that multiple actions are never performed at once.

COLLECTION-DIR/NAME/TARGET/cache
COLLECTION-DIR/NAME/TARGET/dists
COLLECTION-DIR/NAME/TARGET/drpms
COLLECTION-DIR/NAME/TARGET/repodata

: The repository index data for the operating system TARGET's instance of repository NAME, generated when the “select” or “pin” actions change the repository contents and call an implicit “index-repository”.

EXAMPLES

Building RPMs for AlmaLinux 9 from the source of “pv”, automatically generating build instructions, and placing the RPMs in a package archive directory:

parmo --target almalinux9 --source pv-1.9.25.tar.gz --destination /packages/almalinux9 build-package

Generating build instructions from the source of “pv”, and placing them in a directory named pv-build:

parmo --source pv-1.9.25.tar.gz --destination pv-build build-instructions

Indexing a directory full of packages so it can be used as an apt repository by a Debian 12 system:

parmo --target debian12 --source /srv/debian12 index-repository

Selecting version 0.1.4 of “scw” for all available operating systems, from the package archive under /packages/, making them available in the repository named local under /repositories/ for each operating system, and automatically indexing each one:

parmo --source /packages --destination /repositories --constraint repository=local select scw 0.1.4

REPORTING BUGS

Please report any bugs to parmo@ivarch.com.

Alternatively, use the issue tracker linked from the parmo home page.

SEE ALSO

apt(8), dnf(8), yum(8), dpkg-buildpackage(1), dpkg-scanpackages(1), apt-ftparchive(1), rpmbuild(8), createrepo(8), docker(1), podman(1)

Copyright © 2025 Andrew Wood.

License GPLv3+: GNU GPL version 3 or later.

This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

← Back to the project page