Zif

[image of a zero-insertion-force socket]

Zif is a package manager for Fedora written in C that's designed to replace yum.

When designing PackageKit, I coded a framework for a distro-specific backend to be coupled with a distro-agnostic service that listened for user requests to create a package manager daemon.

In doing so, I've become very familiar with about a dozen (!) package systems, with all their specific nuances and peculiarities. It also became bewildering obvious to me that most of these package systems were not a good fit, as much of the package system functionality was not used and usually what PackageKit was using had to hide some pretty hideous hacks.

For instance, PackageKit only exercises less than 5% of the yum API. Another example, is that a good chunk of the yum backend is just making sure that we send and receive text as Unicode.

This layering can be described below:

packagekitd PackageKit daemon (language: C) 10k lines
|
pk-plugin-yum PackageKit backend (language: C) 1k lines
|
PackageKit-python PackageKit python interface code (language: python) 2.5k lines
|
yumBackend PackageKit backend code (language: python) 4k lines
|
yum Core yum (python) 20k lines
|
rpm-python The rpm python bindings (language: python) 2k lines
|
librpm The RPM package manager (language: C) 40k lines

What we're actually asking the package manager to do just isn't that complicated, and the layers, on layers, on layers just introduces bugs and demolishes our performance.

It seems obvious, that instead of looking at the bottom-up approach, where you have an existing "fat" solution that is shoehorned into working with PackageKit, you design a top-down solution. This means that you essentially design a library for the sole use of PackageKit, and only code the parts that PackageKit will use. The fact that we don't want to support plugins means we can leave out a huge chunk of code from this new library.

As we're only designing the library to be used by one thing, we can optimize things in the right places. We can do all operations with the assumption that the user wants an accurate time remaining, and doesn't want to be bothered with the low level details. If we're designing it for situations that only PackageKit cares about, we can do a lot of things a lot nicer than a generic solution. This would include working with offline copies of metadata whenever possible, and erring on returning results quickly rather than checking if the metadata is out of date. We'll aim to do as much as we can without bothering the user.

So, if we're writing a shim library, it makes sense to be in the same language as PackageKit itself (C), to avoid all the spawning and watching of processes. This means all the backend actions can be run in threads, which are managed by the daemon. It also makes sense to make it distribution specific. Smart does a wonderful job of trying to join all the distros together, but because of it's genericness means we loose all the top-down way of thinking.

So, in the Christmas holidays of 2008, and since in a few evenings of spare time since then, I wrote Zif. Zif is designed to work on Fedora, and only Fedora. It's not really designed to be run by the end user, it's only designed to be run as part of a program using libzif.

packagekitd PackageKit daemon (language: C) 10k lines
|
pk-plugin-zif PackageKit backend (language: C) 5k lines
|
libzif libzif (language: C) 34k lines
|
librpm The RPM package manager (language: C) 40k lines

PackageKit has a zif backend, and it seems to work basically as well as the native yum code ever did. Zif is designed to only do what the user wants, and not do lots of cleverness in the background. To solve the difficult desktop problems we need answers to questions like what package owns /usr/bin/totem in milliseconds, not tens of seconds.

Zif features:

Zif is compatible with rpm, yum and the Red Hat and Fedora infrastructure, specifically:

Documentation is available here.

Releases are available here.

The source is managed using Git. You can browse the repository using gitweb or clone it using the following command:

$ git clone git://github.com/hughsie/zif.git