Autopackage root names & versioning

Definitions
-----------

Package:	An Autopackage .package file.
Software:	The software itself.


What is a root name?
--------------------

A root name is an identifier for a particular piece of software.
Software should have a root name for each of it's packages.


What a root name looks like
---------------------------

A root name is made of four parts:
1. The domain name. This is comparable to XML or C++ namespaces.
2. The package name.
3. The software's full version number.
4. The package number. This indicates changes in the *package*, not the
   software. For example, there's a bug in the specfile, and you fixed it, but
   the software did not change, then you increase this number. This is like
   RPM's Release number.

The domain name and package name are seperated by a slash.
The package name, software version number and package number are seperated by
a colon. The package number is optional, if it isn't present, a value of zero
is assumed.

The package name itself can contain one or more slashes.

For example, root names for GTK+ 2.0.1 can look like:
@gtk.org/gtk:2.0.1            <=  the main GTK+ package
@gtk.org/gtk/devel:2.0.1      <=  development headers for GTK+ 2.0.1

or if the package was improved:

@gtk.org/gtk:2.0.1:1



Versioning
----------
The reason why root names contain a version number is to make it possible to
install two different version of the same software in parallel.

However, version numbers are also used for dependancy handling. Let's say
Foobar is a GTK+ 2.0 app. Now we have a few problems:
1. We don't want to check for just "@gtk.org/gtk:2.0.1", we just want to check
   for *any* 2.0.x release.
2. At the time Foobar is written, GTK+ 2.2 didn't exist. GTK+ 2.2 is now
   released, and turns out to be binary compatible with 2.0.
   How can we know this?

So, we introduce a new kind of version number: interface numbers.
Interface numbers are not related to the software's version number:
they change when the *interface* has changed. Interface can mean several things,
depending on your software. For shared libraries, it usually indicates binary
compatibility, but it can also include things like file formats and command line
arguments.

Interface numbers are used to check compatibility.

Interface numbers are made of two numbers, each seperated by a dot:
1. Major: Every time the interface has changed (binary compatibility changed),
   this number is increased by 1 and the revision number is reset to 0.
2. Revision: This number is increased by 1 if something has been added to the
   interface, like a new function in a library. Apps that depend on previous
   revision numbers will still work on this revision, but apps that depend on
   this revision will not work on previous revisions.

Interface numbers *only* contain numbers, not letters or anything weird!

Examples:
Software            Interface number
--------            ----------------
GTK+ 1.2.0          1.0
GTK+ 1.2.1          1.0
GTK+ 2.0.0          2.0
GTK+ 2.0.1          2.0
GTK+ 2.2.0          2.2
GTK+ 2.2.1          2.2

GTK+ 1.2.1, 2.0.1 and 2.2.1 are bugfix releases. So their major and revision
numbers don't change.

GTK+ 2.0 is binary incompatible with GTK+ 1.2, so the major is increased by 1.

GTK+ 2.2 is binary compatible with GTK+ 2.0, but new functions has been added.
That's why the major number doesn't change, and the revision number is
increased by 1.

GTK is simple, because its software version numbers happen to reflect the interfaces.
Other software is less simple, for instance:

Release name        Major interface number
------------        ----------------------
libpng 1.0.x        1
libpng 1.2.5        2
libpng 1.2.6        3

The interface number is not part of the root name, and is stored separately.
When software contains multiple interfaces, such as libraries that use symbol
versions, the major number stays the same and the revision is incremented.



How to integrate this with skeletons
--------------------------------------------------

Skeletons represent software, but is not the software (or the package) itself.
Skeletons are used to:
1. Check for the existance of software.
2. Install software if it's not found.

Skeletons' root names are the same as the specfiles', but without the software
version number and the package number. Example:
@gtk.org/gtk

Skeletons have a Test section, which should set SOFTWARE_VERSION and must set INTERFACE_VERSION

SOFTWARE_VERSIONS: This is a space separated list of versions of the software, if detectable.
INTERFACE_VERSIONS: this is a space separated list of the interfaces of the software

The reason there can be more than one is so skeletons can detect parallel installs.

If no versions were detected, these variables should not be changed from their initial values.

How to interface with require()
-------------------------------
Usage: require <ROOTNAME> <MAJOR>[.REVISION]

Require will check for the skeleton that has the root name ROOTNAME. As
described earlier, skeletons' root names do NOT contain a software version
number or a package version number. So:

require "@gtk.org/gtk" 1             # valid
require "@gtk.org/gtk" 1.2	     # valid
require "@gtk.org/gtk:2.0.0:1" 1     # invalid

MAJOR and REVISION are of course the required major and revision numbers.
If REVISION is not specified, then it is assumed to be zero.

