281 lines
16 KiB
ReStructuredText
281 lines
16 KiB
ReStructuredText
|
=================================
|
||
|
Package Management Infrastructure
|
||
|
=================================
|
||
|
This pages gives an overview of what components belong to Haiku's package
|
||
|
management infrastructure and how they work and interact.
|
||
|
|
||
|
- **package** and **package_repo** are command line tools for building package
|
||
|
and package repository files. They are discussed in `Building Packages`_.
|
||
|
- **packagefs** is the file system that virtually extracts activated packages.
|
||
|
- The **package kit** is an API for package management related programming.
|
||
|
- The **dependency solver** is a part of the package kit. It solves dependencies
|
||
|
between packages.
|
||
|
- The **package management daemon** (short: package daemon) is a background
|
||
|
process that is activated whenever the user adds packages to or removes them
|
||
|
from one of their activation locations. It verifies that all dependencies are
|
||
|
fulfilled (prompting the user, if necessary) and performs whatever package
|
||
|
pre-activation/post-deactivation tasks are required. The daemon is also
|
||
|
contacted by the package manager (after it has resolved dependencies and
|
||
|
downloaded all required packages) to do the package de-/activation.
|
||
|
- The **package manager** provides the user interface for software installation,
|
||
|
update, and removal. There are actually two programs, ``pkgman``, a command
|
||
|
line tool, and, ``HaikuDepot``, a GUI application.
|
||
|
|
||
|
.. _Building Packages: BuildingPackages.rst
|
||
|
|
||
|
.. image:: package-management-infrastructure.png
|
||
|
:align: center
|
||
|
|
||
|
Software Installation Locations
|
||
|
===============================
|
||
|
In Haiku there are two main locations where software is installed.
|
||
|
"/boot/system" and "/boot/home/config". "/boot/system" is where system-wide
|
||
|
software (i.e. software for all users), including the base system, is installed,
|
||
|
while "/boot/home/config" is only for the user's software. The discrimination
|
||
|
between those two doesn't make that much sense yet, but when Haiku supports
|
||
|
multi-user it will (obviously each user will need their own home directory then,
|
||
|
e.g. "/boot/home/<user>").
|
||
|
|
||
|
At both main installation locations a packagefs instance is mounted. Each
|
||
|
instance presents a virtually extracted union of the contents of all packages in
|
||
|
the subdirectory "packages" of that location. E.g. if one would extract the
|
||
|
contents of all package files in "/boot/system/packages" to an actual directory,
|
||
|
that would match exactly what is presented by packagefs in "/boot/system". With
|
||
|
a few exceptions -- packagefs provides several additional directories.
|
||
|
|
||
|
There are so-called shine-through directories which live on the underlying BFS
|
||
|
volume. Normally a file system mounted at a directory would completely hide
|
||
|
anything that is in that directory. These shine-through directories are handled
|
||
|
specially, though; packagefs shows them just like they are on the BFS volume.
|
||
|
One of those directories is "packages". This is necessary since otherwise it
|
||
|
wouldn't be possible to add, remove, or update any packages. Further
|
||
|
shine-through directories are "settings", "cache", "var", and "non-packaged".
|
||
|
The latter is a place where software can be installed the "traditional",
|
||
|
i.e. unpackaged, way.
|
||
|
|
||
|
Software Installation
|
||
|
=====================
|
||
|
Manual Installation
|
||
|
-------------------
|
||
|
At the lowest level software can be installed by simply dropping a respective
|
||
|
package file in a "packages" subdirectory of one of "/boot/system" or
|
||
|
"/boot/home/config". The package daemon, a background process that sleeps most
|
||
|
of the time, monitors the directory and, when happy with the newly added
|
||
|
package, it asks packagefs to presents its contents on the fly in the directory
|
||
|
structure. The package is said to be activated. Removing a package has the
|
||
|
opposite effect.
|
||
|
|
||
|
Things are a bit more complicated due to the fact that packages usually have
|
||
|
dependencies. E.g. when adding a package that has an unsatisfied dependency
|
||
|
(e.g. needs a certain library that is not installed) it is not a good idea to
|
||
|
activate the package nonetheless. The package contents (programs, libraries,...)
|
||
|
might not work correctly, and, e.g. when shadowing other installed software,
|
||
|
might even break things that worked before.
|
||
|
|
||
|
That's why the package daemon doesn't just activate any well-formed packages.
|
||
|
Instead it examines the new situation and checks whether all dependencies are
|
||
|
fulfilled and whether there are any conflicts. If they aren't any problems, it
|
||
|
tells packagefs to activate/deactivate the packages as requested. In case there
|
||
|
are issues with the dependencies, according to how it has been configured via
|
||
|
settings, the daemon prompts the user immediately, checks remote repositories
|
||
|
for solutions to the problem and presents the user with the possible options, or
|
||
|
it even performs all necessary actions without bothering the user, if possible.
|
||
|
In the end, if the problems could be solved (e.g. by downloading additional
|
||
|
packages), the respective packages will be de-/activated, or, otherwise, nothing
|
||
|
will be changed.
|
||
|
|
||
|
To avoid always having to check all dependencies when booting, the package
|
||
|
daemon writes the last consistent state of package activations to the file
|
||
|
"packages/administrative/activated-packages". When being mounted packagefs,
|
||
|
reads that file and only activates the packages specified by it. If the file is
|
||
|
missing or packages it refers to cannot be found or loaded, packagefs falls back
|
||
|
to activating all packages in the "packages" directory. The package daemon, once
|
||
|
started, checks the state.
|
||
|
|
||
|
Installation via Package Manager
|
||
|
--------------------------------
|
||
|
While manual software installation is possible, the more comfortable way is to
|
||
|
use the package manager. The package manager has a configurable list of remote
|
||
|
software repositories. It knows what software is available in those repositories
|
||
|
and what is installed locally. After the user has selected software packages to
|
||
|
be installed/deinstalled, package dependencies are resolved, and packages are
|
||
|
downloaded and moved to their installation location.
|
||
|
|
||
|
The package manager prepares a transaction directory, a subdirectory in the
|
||
|
"packages/administrative" directory, which contains the new packages. It then
|
||
|
contacts the package management daemon (via the package kit) to perform the
|
||
|
package activation changes. The daemon moves the new packages to the "packages"
|
||
|
directory, moves obsolete packages to an old state directory (also a
|
||
|
subdirectory in the "packages/administrative" directory, with the current
|
||
|
date and time encoded in its name) and asks packagefs to activate/deactivate the
|
||
|
respective packages. The old state directories allow recovery of old states.
|
||
|
That is particularly interesting for the system installation location. As as
|
||
|
safe mode/recovery option, the boot loader offers the user to select an old
|
||
|
installation state which can then be booted into, instead of the latest state.
|
||
|
|
||
|
Application Bundles
|
||
|
-------------------
|
||
|
Haiku also supports a concept that is commonly referred to as application
|
||
|
bundles. An application bundle is a fully self-contained package that doesn't
|
||
|
need to be installed anywhere. The implementation details have not yet been
|
||
|
decided on. The basic idea is to either mount a dedicated packagefs with the
|
||
|
content of such a package or have a special location where one of the three
|
||
|
already mounted packagefs instances (likely the "/boot/home/config" one) shows
|
||
|
that content. With a bit of Tracker (or even libbe) integration that will allow
|
||
|
the mounted directory to be opened or the application to be started when such a
|
||
|
package file has been double-clicked.
|
||
|
|
||
|
Installation Location Order and Consistency
|
||
|
-------------------------------------------
|
||
|
Having two separate installation locations for software requires some
|
||
|
considerations regarding their consistency and interactions. There's a
|
||
|
well-defined order of the installation locations: "/boot/home/config",
|
||
|
"/boot/system". This has already been the order in which on BeOS commands,
|
||
|
libraries, and add-ons where searched (according to the environmental variables
|
||
|
``PATH``, ``LIBRARY_PATH``, and ``ADDON_PATH``). That e.g. allows a user to
|
||
|
install a new/different version of a program in "/boot/home/config" and have it
|
||
|
override the version in "/boot/system".
|
||
|
|
||
|
This order also needs to be the order in which package dependencies are
|
||
|
directed. While it shall be possible to have a library in "/boot/home/config"
|
||
|
override one in "/boot/system" and have programs installed in the latter
|
||
|
location use the overriding library, packages in an installation location must
|
||
|
not have dependencies that can only be resolved to packages installed in a
|
||
|
location that is prior according to the order. E.g. a program installed in
|
||
|
"/boot/system" must not depend on a library that is only installed in
|
||
|
"/boot/home/config". When going multi-user that would mean the program would
|
||
|
work for one user, but not for another one who hasn't installed the library.
|
||
|
Consequently "/boot/system" is fully self-contained. All dependencies must be
|
||
|
resolved within it. A safe-mode boot should be possible with only the
|
||
|
"/boot/system" packagefs being mounted. As a consequence these constraints have
|
||
|
to be respected when software is installed or uninstalled.
|
||
|
|
||
|
Another challenge that comes with having two installation locations is that some
|
||
|
packages have compiled-in absolute paths to their own files (e.g. data files) or
|
||
|
to their dependencies. The former could be solved by building two different
|
||
|
versions of a package, but that wouldn't work with the latter and would be
|
||
|
tedious anyway. The solution are dynamically generated symbolic links in a fixed
|
||
|
location, "/boot/system/package-links" (symlinked to "/packages"), that for each
|
||
|
installed package and its dependencies refer to the respective installation
|
||
|
location.
|
||
|
|
||
|
For each installed package a subdirectory named like the package (package name
|
||
|
plus version) will be generated automatically. That subdirectory contains a
|
||
|
symlink ".self" which refers to the installation location of the package itself
|
||
|
as well as a symlink for each of its dependencies pointing to their installation
|
||
|
locations. Furthermore there's a symlink ".settings" which points to the
|
||
|
installation location's directory for global settings. E.g. for an OpenSSH
|
||
|
package installed in "/boot/home/config" and OpenSSL installed in "/boot/system"
|
||
|
the directory could look like this::
|
||
|
|
||
|
/boot/system/package-links/openssh-5.8p2-1/
|
||
|
.self -> ../../../home/config
|
||
|
.settings -> ../../../home/config/settings/global
|
||
|
haiku -> ../..
|
||
|
lib:libssl -> ../..
|
||
|
|
||
|
Installing a different, compatible version of OpenSSL in "/boot/home/config"
|
||
|
would automatically change the respective dependency symlink. Once supporting
|
||
|
multi-user fully, the symlinks targets would also depend on the user ID of the
|
||
|
process that checks them, so software installed only for the user is handled
|
||
|
correctly.
|
||
|
|
||
|
While it depends on the location the package has been installed in where the
|
||
|
paths refer to, the absolute paths of the package links themselves remain
|
||
|
stable. So they can be compiled in, when a package is built, and will work
|
||
|
regardless of where the package is installed.
|
||
|
|
||
|
Another problem the package links can solve are incompatible versions of the
|
||
|
same package being installed in different locations. E.g. when a program and
|
||
|
another program it depends on are installed in "/boot/system", installing an
|
||
|
incompatible version of the latter in "/boot/home/config" will not break the
|
||
|
former, since the dependency link will continue to point to the compatible
|
||
|
version. With a bit of help from the runtime loader the same would work for
|
||
|
libraries. In practice that's less of a problem, though, since libraries usually
|
||
|
have a naming scheme and matching shared object names that already prevent
|
||
|
mismatches.
|
||
|
|
||
|
Software Repositories
|
||
|
=====================
|
||
|
A software repository is a collection of packages, usually accessible via the
|
||
|
internet. Haiku's package management solution allows to refer to any number of
|
||
|
software repositories from which packages can be downloaded and installed. The
|
||
|
structure of the respository is very simple. It's just a set of files which can
|
||
|
be downloaded via a common protocol (HTTP or FTP). One file is the repository
|
||
|
index file in `HPKR format`_. It lists all packages that are available in the
|
||
|
repository together with their descriptions and dependency information. It is
|
||
|
downloaded and cached, allowing user interfaces to show the information and the
|
||
|
dependency solver to do the computation locally. The other files are the
|
||
|
individual package files.
|
||
|
|
||
|
.. _HPKR format: FileFormat.rst#haiku-package-repository-format
|
||
|
|
||
|
Standard Repositories
|
||
|
---------------------
|
||
|
There are two standard repositories for Haiku:
|
||
|
|
||
|
- the Haiku repository, which only contains the small set of packages that is
|
||
|
built by Haiku's build system (haiku.hpkg, haiku_devel.hpkg, etc.) and
|
||
|
- the HaikuPorts repository, which contains the packages maintained by
|
||
|
HaikuPorts.
|
||
|
|
||
|
For the different builds and releases there are different instances of those two
|
||
|
repositories:
|
||
|
|
||
|
- There are snapshot repository instances for any repository version that was
|
||
|
ever available (to save space old versions may be removed/thinned out). Those
|
||
|
repositories will never be updated. Their main purpose is to be able to
|
||
|
retrospectively get a certain Haiku version for testing and comparisons.
|
||
|
- For each official major release there will be an instance of the two
|
||
|
repositories. For small updates the repositories will simply be updated. An
|
||
|
official Haiku release is pre-configured with the corresponding repositories,
|
||
|
so that the user can conveniently keep their Haiku up-to-date. The update to
|
||
|
the next major release has to be requested explicitly.
|
||
|
- Similar to the nightly images there are repository instances that are
|
||
|
continuously updated to the latest head of development. Those are suitable
|
||
|
mainly for testers and developers.
|
||
|
- For each state of the HaikuPorts repository a Haiku development revision
|
||
|
refers to a snapshot version of the repository is created. This allows to
|
||
|
check out and build older Haiku revisions with their corresponding HaikuPorts
|
||
|
packages.
|
||
|
|
||
|
The repositories are maintained via files in the Haiku git repository. For each
|
||
|
architecture and each repository the Haiku git repository contains a file
|
||
|
listing the packages for that repository. For the HaikuPorts repositories the
|
||
|
packages are listed with the respective version. For the Haiku repositories the
|
||
|
version is implied.
|
||
|
|
||
|
Whenever a developer wants to update or add a HaikuPorts package, the new
|
||
|
package file has to be uploaded to their git.haiku-os.org account and the
|
||
|
package list file for the repository has to be adjusted accordingly.
|
||
|
``jam upload-packages <packages-list>`` can be used in order to upload the
|
||
|
package(s) or the packages could just be ``scp``'ed into the 'hpkg-upload'
|
||
|
folder in the developer home directory on git.haiku-os.org. When that is done,
|
||
|
the change can be pushed to git.haiku-os.org, where a push hook will analyze the
|
||
|
change, move the new package file(s) from the developer's account to the
|
||
|
repository directory, and build a new repository snapshot. If a package file is
|
||
|
missing or broken, the push will be rejected with a message notifying the
|
||
|
developer about the problem.
|
||
|
|
||
|
The creation and update of repositories for official releases has to be
|
||
|
triggered explicitly on the server. In either case the Haiku repository is built
|
||
|
by the build service.
|
||
|
|
||
|
The Package Kit
|
||
|
===============
|
||
|
The package kit provides an API for all package management related tasks,
|
||
|
including:
|
||
|
|
||
|
- Reading and writing HPKG and HPKR files.
|
||
|
- Adding, removing, and querying software repositories.
|
||
|
- Solving package dependencies.
|
||
|
- Adding, removing, and updating packages.
|
||
|
|
||
|
Localization
|
||
|
============
|
||
|
Package files and repository index files contain text strings -- e.g. the
|
||
|
package short and long description -- that are presented to the user. Therefore
|
||
|
translations for these strings must be available. Since it is impractical to
|
||
|
include the translations in the package and repository index files, they must be
|
||
|
provided in separate files. How exactly has not been decided on yet.
|