123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- # APT External Dependency Solver Protocol (EDSP) - version 0.5
- This document describes the communication protocol between APT and
- external dependency solvers. The protocol is called APT EDSP, for "APT
- External Dependency Solver Protocol".
- ## Terminology
- In the following we use the term **architecture qualified package name**
- (or *arch-qualified package names* for short) to refer to package
- identifiers of the form "package:arch" where "package" is a package name
- and "arch" a dpkg architecture.
- ## Components
- - **APT**: we know this one.
- - APT is equipped with its own **internal solver** for dependencies,
- which is identified by the string `internal`.
- - **External solver**: an *external* software component able to resolve
- dependencies on behalf of APT.
-
- At each interaction with APT, a single solver is in use. When there is
- a total of 2 or more solvers, internals or externals, the user can
- choose which one to use.
- Each solver is identified by an unique string, the **solver
- name**. Solver names must be formed using only alphanumeric ASCII
- characters, dashes, and underscores; solver names must start with a
- lowercase ASCII letter. The special name `internal` denotes APT's
- internal solver, is reserved, and cannot be used by external solvers.
- ## Installation
- Each external solver is installed as a file under Dir::Bin::Solvers (see
- below), which defaults to `/usr/lib/apt/solvers`. We will assume in the
- remainder of this section that such a default value is in effect.
- The naming scheme is `/usr/lib/apt/solvers/NAME`, where `NAME` is the
- name of the external solver.
- Each file under `/usr/lib/apt/solvers` corresponding to an external
- solver must be executable.
- No non-solver files must be installed under `/usr/lib/apt/solvers`, so
- that an index of available external solvers can be obtained by listing
- the content of that directory.
- ## Configuration
- Several APT options can be used to affect dependency solving in APT. An
- overview of them is given below. Please refer to proper APT
- configuration documentation for more, and more up to date, information.
- - **APT::Solver**: the name of the solver to be used for
- dependency solving. Defaults to `internal`
- - **Dir::Bin::Solvers**: absolute path of the directory where to look for
- external solvers. Defaults to `/usr/lib/apt/solvers`.
- - **APT::Solver::Strict-Pinning**: whether pinning must be strictly
- respected (as the internal solver does) or can be slightly deviated
- from. Defaults to `yes`.
- - **APT::Solver::Preferences**: user preference string used during
- dependency solving by the requested solver. Check the documentation
- of the solver you are using if and what is supported as a value here.
- Defaults to the empty string.
- The options **Strict-Pinning** and **Preferences** can also be set for
- a specific solver only via **APT::Solver::NAME::Strict-Pinning** and
- **APT::Solver::NAME::Preferences** respectively where `NAME` is the name
- of the external solver this option should apply to. These options if set
- override the generic options; for simplicity the documentation will
- refer only to the generic options.
- ## Protocol
- When configured to use an external solver, APT will resort to it to
- decide which packages should be installed or removed.
- The interaction happens **in batch**: APT will invoke the external
- solver passing the current status of installed and available packages,
- as well as the user request to alter the set of installed packages. The
- external solver will compute a new complete set of installed packages
- and gives APT a "diff" listing of which *additional* packages should be
- installed and of which currently installed packages should be
- *removed*. (Note: the order in which those actions have to be performed
- will be up to APT to decide.)
- External solvers are invoked by executing them. Communications happens
- via the file descriptors: **stdin** (standard input) and **stdout**
- (standard output). stderr is not used by the EDSP protocol. Solvers can
- therefore use stderr to dump debugging information that could be
- inspected separately.
- After invocation, the protocol passes through a sequence of phases:
- 1. APT invokes the external solver
- 2. APT send to the solver a dependency solving **scenario**
- 3. The solver solves dependencies. During this phase the solver may
- send, repeatedly, **progress** information to APT.
- 4. The solver sends back to APT an **answer**, i.e. either a *solution*
- or an *error* report.
- 5. The external solver exits
- ### Scenario
- A scenario is a text file encoded in a format very similar to the "Deb
- 822" format (AKA "the format used by Debian `Packages` files"). A
- scenario consists of two distinct parts: a **request** and a **package
- universe**, occurring in that order. The request consists of a single
- Deb 822 stanza, while the package universe consists of several such
- stanzas. All stanzas occurring in a scenario are separated by an empty
- line.
- #### Request
- Within a dependency solving scenario, a request represents the action on
- installed packages requested by the user.
- A request is a single Deb 822 stanza opened by a mandatory Request field
- and followed by a mixture of action, preference, and global
- configuration fields.
- The value of the **Request:** field is a string describing the EDSP
- protocol which will be used to communicate. At present, the string must
- be `EDSP 0.5`. Request fields are mainly used to identify the beginning
- of a request stanza; their actual values are otherwise not used by the
- EDSP protocol.
- The following **configuration fields** are supported in request stanzas:
- - **Architecture:** (mandatory) The name of the *native* architecture on
- the user machine (see also: `dpkg --print-architecture`)
- - **Architectures:** (optional, defaults to the native architecture) A
- space separated list of *all* architectures known to APT (this is
- roughly equivalent to the union of `dpkg --print-architecture` and
- `dpkg --print-foreign-architectures`)
- The following **action fields** are supported in request stanzas:
- - **Install:** (optional, defaults to the empty string) A space
- separated list of arch-qualified package names, with *no version
- attached*, to install. This field denotes a list of packages that the
- user wants to install, usually via an APT `install` request.
- - **Remove:** (optional, defaults to the empty string) Same syntax of
- Install. This field denotes a list of packages that the user wants to
- remove, usually via APT `remove` or `purge` requests.
- - **Upgrade:** (optional, defaults to `no`). Allowed values: `yes`,
- `no`. When set to `yes`, an upgrade of all installed packages has been
- requested, usually via an APT `upgrade` request.
- - **Dist-Upgrade:** (optional, defaults to `no`). Allowed values: `yes`,
- `no`. Same as Upgrade, but for APT `dist-upgrade` requests.
- - **Autoremove:** (optional, defaults to `no`). Allowed values: `yes`,
- `no`. When set to `yes`, a clean up of unused automatically installed
- packages has been requested, usually via an APT `autoremove` request.
- The following **preference fields** are supported in request stanzas:
- - **Strict-Pinning:** (optional, defaults to `yes`). Allowed values:
- `yes`, `no`. When set to `yes`, APT pinning is strict, in the sense
- that the solver must not propose to install packages which are not APT
- candidates (see the `APT-Pin` and `APT-Candidate` fields in the
- package universe). When set to `no`, the solver does only a best
- effort attempt to install APT candidates. Usually, the value of this
- field comes from the `APT::Solver::Strict-Pinning` configuration
- option.
- - **Solver:** (optional, defaults to the empty string) a purely
- informational string specifying to which solver this request was send
- initially.
- - **Preferences:** (optional, defaults to the empty string)
- a solver-specific optimization string, usually coming from the
- `APT::Solver::Preferences` configuration option.
- #### Package universe
- A package universe is a list of Deb 822 stanzas, one per package, called
- **package stanzas**. Each package stanzas starts with a Package
- field. The following fields are supported in package stanzas:
- - All fields contained in the dpkg database, with the exception of
- fields marked as "internal" (see the manpage `dpkg-query (1)`). Among
- those fields, the following are mandatory for all package stanzas:
- Package, Version, Architecture.
-
- It is recommended not to pass the Description field to external
- solvers or, alternatively, to trim it to the short description only.
- - **Installed:** (optional, defaults to `no`). Allowed values: `yes`,
- `no`. When set to `yes`, the corresponding package is currently
- installed.
-
- Note: the Status field present in the dpkg database must not be passed
- to the external solver, as it's an internal dpkg field. Installed and
- other fields permit to encode the most relevant aspects of Status in
- communications with solvers.
- - **Hold:** (optional, defaults to `no`). Allowed values: `yes`,
- `no`. When set to `yes`, the corresponding package is marked as "on
- hold" by dpkg.
- - **APT-ID:** (mandatory). Unique package identifier, according to APT.
- - **APT-Pin:** (mandatory). Must be an integer. Package pin value,
- according to APT policy.
- - **APT-Candidate:** (optional, defaults to `no`). Allowed values:
- `yes`, `no`. When set to `yes`, the corresponding package is the APT
- candidate for installation among all available packages with the same
- name and architecture.
- - **APT-Automatic:** (optional, defaults to `no`). Allowed values:
- `yes`, `no`. When set to `yes`, the corresponding package is marked by
- APT as automatic installed. Note that automatic installed packages
- should be removed by the solver only when the Autoremove action is
- requested (see Request section).
- - **APT-Release:** (optional) The releases the package belongs to, according to
- APT. The format of this field is multiline with one value per line and the
- first line (the one containing the field name) empty. Each subsequent line
- corresponds to one of the releases the package belongs to and looks like
- this: `o=Debian,a=unstable,n=sid,l=Debian,c=main`. That is, each release line
- is a comma-separated list of "key=value" pairs, each of which denotes a
- Release file entry (Origin, Label, Codename, etc.) in the format of
- APT_PREFERENCES(5).
- - **Source:** (optional) The name of the source package the binary
- package this record is for was built from.
- This field does NOT include the version of the source package unlike
- the Source field in the dpkg database. The version is optionally
- available in the **Source-Version:** field.
- ### Answer
- An answer from the external solver to APT is either a *solution* or an
- *error*.
- The following invariant on **exit codes** must hold true. When the
- external solver is *able to find a solution*, it will write the solution
- to standard output and then exit with an exit code of 0. When the
- external solver is *unable to find a solution* (and is aware of that),
- it will write an error to standard output and then exit with an exit
- code of 0. An exit code other than 0 will be interpreted as a solver
- crash with no meaningful error about dependency resolution to convey to
- the user.
- #### Solution
- A solution is a list of Deb 822 stanzas. Each of them could be an install
- stanza (telling APT to install a specific new package or to upgrade or
- downgrade a package to a specific version), a remove stanza (telling APT to
- remove one), or an autoremove stanza (telling APT about the *future*
- possibility of removing a package using the Autoremove action).
- An **install stanza** starts with an Install field and supports the
- following fields:
- - **Install:** (mandatory). The value is a package identifier,
- referencing one of the package stanzas of the package universe via its
- APT-ID field.
- - All fields supported by package stanzas.
- **Remove stanzas** are similar to install stanzas, but have **Remove**
- fields instead of Install fields.
- **Autoremove stanzas** are similar to install stanzas, but have
- **Autoremove** fields instead of Install fields. Autoremove stanzas
- should be output so that APT can inform the user of which packages they
- can now autoremove, as a consequence of the executed action. However,
- this protocol makes no assumption on the fact that a subsequent
- invocation of an Autoremove action will actually remove the very same
- packages indicated by Autoremove stanzas in the former solution.
- A package can't be installed in multiple versions at the same time, so
- for each package there can at most one version be selected either for
- installation or removal. This especially means that a solver is neither
- allowed to represent package upgrades as a remove of the installed
- version and the installation of another (the remove is implicit and must
- be omitted from the solution) nor is it supported to revert previous
- actions in the solution with later actions. APT is allowed to show
- warnings and might even misbehave in earlier versions if a solver is
- violating this assumption.
- In terms of expressivity, install and remove stanzas can carry one
- single field each, as APT-IDs are enough to pinpoint packages to be
- installed/removed. Nonetheless, for protocol readability, it is
- recommended that solvers either add unconditionally the fields Package,
- Version, and Architecture to all install/remove stanzas or,
- alternatively, that they support a `--verbose` command line flag that
- explicitly enables the output of those fields in solutions.
- #### Error
- An error is a single Deb 822 stanza, starting the field Error. The
- following fields are supported in error stanzas:
- - **Error:** (mandatory). The value of this field is ignored, although
- it should be a unique error identifier, such as a UUID.
- - **Message:** (mandatory). The value of this field is a text string,
- meant to be read by humans, that explains the cause of the solver
- error. Message fields might be multi-line, like the Description field
- in the dpkg database. The first line conveys a short message, which
- can be explained in more details using subsequent lines.
- ### Progress
- During dependency solving, an external solver may send progress
- information to APT using **progress stanzas**. A progress stanza starts
- with the Progress field and might contain the following fields:
- - **Progress:** (mandatory). The value of this field is a date and time
- timestamp, in RFC 2822 format. The timestamp provides a time
- annotation for the progress report.
- - **Percentage:** (optional). An integer from 0 to 100, representing the
- completion of the dependency solving process, as declared by the
- solver.
- - **Message:** (optional). A textual message, meant to be read by the
- APT user, telling what is going on within the dependency solving
- (e.g. the current phase of dependency solving, as declared by the
- solver).
- # Future extensions
- Potential future extensions to this protocol, listed in no specific
- order, include:
- - fixed error types to identify common failures across solvers and
- enable APT to translate error messages
- - structured error data to explain failures in terms of packages and
- dependencies
|