However, sometimes you want to have a specific version of a library (for
whatever reason). Let's say you want GTK+ 1.2.5 specifically.

For the sake of keeping require() simple, we introduce a new function:

requireExactVersion <ROOTNAME> <VERSION>

VERSION is the software's version number. It may contain letters to a
certain degree, the exact capabilities of autopackages version number
comparison routines will be documented later.

And sometimes you need a version that's higher than a specific number.
Because of a bug in GTK+ 1.2, AbiWord will only work on GTK+ 1.2.5 or higher,
even though the interface hasn't changed. So we introduce another function:

requireAtLeastVersion <ROOTNAME> <VERSION> <MAJOR>[.MINOR]

This function is like require(), but also checks whether the software version
of the software installed on the computer equals VERSION or is higher than
VERSION.

It is the job of the skeleton file to accurately report what the version number
of the installed software is, the test code should set the $VERSION variable to
the detected value, or empty if the version could not be located.


More on skeletons
-----------------
So skeletons contain code to check whether certain software is present on the
system. But it is impractical if one single skeleton must be able to detect
*all* versions of the software it represents.

Sometimes, you will need to change the skeleton file. Because of that,
skeleton files have a version number as well. This is a single integer value
that increments in steps of one. The number has no related to any other
version number, it is purely there to allow you to distinguish between
different sets of metadata for the software.

Example:
Software            Interface number     Skeleton filename
--------            ----------------     -----------------
GTK+ 1.2.0          0.0                  skeleton.0
GTK+ 2.0.0          1.0                  skeleton.1 (gtk has a new soname)   
GTK+ 2.2.0          1.1                  skeleton.2 (oops, bug in skeleton)

Note: skeleton.2 must be able to detect GTK+ 2.2.0 and 1.2.0 too!
A skeleton must be able to detect all known versions.


Automatic dependancy retrieval
------------------------------

The retrieve() function should be like this:
retrieve <ROOTNAME> <MAJOR>[.REVISION]

ROOTNAME may or may not contain a software version number.
If it does:
	MAJOR and REVISION are ignored.
	Search the harddisk and network for a packages that matches the given
	version number. Out of those packages, select the one with the highest
	package number.
If it doesn't:
	MAJOR will be a required parameter and REVISION an optional one.
	1. Search the harddisk and network for packages that match MAJOR.
	   If REVISION is specified:
		1.1. Out of those packages, select the ones with a revision
		     version number that is equal or higher than REVISION.
		     Then select the ones with the highest REVISION number.
	2. Select the ones with the highest software number.
	3. Select the ones with the highest package number.


Example:
There are these files:
Filename                    Specfile root name       Interface number
--------                    ------------------       ----------------
gtk-1.2.2.package           @gtk.org/gtk:1.2.2       0.0
gtk-1.2.5.package           @gtk.org/gtk:1.2.5       0.0
gtk-1.2.6.package           @gtk.org/gtk:1.2.6       0.0
gtk-1.2.6-fixed.package     @gtk.org/gtk:1.2.6:1     0.0
gtk-2.0.0.package           @gtk.org/gtk:2.0.0       1.0
gtk-2.2.0.package           @gtk.org/gtk:2.2.0       1.1
gtk-2.2.1.package           @gtk.org/gtk:2.2.1       1.1

Notice gtk-1.2.6-fixed.package. The packager made a mistake in the specfile
so he released another package of the same version.

retrieve "@gtk.org/gtk:1.2.5"
---> Install gtk-1.2.5.package

retrieve "@gtk.org/gtk" 0
1. Selected by major number:
   gtk-1.2.2.package
   gtk-1.2.5.package
   gtk-1.2.6.package
   gtk-1.2.6-fixed.package
2. Selected by revision number:
   gtk-1.2.6.package
   gtk-1.2.6-fixed.package
3. Install due to package number: gtk-1.2.6-fixed.package

retrieve "@gtk.org/gtk" 1.0
1. Selected by major number:
   gtk-2.0.0.package
   gtk-2.2.0.package
   gtk-2.2.1.package
1.1: Selected by revision number:
     gtk-2.2.0.package
     gtk-2.2.1.package
2. Install by software version number comparison: gtk-2.2.1.package
3. There was only 1 package left in step 2 so we never reach this step.



Summary
-------
Are you confused with all the different version numbers? We have:

Software version:	The version number of the software, as defined by the
			maintainer. Tends to be put on websites etc

Package version:	The number of the package. Similar to RPM's Release
			number. Used only in the specfile. Used for "bugfix
			releases" of a package itself.

Interface version:	Version number used to determine the interface
			compatibility of the software.
			+ Major
			+ Revision
