
### DRAFT ### not sure if correct and probably not matching the implementation
# pietro.abate@pps.jussieu.fr

Rpm comparison function.

Rpm versions are tuples divided in epoch, version, release.
These a compared sequentially as with the following algorithm:

let rpmcmp (e1,v1,r1) (e2,v2,r2) =
  if epochcmp e1 e2  = 0 then
     if rpmvercmp v1 v2 = 0 then
        rpmvercmp r1 r2
     else rpmvercmp v1 v2
  else epochcmp e1 e2

let epochcmp = function
   |"","" | "", "0" | "0", "" -> 0
   |"", i > 1 -> -1
   |i > 1 , "" -> 1
   |i, j -> cmp i j

where cmp is the canonical comparison function.

Version expansion.
package: a
version: 1.3
epoch: 1
release: ex2010

will be associated with a canonical version string of the form 1:1.3-ex2010
if the epoch is not mentioned is assumed to be 0, but it won't be added to the
version string.

Cudf version mapping : to each rpm version (mentioned anywhere in the rpm source
as conflict, depends, provide or as real package version) is associated a integer
ordered according to the comparison function. Cudf versions are numbered from 1.
In order to map a version of a non existent rpm package, rpmcudf versions are 
numbered starting from 2 and 1 is left to represent a version of a non existent 
package reference.

For example :
package: a
version: 1.3.3
release: ex2010
provides: a = 1.3.3-ex2010

package: a
version: 1.2
release: ex2010

we associate the following integers 
1.2 -> 2
1.3.3 -> 3

therefore the package will be converted in cudf as follows:
package: a
version: 3
provides: a = 3

package: a
version: 2

However if the package is given as
package: a
version: 1.3.3
release: ex2010
provides: a = 1.3.3

This will be expanded as 
package: a
version: 3
# in cudf this provide is not needed, but added for clarity
provides: a = 3 

The following translation is based on the assumption that dependencies
expressed as incomplete epoch/version/release tuples (that is versions that do
not have a release component) are translated by matching all possible
releases. In the previous example the provide dependency on a = 1.3.3 is
effectively translated as a dependency on 1.3.3-* that is hence expanded in a
= 3

Provides/conflict problem :

consider the following packages:

package: a
version: 1.27
release: ex2010
provides: a = 1.27

package: b
version: 1.2
conflict: a < 1.27-ex2010

if we were going to give a different (incorrect) translation as :
package: a
version: 3
provides: a = 2, a = 3

package: b
version: 2
conflict: a < 3

the (wrong) provide a = 2 will result in an unwanted conflict.

The correct translation is to expand provides to match versions 
containing releases. So in this case (as above) the constraint 
a = 1.27 will be expanded as a = 1.27-* 

package: a
version: 3
provides: a = 3

package: b
version: 2
conflict: a < 3

File conflicts :
cudf documents can be generated from multiple sources.

In the rpm model dependencies can also be expressed a file dependency, that
is in the form of a file system path (ex: /bin/sh) . File dependencies are
automatically added to synthesis files. A package provides a file that is in
its file list if there exists a package in the archive that depends on it.
Since the synthesis file does not contain the full file list, the cudf
translation must relay only of the information contained therein.

When considering hdlists, the rpm / cudf converter can also relay on the file
list associated to each package and generate additional conflicts by analysing
the file list.

package: a
version: 1.27
release: ex2009
provides: a = 1.27

package: a
version: 1.27
release: ex2010
provides: a = 1.27

package: b
version: 1.2
conflict: a < 1.27

package: c
version: 1.2
require: a = 1.27
--------------
package: a
version: 2
provides: a = 2

package: a
version: 3
provides: a = 3

package: b
version: 2
conflict: a < 3

package: c
version: 2
depends: a = 2 | a = 3
