From Fedora Project Wiki
(Add note at the beginning.)
(Incorporate simplifications from the previous tilde draft.)
Line 4: Line 4:
{{ admon/note |This is a a draft which allows the use of tilde versioning for prereleases but prohibits mixing tilde and snapshots.}}
{{ admon/note |This is a a draft which allows the use of tilde versioning for prereleases but prohibits mixing tilde and snapshots.}}


In Fedora, the package versioning scheme (which encompasses both the <code>Version:</code> and <code>Release:</code> tags, as well as <code>Epoch:</code>) balances two separate goals:


* To provide information about the version of the packaged software to users.  When a package version does not correspond directly to the upstream version of the software, some useful information is conveyed such as the date a snapshot was taken or whether a pre- or post-release version has been packaged.
Fedora's package versioning scheme encompasses both the <code>Version:</code> and <code>Release:</code> tags, as well as <code>Epoch:</code>).  The overriding goal is to provide sequence of packages which are treated as updates by RPM's version comparison algorithm while accommodating varied and often inconsistent upstream versioning schemes.
 
* To ensure proper ordering between updates to a package within a Fedora release, as well as between Fedora releases.  Within a release, Fedora does not allow package versions to go backwards, so the versioning scheme must produce successive versions which increase monotonically, even if the upstream versions don't have this property when compared using RPM's version comparison function.  The versioning scheme also ensures that for a package built at the same time for two different Fedora releases, the version in the newer release sorts higher than the version in the older release.
 
Fedora's versioning scheme must adapt to whatever scheme any upstream developer may choose for versioning their software, while at the same time preserving the two goals above.
 
The <code>Epoch:</code> tag, which provides the most significant input to RPM's version comparison function, SHOULD ONLY be used or incremented when necessary to avoid ordering issues.  If present, it MUST contain a positive integer.  <code>Epoch:</code> MUST NOT ever be decreased in any way.
 
