]>
Commit | Line | Data |
---|---|---|
1 | # APT External Dependency Solver Protocol (EDSP) - version 0.5 | |
2 | ||
3 | This document describes the communication protocol between APT and | |
4 | external dependency solvers. The protocol is called APT EDSP, for "APT | |
5 | External Dependency Solver Protocol". | |
6 | ||
7 | ||
8 | ## Terminology | |
9 | ||
10 | In the following we use the term **architecture qualified package name** | |
11 | (or *arch-qualified package names* for short) to refer to package | |
12 | identifiers of the form "package:arch" where "package" is a package name | |
13 | and "arch" a dpkg architecture. | |
14 | ||
15 | ||
16 | ## Components | |
17 | ||
18 | - **APT**: we know this one. | |
19 | - APT is equipped with its own **internal solver** for dependencies, | |
20 | which is identified by the string `internal`. | |
21 | - **External solver**: an *external* software component able to resolve | |
22 | dependencies on behalf of APT. | |
23 | ||
24 | At each interaction with APT, a single solver is in use. When there is | |
25 | a total of 2 or more solvers, internals or externals, the user can | |
26 | choose which one to use. | |
27 | ||
28 | Each solver is identified by an unique string, the **solver | |
29 | name**. Solver names must be formed using only alphanumeric ASCII | |
30 | characters, dashes, and underscores; solver names must start with a | |
31 | lowercase ASCII letter. The special name `internal` denotes APT's | |
32 | internal solver, is reserved, and cannot be used by external solvers. | |
33 | ||
34 | ||
35 | ## Installation | |
36 | ||
37 | Each external solver is installed as a file under Dir::Bin::Solvers (see | |
38 | below), which defaults to `/usr/lib/apt/solvers`. We will assume in the | |
39 | remainder of this section that such a default value is in effect. | |
40 | ||
41 | The naming scheme is `/usr/lib/apt/solvers/NAME`, where `NAME` is the | |
42 | name of the external solver. | |
43 | ||
44 | Each file under `/usr/lib/apt/solvers` corresponding to an external | |
45 | solver must be executable. | |
46 | ||
47 | No non-solver files must be installed under `/usr/lib/apt/solvers`, so | |
48 | that an index of available external solvers can be obtained by listing | |
49 | the content of that directory. | |
50 | ||
51 | ||
52 | ## Configuration | |
53 | ||
54 | Several APT options can be used to affect dependency solving in APT. An | |
55 | overview of them is given below. Please refer to proper APT | |
56 | configuration documentation for more, and more up to date, information. | |
57 | ||
58 | - **APT::Solver**: the name of the solver to be used for | |
59 | dependency solving. Defaults to `internal` | |
60 | ||
61 | - **Dir::Bin::Solvers**: absolute path of the directory where to look for | |
62 | external solvers. Defaults to `/usr/lib/apt/solvers`. | |
63 | ||
64 | - **APT::Solver::Strict-Pinning**: whether pinning must be strictly | |
65 | respected (as the internal solver does) or can be slightly deviated | |
66 | from. Defaults to `yes`. | |
67 | ||
68 | - **APT::Solver::Preferences**: user preference string used during | |
69 | dependency solving by the requested solver. Check the documentation | |
70 | of the solver you are using if and what is supported as a value here. | |
71 | Defaults to the empty string. | |
72 | ||
73 | - **APT::Solver::RunAsUser**: if APT itself is run as root it will | |
74 | change to this user before executing the solver. Defaults to the value | |
75 | of APT::Sandbox::User, which itself defaults to `_apt`. Can be | |
76 | disabled by set this option to `root`. | |
77 | ||
78 | The options **Strict-Pinning** and **Preferences** can also be set for | |
79 | a specific solver only via **APT::Solver::NAME::Strict-Pinning** and | |
80 | **APT::Solver::NAME::Preferences** respectively where `NAME` is the name | |
81 | of the external solver this option should apply to. These options if set | |
82 | override the generic options; for simplicity the documentation will | |
83 | refer only to the generic options. | |
84 | ||
85 | ||
86 | ## Protocol | |
87 | ||
88 | When configured to use an external solver, APT will resort to it to | |
89 | decide which packages should be installed or removed. | |
90 | ||
91 | The interaction happens **in batch**: APT will invoke the external | |
92 | solver passing the current status of installed and available packages, | |
93 | as well as the user request to alter the set of installed packages. The | |
94 | external solver will compute a new complete set of installed packages | |
95 | and gives APT a "diff" listing of which *additional* packages should be | |
96 | installed and of which currently installed packages should be | |
97 | *removed*. (Note: the order in which those actions have to be performed | |
98 | will be up to APT to decide.) | |
99 | ||
100 | External solvers are invoked by executing them. Communications happens | |
101 | via the file descriptors: **stdin** (standard input) and **stdout** | |
102 | (standard output). stderr is not used by the EDSP protocol. Solvers can | |
103 | therefore use stderr to dump debugging information that could be | |
104 | inspected separately. | |
105 | ||
106 | After invocation, the protocol passes through a sequence of phases: | |
107 | ||
108 | 1. APT invokes the external solver | |
109 | 2. APT send to the solver a dependency solving **scenario** | |
110 | 3. The solver solves dependencies. During this phase the solver may | |
111 | send, repeatedly, **progress** information to APT. | |
112 | 4. The solver sends back to APT an **answer**, i.e. either a *solution* | |
113 | or an *error* report. | |
114 | 5. The external solver exits | |
115 | ||
116 | ||
117 | ### Scenario | |
118 | ||
119 | A scenario is a text file encoded in a format very similar to the "Deb | |
120 | 822" format (AKA "the format used by Debian `Packages` files"). A | |
121 | scenario consists of two distinct parts: a **request** and a **package | |
122 | universe**, occurring in that order. The request consists of a single | |
123 | Deb 822 stanza, while the package universe consists of several such | |
124 | stanzas. All stanzas occurring in a scenario are separated by an empty | |
125 | line. | |
126 | ||
127 | ||
128 | #### Request | |
129 | ||
130 | Within a dependency solving scenario, a request represents the action on | |
131 | installed packages requested by the user. | |
132 | ||
133 | A request is a single Deb 822 stanza opened by a mandatory Request field | |
134 | and followed by a mixture of action, preference, and global | |
135 | configuration fields. | |
136 | ||
137 | The value of the **Request:** field is a string describing the EDSP | |
138 | protocol which will be used to communicate. At present, the string must | |
139 | be `EDSP 0.5`. Request fields are mainly used to identify the beginning | |
140 | of a request stanza; their actual values are otherwise not used by the | |
141 | EDSP protocol. | |
142 | ||
143 | The following **configuration fields** are supported in request stanzas: | |
144 | ||
145 | - **Architecture:** (mandatory) The name of the *native* architecture on | |
146 | the user machine (see also: `dpkg --print-architecture`) | |
147 | ||
148 | - **Architectures:** (optional, defaults to the native architecture) A | |
149 | space separated list of *all* architectures known to APT (this is | |
150 | roughly equivalent to the union of `dpkg --print-architecture` and | |
151 | `dpkg --print-foreign-architectures`) | |
152 | ||
153 | The following **action fields** are supported in request stanzas: | |
154 | ||
155 | - **Install:** (optional, defaults to the empty string) A space | |
156 | separated list of arch-qualified package names, with *no version | |
157 | attached*, to install. This field denotes a list of packages that the | |
158 | user wants to install, usually via an APT `install` request. | |
159 | ||
160 | - **Remove:** (optional, defaults to the empty string) Same syntax of | |
161 | Install. This field denotes a list of packages that the user wants to | |
162 | remove, usually via APT `remove` or `purge` requests. | |
163 | ||
164 | - **Upgrade-All:** (optional, defaults to `no`). Allowed values `yes`, | |
165 | `no`. When set to `yes`, an upgrade of all installed packages has been | |
166 | requested, usually via an upgrade command like 'apt full-upgrade'. | |
167 | ||
168 | - **Autoremove:** (optional, defaults to `no`). Allowed values: `yes`, | |
169 | `no`. When set to `yes`, a clean up of unused automatically installed | |
170 | packages has been requested, usually via an APT `autoremove` request. | |
171 | ||
172 | - **Upgrade:** (deprecated, optional, defaults to `no`). Allowed values: | |
173 | `yes`, `no`. When set to `yes`, an upgrade of all installed packages | |
174 | has been requested, usually via an APT `upgrade` request. A value of | |
175 | `yes` is equivalent to the fields `Upgrade-All`, | |
176 | `Forbid-New-Install`and `Forbid-Remove` all set to `yes`. | |
177 | ||
178 | - **Dist-Upgrade:** (deprecated, optional, defaults to `no`). Allowed | |
179 | values: `yes`, `no`. Same as Upgrade, but for APT `dist-upgrade` | |
180 | requests. A value of `yes` is equivalent to the field `Upgrade-All` | |
181 | set to `yes` and the fields `Forbid-New-Install`and `Forbid-Remove` | |
182 | set to `no`. | |
183 | ||
184 | The following **preference fields** are supported in request stanzas: | |
185 | ||
186 | - **Strict-Pinning:** (optional, defaults to `yes`). Allowed values: | |
187 | `yes`, `no`. When set to `yes`, APT pinning is strict, in the sense | |
188 | that the solver must not propose to install packages which are not APT | |
189 | candidates (see the `APT-Pin` and `APT-Candidate` fields in the | |
190 | package universe). When set to `no`, the solver does only a best | |
191 | effort attempt to install APT candidates. Usually, the value of this | |
192 | field comes from the `APT::Solver::Strict-Pinning` configuration | |
193 | option. | |
194 | ||
195 | - **Forbid-New-Install:* (optional, defaults to `no`). Allowed values: | |
196 | `yes`, `no`. When set to `yes` the resolver is forbidden to install | |
197 | new packages in its returned solution. | |
198 | ||
199 | - **Forbid-Remove:* (optional, defaults to `no`). Allowed values: `yes`, | |
200 | `no`. When set to `yes` the resolver is forbidden to remove currently | |
201 | installed packages in its returned solution. | |
202 | ||
203 | - **Solver:** (optional, defaults to the empty string) a purely | |
204 | informational string specifying to which solver this request was send | |
205 | initially. | |
206 | ||
207 | - **Preferences:** (optional, defaults to the empty string) | |
208 | a solver-specific optimization string, usually coming from the | |
209 | `APT::Solver::Preferences` configuration option. | |
210 | ||
211 | ||
212 | #### Package universe | |
213 | ||
214 | A package universe is a list of Deb 822 stanzas, one per package, called | |
215 | **package stanzas**. Each package stanzas starts with a Package | |
216 | field. The following fields are supported in package stanzas: | |
217 | ||
218 | - All fields contained in the dpkg database, with the exception of | |
219 | fields marked as "internal" (see the manpage `dpkg-query (1)`). Among | |
220 | those fields, the following are mandatory for all package stanzas: | |
221 | Package, Version, Architecture. | |
222 | ||
223 | It is recommended not to pass the Description field to external | |
224 | solvers or, alternatively, to trim it to the short description only. | |
225 | ||
226 | - **Installed:** (optional, defaults to `no`). Allowed values: `yes`, | |
227 | `no`. When set to `yes`, the corresponding package is currently | |
228 | installed. | |
229 | ||
230 | Note: the Status field present in the dpkg database must not be passed | |
231 | to the external solver, as it's an internal dpkg field. Installed and | |
232 | other fields permit to encode the most relevant aspects of Status in | |
233 | communications with solvers. | |
234 | ||
235 | - **Hold:** (optional, defaults to `no`). Allowed values: `yes`, | |
236 | `no`. When set to `yes`, the corresponding package is marked as "on | |
237 | hold" by dpkg. | |
238 | ||
239 | - **APT-ID:** (mandatory). Unique package identifier, according to APT. | |
240 | ||
241 | - **APT-Pin:** (mandatory). Must be an integer. Package pin value, | |
242 | according to APT policy. | |
243 | ||
244 | - **APT-Candidate:** (optional, defaults to `no`). Allowed values: | |
245 | `yes`, `no`. When set to `yes`, the corresponding package is the APT | |
246 | candidate for installation among all available packages with the same | |
247 | name and architecture. | |
248 | ||
249 | - **APT-Automatic:** (optional, defaults to `no`). Allowed values: | |
250 | `yes`, `no`. When set to `yes`, the corresponding package is marked by | |
251 | APT as automatic installed. Note that automatic installed packages | |
252 | should be removed by the solver only when the Autoremove action is | |
253 | requested (see Request section). | |
254 | ||
255 | - **APT-Release:** (optional) The releases the package belongs to, according to | |
256 | APT. The format of this field is multiline with one value per line and the | |
257 | first line (the one containing the field name) empty. Each subsequent line | |
258 | corresponds to one of the releases the package belongs to and looks like | |
259 | this: `o=Debian,a=unstable,n=sid,l=Debian,c=main`. That is, each release line | |
260 | is a comma-separated list of "key=value" pairs, each of which denotes a | |
261 | Release file entry (Origin, Label, Codename, etc.) in the format of | |
262 | APT_PREFERENCES(5). | |
263 | ||
264 | - **Source:** (optional) The name of the source package the binary | |
265 | package this record is for was built from. | |
266 | This field does NOT include the version of the source package unlike | |
267 | the Source field in the dpkg database. The version is optionally | |
268 | available in the **Source-Version:** field. | |
269 | ||
270 | ||
271 | ### Answer | |
272 | ||
273 | An answer from the external solver to APT is either a *solution* or an | |
274 | *error*. | |
275 | ||
276 | The following invariant on **exit codes** must hold true. When the | |
277 | external solver is *able to find a solution*, it will write the solution | |
278 | to standard output and then exit with an exit code of 0. When the | |
279 | external solver is *unable to find a solution* (and is aware of that), | |
280 | it will write an error to standard output and then exit with an exit | |
281 | code of 0. An exit code other than 0 will be interpreted as a solver | |
282 | crash with no meaningful error about dependency resolution to convey to | |
283 | the user. | |
284 | ||
285 | ||
286 | #### Solution | |
287 | ||
288 | A solution is a list of Deb 822 stanzas. Each of them could be an install | |
289 | stanza (telling APT to install a specific new package or to upgrade or | |
290 | downgrade a package to a specific version), a remove stanza (telling APT to | |
291 | remove one), or an autoremove stanza (telling APT about the *future* | |
292 | possibility of removing a package using the Autoremove action). | |
293 | ||
294 | An **install stanza** starts with an Install field and supports the | |
295 | following fields: | |
296 | ||
297 | - **Install:** (mandatory). The value is a package identifier, | |
298 | referencing one of the package stanzas of the package universe via its | |
299 | APT-ID field. | |
300 | ||
301 | - All fields supported by package stanzas. | |
302 | ||
303 | **Remove stanzas** are similar to install stanzas, but have **Remove** | |
304 | fields instead of Install fields. | |
305 | ||
306 | **Autoremove stanzas** are similar to install stanzas, but have | |
307 | **Autoremove** fields instead of Install fields. Autoremove stanzas | |
308 | should be output so that APT can inform the user of which packages they | |
309 | can now autoremove, as a consequence of the executed action. However, | |
310 | this protocol makes no assumption on the fact that a subsequent | |
311 | invocation of an Autoremove action will actually remove the very same | |
312 | packages indicated by Autoremove stanzas in the former solution. | |
313 | ||
314 | A package can't be installed in multiple versions at the same time, so | |
315 | for each package there can at most one version be selected either for | |
316 | installation or removal. This especially means that a solver is neither | |
317 | allowed to represent package upgrades as a remove of the installed | |
318 | version and the installation of another (the remove is implicit and must | |
319 | be omitted from the solution) nor is it supported to revert previous | |
320 | actions in the solution with later actions. APT is allowed to show | |
321 | warnings and might even misbehave in earlier versions if a solver is | |
322 | violating this assumption. | |
323 | ||
324 | In terms of expressivity, install and remove stanzas can carry one | |
325 | single field each, as APT-IDs are enough to pinpoint packages to be | |
326 | installed/removed. Nonetheless, for protocol readability, it is | |
327 | recommended that solvers either add unconditionally the fields Package, | |
328 | Version, and Architecture to all install/remove stanzas or, | |
329 | alternatively, that they support a `--verbose` command line flag that | |
330 | explicitly enables the output of those fields in solutions. | |
331 | ||
332 | ||
333 | #### Error | |
334 | ||
335 | An error is a single Deb 822 stanza, starting the field Error. The | |
336 | following fields are supported in error stanzas: | |
337 | ||
338 | - **Error:** (mandatory). The value of this field is ignored, although | |
339 | it should be a unique error identifier, such as a UUID. | |
340 | ||
341 | - **Message:** (mandatory). The value of this field is a text string, | |
342 | meant to be read by humans, that explains the cause of the solver | |
343 | error. Message fields might be multi-line, like the Description field | |
344 | in the dpkg database. The first line conveys a short message, which | |
345 | can be explained in more details using subsequent lines. | |
346 | ||
347 | ||
348 | ### Progress | |
349 | ||
350 | During dependency solving, an external solver may send progress | |
351 | information to APT using **progress stanzas**. A progress stanza starts | |
352 | with the Progress field and might contain the following fields: | |
353 | ||
354 | - **Progress:** (mandatory). The value of this field is a date and time | |
355 | timestamp from the UTC timezone, in RFC 2822 format (see 'date -uR' as | |
356 | an example). The timestamp provides a time annotation for the | |
357 | progress report. | |
358 | ||
359 | - **Percentage:** (optional). An integer from 0 to 100, representing the | |
360 | completion of the dependency solving process, as declared by the | |
361 | solver. | |
362 | ||
363 | - **Message:** (optional). A textual message, meant to be read by the | |
364 | APT user, telling what is going on within the dependency solving | |
365 | (e.g. the current phase of dependency solving, as declared by the | |
366 | solver). | |
367 | ||
368 | ||
369 | # Future extensions | |
370 | ||
371 | Potential future extensions to this protocol, listed in no specific | |
372 | order, include: | |
373 | ||
374 | - fixed error types to identify common failures across solvers and | |
375 | enable APT to translate error messages | |
376 | - structured error data to explain failures in terms of packages and | |
377 | dependencies |