Zero Install

the antidote to app-stores

Selections file format specification

This document describes the format of 0install's XML selections documents. A selections document contains all the information needed to launch a program. 0install generates a selections document by collecting information from multiple feeds and then running a solver to choose the best combination of components.

For example, to generate the selections document for the ROX Edit application:

  $ 0install select --xml http://rox.sourceforge.net/2005/interfaces/Edit

For an app, foo, the current selections can be found in ~/.config/0install.net/apps/foo/selections.xml. For binaries generated by 0compile, the selections used to build it can be found in the 0install directory of the binary package, in the build-environment.xml file.

Changes to this document (and to the rest of the web-site) are tracked using Git.

Contents

  1. <selections>
  2. <selection>
  3. Executing the selections
  4. Future plans

<selections>

A selections document contains a set of selections, one per selected interface.

<?xml version="1.0" ?>
<selections
    xmlns="http://zero-install.sourceforge.net/2004/injector/interface"
    interface="..."
    command="..." ?
    source="true|false" ? >

  [ selection ] +
</selections>
interface
The URI of the main program being run (e.g. "http://rox.sourceforge.net/2005/interfaces/Edit").
command
The name of the (optional) <command> to run on the main program (e.g. "run").
source
Indicates whether the root is source or binary (since 0install 2.8). This is useful if implementations of both are present.

Historical notes

Before 0install 1.2, there was no command attribute on the root. Instead, the root <selections> element also contained a set of <command> elements as direct children. The first <command> was for the main interface, the second was for its <runner> and so on. In later versions, the commands go inside their <selection> elements, which is needed to support executable bindings.

Before 0install 0.51, there were no commands at all. Instead, the <selection> for the main interface had a main attribute which was used (the command should be treated as "run" in this case).

<selection>

<selection
      interface="..."
      from-feed="..." ?
      local-path="..." ?
      quick-test-file="..." ?
      ... >
    [ dependencies ]
    [ bindings ]
    [ digests ]
    [ commands ]
</selection>
interface
Indicates that this is the selected implementation of this interface.
from-feed
The URL of the feed which provided this implementation. If missing, use the value of interface.
local-path
For local implementations, this is the path of the directory containing the implementation.
quick-test-file
A file which, if present, indicates that the selection is still valid. This is sometimes used with distribution-provided selections. If not present and the ID starts with "package:", you'll need to query the distribution's package manager to check that this version is still installed.
Other attributes
All attributes from the selected <implementation> are included on the <selection>, except for stability and the deprecated main and self-test attributes, which were replaced by commands. The most useful ones are id and version.

The dependencies, bindings, digests and commands are defined in the feed specification. <restricts> elements are not included.

As in feed files, the id may also be used as a digest or a local path in older documents. See the feed specification for details.

Executing the selections

0install performs the following steps when running an app:

  1. Load the saved selections XML (or do an update if missing).
  2. Check that they are valid and up-to-date.
  3. Process all the bindings to set up the new environment.
  4. Build the command line arguments, starting with the main command and following the chain of <runner>s.
  5. Exec the new process.

Checking the selections are up-to-date

This is how 0install checks the selections for an app before running them:

  1. If any input files have changed or disappeared since the solver last ran, we re-run the solver. The files checked are:

    • The previously selected feed files (local or cached).
    • Configuration files for the selected interfaces (e.g. preferred stability).
    • The global configuration file (e.g. preferred stability).

    0install currently ignores feeds and interfaces which were considered but not selected.

  2. If any selections are no longer present, we rerun the solver. For distribution packages, we check that the version hasn't changed.

  3. If it has been a while since we checked for updates, we trigger a background update but run the current selections anyway.

Processing bindings

For each <selection>, 0install will:

  1. Process all bindings directly inside the <selection>.
  2. Process all dependencies directly inside the <selection>:
    1. Find the selection for the required interface (note: may be missing for non-essential dependencies).
    2. Process all bindings inside the dependency.
  3. Process all commands directly inside the <selection>:
    1. Process all bindings inside the command.
    2. Process all dependencies inside the command, including their bindings (as above) and also including any <runner>.

Having located all the bindings:

  1. Calculate the environment for the new process by expanding all <environment> bindings.
  2. Process all <executable-in-var> and <executable-in-path> bindings. Note: you must do this after expanding all other environment variables because of $-expansion in <arg>.

A binding directly inside a <selection> or <command> binds a selection to itself (e.g. a Python library may wish to add itself to PYTHONPATH). Bindings inside dependencies bind to the dependency (e.g. a Python program may wish to add a library to PYTHONPATH).

A distribution-provided selection does not have a path, and so any <environment> bindings for it are skipped (e.g. it's up to the distribution package manager to ensure that Python libraries it provides are in the default search path).

Future plans

Indexing the selections by interface URI is a bit restrictive. Once we get scoping, we'll need to cope with e.g. a Python 2 program that depends on a Python 3 program, which will require two different selections for the Python interface.