Limited use of the tilde (<code>~</code>) notation (which alters the way RPM does version comparisons) is allowed. See [[#Versioning prereleases with tilde|below]].


== Some definitions ==
== Some definitions ==
Line 38: Line 29:


Examples of many possible versioning scenarios are available from [[Package Versioning Examples]].
Examples of many possible versioning scenarios are available from [[Package Versioning Examples]].
== Epoch: tag ==
The <code>Epoch:</code> tag provides the most significant input to RPM's version comparison function.  If present, it MUST consist of a positive integer.  It SHOULD ONLY be introduced or incremented when necessary to avoid ordering issues.  The <code>Epoch:</code> tag, once introduced to a package, MUST NOT ever remove or be decreased in any way.


== Simple versioning ==
== Simple versioning ==

Revision as of 17:50, 19 November 2018

This is a a draft which allows the use of tilde versioning for prereleases but prohibits mixing tilde and snapshots.


Fedora's package versioning scheme encompasses both the Version: and Release: tags, as well as Epoch:). The overriding goal is to provide sequence of packages which are treated as updates by RPM's version comparison algorithm while accommodating varied and often inconsistent upstream versioning schemes.

Some definitions

Note that upstreams may each have their own terminology and it is in general impossible to define these terms with complete generality. For some upstreams, every commit is itself considered a version. Many upstreams never make releases, instead just letting users take whatever is in the code repository at any given time.

release version
A version of the software which upstream has decided to release. The act of releasing the software can be as simple as adding a git tag. This includes so-called "point releases" or "patchlevels" which some upstreams make, since those are actually assigned versions and released.
snapshot
An archive taken from upstream's source code control system which is not associated with any release version.
prerelease version
Before a release happens, many upstreams will decide which version that will release will have, and then produce "alphas", "betas", "release candidates", or the like which carry that new version but indicate that the release of that version has not yet been made. These we call prerelease versions. Any snapshots made while upstream is preparing for their release are also considered prerelease versions.
postrelease version
Any version which happens after a particular release is technically "post-release", but before upstream begins making prereleases for the next version, any snapshot is considered a postrelease version.
non-sorting version sequence
A sequence of version strings which is not ordered in the same way that RPM's version comparison function would order it. RPM has a somewhat complicated version comparison function which it will use to determine if a package is "newer". If upstream's idea of what constitutes a "newer" version differs from RPM's implementation then simply using upstream's versions directly will result in updates which don't actually update any packages.

Examples

Examples of many possible versioning scenarios are available from Package Versioning Examples.

Epoch: tag

The Epoch: tag provides the most significant input to RPM's version comparison function. If present, it MUST consist of a positive integer. It SHOULD ONLY be introduced or incremented when necessary to avoid ordering issues. The Epoch: tag, once introduced to a package, MUST NOT ever remove or be decreased in any way.

Simple versioning

Most upstream versioning schemes are "simple"; they generate versions like "1.2.03.007p1". They consists of one or more version components, separated by periods. Each component is a whole number, potentially with leading zeroes. The rightmost component can also include one or more ASCII letters, upper or lower case. The value of a component must *never* be reduced (to a value which sorts lower) without a component somewhere to the left increasing. Note that the version sequence ("1.4a", "1.4b", "1.4") does not meet this criterion, as "4" sorts lower than "4b". The sequence ("1.4", "1.4a", "1.4b") is, however, simple.

This is a very common versioning scheme, and the vast majority of software projects use something which works like this.

To package release versions of software using this versioning scheme:

  • Use the upstream verbatim in the Version: tag. Don't trim leading zeroes.
  • Use a Release: tag starting with 1 (never 0). Append the Dist tag. Increment the release (by 1) for each update you make. Reset to 1 whenever you change Version:.

More complex versioning

There are several ways in which the simple scheme might not work in a particular situation:

  • Upstream has never chosen a version; only snapshots are available for packaging.
  • Upstream simply doesn't use a version scheme which orders properly under RPM's version comparison operation.
  • You wish to package a prerelease version (snapshot or otherwise).
  • You wish to package a postrelease snapshot.
  • Upstream was thought to be following one scheme but then changed in a way that can't be sorted.
  • You need to apply a small fix to a release branch of Fedora without updating the newer branches.
  • More than one of the above may apply (lucky you). Follow all of the relevant recommendations below together.

The methods for dealing with most of these issues involves potentially removing some information from the Version: tag while imposing additional structure onto the Release: tag. There are potentially three fields which comprise the structured Release: tag:

  • package release number (<pkgrel>)
  • extra version information (<extraver>)
  • snapshot information (<snapinfo>)
  • minor release bump (<minorbump>)

The package release number MUST always be present while the others may or may not be depending on the situation.

Those items which are present are combined (with periods to separate them) to construct the final Release: tag. In the usual notation where square brackets indicate that an item is optional:

  • <pkgrel>[.<extraver>][.<snapinfo>]%{?dist}[.<minorbump>]

The actual values to be used for those three fields are situational and are referenced in the sections below. Note that your particular situation might not result in the use of <extraver> or <snapinfo>, and in most situations <minorbump> won't be used at all. Simply do not include those which you don't have.

Upstream has never chosen a version

When upstream has never chosen a version, you MUST use Version: 0. "0" sorts lower than any other possible value that upstream might choose. And if upstream does choose to release "version 0" then you can immediately move to using Release: 1%{?dist} with no ordering issues.

Upstream uses invalid characters in the version

It's possible that upstream uses characters besides ASCII letters (upper and lower case), digits and periods in its version. They must be removed and potentially replaced with valid characters. Any such alterations MUST be documented in the specfile. It is not possible to cover all potential situations here, so it is left to the packager to alter the upstream versioning scheme consistently.

After altering the version to be free of invalid characters, see #Unsortable versions below if the modifications, when applied to successive releases from upstream, will not order properly.

Unsortable versions

When upstream uses a versioning scheme that does not sort properly, first see if there is any portion which can be removed from the right side of the version string such that the remainder is sortable. This is often possible if upstream uses a sequence like ("1.2pre1", "1.2pre1", "1.2final"). If so, use the removed portion as <extraver> above, and the remainder as the package version. If this splitting leaves a leading or trailing period in either value, remove it.

If this is not possible, use Version: 0 and move the _entire_ version string into <extraver>.

Snapshots

All snapshots MUST contain a snapshot information field (<snapinfo>) in the Release: tag. That field must at minimum consist of the date in eight-digit "YYYYMMDD" format. The packager MAY include up to 17 characters of additional information after the date. The following formats are suggested:

  • YYYYMMDD.<revision>
  • YYYYMMDD<scm><revision>

Where <scm> is a short string identifying the source code control system upstream uses (e.g. "git", "svn", "hg") or the string "snap". <revision> is either a short git commit hash, a subversion revision number, or something else useful in identifying the precise revision in upstream's source code control system. Obviously if CVS is used, no such revision information exists, so it would be omitted, but otherwise it SHOULD be included.

Prerelease versions

In the Version: tag, use the version that upstream has determined the next release will be. For the <pkgrel> field of the Release: tag, use a number of the form "0.N" where N is an integer beginning with 1 and increasing for each revision of the package. Prerelease versions MUST use a Release: tag strictly less than 1, as this is the sole indicator that a prerelease has been packaged.

Release and post-release versions

For the <pkgrel> field of the Release: tag, use an integer beginning with 1 and increasing for each revision of the package. Release and post-release versions MUST use a Release: tag greater than or equal to 1.

Upstream makes unsortable changes

It is possible that upstream simply adopts a different versioning scheme, fails to follow an expected pattern, or even simply resets their version to some lower value. If none of the above operations can help with giving a version which sorts properly, or give you a version which simply sorts lower than the packages already in Fedora, then you have little recourse but to increment the Epoch: tag, or to begin using it by adding Epoch: 1. At the same time, try to work with upstream to hopefully minimize the need to involve Epoch: in the future.

You need to change an old branch without rebuilding the others

Sometimes, you may find yourself in a situation where an older branch needs a fix, but the newer branches are fine. For example, if pkg = 1.0-1%{?dist} in F40 and F41, and only F40 needs a fix. Normally, you would need to bump the release in each of the branches to ensure that F40 < F41, but that is a waste of time and energy for the newer branches which do not need to be touched.

In this case, you MAY set <minorbump> to an in integer beginning with '1' and increasing by one for each minor bump you need to do. Remove <minorbump> once you are able to increase the package release normally without introducing ordering issues.

Versioning prereleases with tilde

If you wish to package a prerelease version and are confident that you will not need to package only tagged releases and not any snapshots until the next release, you MAY make use of RPM's tilde ('~') notation. To do this, split upstream's prerelease version into two components:

  • the version that the next actual release will take (<nextrel>
  • the "prerelease" portion (<prerel>).

Then you may construct Version: as follows: Version: <nextrel>~<prerel>. Use Release: <pkgrel>%{?dist}[.<minorbump>] with <phgrel> and <minorbump> as detailed above.

Note that you MUST NOT mix the use of tilde with the previously detailed scheme for versioning prerelease snapshots. Once a snapshot has been packaged according to these guidelines, any Version: which uses tilde will be seen by RPM as older and this will not serve as an upgrade to the existing package.

Rawhide is allowed to lag temporarily

A package MAY temporarily have a lower EVR in Rawhide when compared to a release branch of Fedora ONLY in the case where the package fails to build in Rawhide. This permits important updates to be pushed to existing Fedora releases regardless of the current state of Rawhide.