Below you can find a short introduction (or primer) to the CUDF format: it should be enough to get you started in reading or writing CUDF documents. For a more in depth explaination of CUDF syntax and semantics, you would probably want to check the full specification of CUDF 2.0.
CUDF (for Common Upgradeability Description Format) is a document format meant to describe upgrade scenarios as commonly faced by package managers in Free and Open Source Software distributions.
Typically, in an upgrade scenario, there exists:
A current package universe describing all packages known to the package manager.
A current package status denoting all currently installed packages; the package status is contained in the package universe.
A user request representing the change that a user has asked the package manager to perform.
A CUDF document grasps all relevant details of the above entities, providing a common ground to describe the input of the dependency solver components found in most package managers.
package: m4 version: 3 depends: libc6 >= 8 package: openssl version: 11 depends: libc6 >= 18, libssl0.9.8 >= 8, zlib1g >= 1 conflicts: ssleay < 1 # and so on ...
CUDF is a simple plain text format, largely inspired by RFC 2822 (commonly known for being the basis of the mailbox format). Accordingly, a CUDF document is composed by several stanzas (or paragraphs), separated by an empty line.
Comments are allowed by using #
on the first column, and newlines are
in the Unix style (i.e. \n
or ASCII 0x0A
).
Each stanza consists of a set of key/value pairs, where keys are unique
within a given stanza. A single key/value pair denotes a property and
appears in the document as a single logical line obtained by concatenating:
the key, the string ": " (without quotes, i.e. a colon and the ASCII space
0x0A
), and the value.
Keys must match the regexp "^[a-z][a-z0-9-]*$
" (without quotes).
package: wesnoth version: 1 depends: libc6 >= 8, libfreetype6 >= 4, libfribidi0 >= 1, libgcc1 >= 6, libsdl-image1.2 >= 2, libsdl-mixer1.2 >= 1, libsdl-net1.2, libsdl1.2debian >= 3, libstdc++6 >= 5, libx11-6 , zlib1g >= 5, wesnoth-data = 1
Each value is, in the most general case, a single line of text. Still, to make CUDF documents more readable, long values can be split over multiple lines using line continuations. Each key/value pair line can be continued by subsequent line(s) starting with a space. All such lines taken together (the first line with the key and all continuations) form a single key value pair: the key is as usual, whereas the value is obtaining by concatenating the value on the first line with all continuations, taking care of removing the leading space of each continuation.
Each value in a stanza is in fact a typed value and you cannot generally
write arbitrary strings as values, for instance writing "foo
" as a package
version will lead to a parse error. CUDF supports several types and also lets
you define your own.
Generally you can ignore the gory details by just having a look at the examples below that highlight the most important types:
-2
, -1
, 0
, 1
, 2
, ...1
, 2
, 3
, ...true
, false
^[a-zA-Z0-9+./@()%-]+$
" : libc6
, libdb4.6
, libc-dev
, /bin/bash
(as
a virtual package in some distribution), ...python-minimal
: any package called python-minimal
libedac1 = 1
: version 1 of package libedac1
libxft2 > 1
: any version of libxft2
greater than 1haskell-doc <= 2
: any version of haskell-doc
less than or equal to 2libz-dev != 3
: any version of libz-dev
other than 3postfix > 2 | exim4-base
: either a version of postfix
greater than 2,
or any version of exim4-base
ocaml-nox, libc6 >= 6
: both (any version of) ocaml-nox
and a
version of libc6
greater than 6php4, apache | httpd
: both (any version of) php4
and one among: (any
version of) apache
and (any version of) httpd
:-)
|
") are
not allowed:
libc6
: any version of libc6
f2c, cpp
: any version of f2c
and any version of cpp
python >= 10 , python-support >= 11
: a version of python
greater or
equal to 10 and a version of python-support
greater or equal to 11For more details on available CUDF types, you should check Section 2.2.2 of the CUDF spec.
# sample CUDF document structure preamble: # documents start with an optional preamble # ... package: foo # then come several packages # ... package: bar # ... request: # and finally a mandatory request stanza # ...
The various stanzas that compose a CUDF document belong to 3 different kinds of stanzas, recognizable by the name of their first property.
A single preamble stanza (starting with the preamble
property) may
appear at the beginning of the document; it is forbidden to have such a
stanza elsewhere.
Then come several consecutive package stanzas (starting with the
package
property).
Finally, there must be a single and mandatory request stanza (starting
with the request
property) which concludes the document.
Each kind of stanza has a property scheme that defines the set of properties allowed therein, their types, and whether they are mandatory or optional (in the latter case, a default value is specified too).
Below you can find an overview of property schemata highlighting the most important properties; further details can be found in Section 2.2.3 of the CUDF spec.
A package stanza describes a single package known to the package manager; all package stanzas in a CUDF document describe the package universe as a whole.
package: ... (mandatory; type: package name; must be the first property) version: ... (mandatory; type: positive integer) installed: ... (optional; default: false; type: boolean) depends: ... (optional; type: package formula) conflicts: ... (optional; type: package list) provides: ... (optional; type: package list)
A few important remarks on the above properties:
version
s are positive integers, usual version strings like "1.2.3-4"
are not accepted (as they have no clear cross-distribution
semantics). Ideally, each set of versions in a given distribution has a total
order and can then be easily mapped to positive integers.
provides
account for features (or virtual packages): packages can
depend on features, such dependencies will be considered satisfied if at
least one package providing the features is installed.
CUDF features are versioned, you can provides: httpd > 2
; an
unversioned feature stands for providing all possible versions of that
feature.
conflicts
are not implicit among different versions of the same package:
multiple versions of the same package can be installed at the same
time.
Self-conflicts are ignored. This means that you can achieve
Debian-like implicit conflicts (i.e. only one version of each package can be
installed at any given time) as follows:
package: bash version: 5 conflicts: bash # i.e. conflict with all other versions of foo
Self-conflicts are ignored for virtual packages too, so you can achieve mutual-exclusion among a set of packages providing the same feature as follows:
package: postfix version: 2 provides: mail-transport-agent conflicts: mail-transport-agent package: exim version: 3 provides: mail-transport-agent conflicts: mail-transport-agent
The trailing request stanza describes the user request, that is which change the user wants to be performed to the set of installed packages (i.e. the package status).
request: ... (mandatory; type: string; value is ignored) install: ... (optional; type: package list) remove: ... (optional; type: package list) upgrade: ... (optional; type: package list)
install
, remove
, upgrade
are similar: they tell the solver which
packages must be, respectively, installed, removed, and upgraded. In all
cases version requirements can be specified, e.g. install: bash > 3
means that the user want to install a version of bash
greater than 3.
upgrade
poses additional requirements: all packages request to be upgraded:
The optional leading preamble can be used to provide document meta-information.
preamble: ... (mandatory; type: string; value is ignored) property: ... (optional; type: property declaration) univ-checksum: ... (optional; type: string)
property
is used to declare extra properties that should be allowed in
package stanzas (by default they are forbidden). The actual syntax and
semantics it's a bit tricky and should be checked for in Section 2.2.2 of the
CUDF spec. Here we simply give a representative example
that:
suite
property whose value must be one of: stable
,
testing
, unstable
bugs
property of integer type with a default value of
0installed-size
of positive integer typedescription
property of string type with default value
of no description
preamble: property: suite: enum [ stable , testing , unstable ] = [ stable ] , bugs: int = [0] , installed-size: posint , description: string = ["no description"] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c
univ-checksum
provides a checksum of the universe: a solver receiving
two CUDF documents with the same checksum is allowed to avoid parsing /
internalizing all packages again, in case it has a cache hit for that
Note that the description of all stanzas above is not complete, more properties and details are available, but you should really refer to the CUDF spec for that.