From Fedora Project Wiki
(Move the examples elsewhere.)
Line 83: Line 83:




=== Old section below ===
=== Old bits below which may still need to find a home ===
 
If the version is non-numeric (contains tags that are not numbers), you may need to include the additional non-numeric characters in the release field.
 
There are four cases where the version contains non-numeric characters:
 
* Pre-release packages: Packages released as "pre-release" versions, prior to a "final" version. Example tags include "alpha", "beta", "rc", "cvs". Unfortunately, we cannot simply put these letters into the version tag, so we use the Release field for this. Details can be found here: [[#NonNumericRelease|  Non-Numeric Version in Release]]
 
* Post-release packages: Packages released after a "final" version. These packages contain the same numeric version as the "final" version, but have an additional non-numeric identifier. Details can be found here: [[#NonNumericRelease|  Non-Numeric Version in Release]]
 
* Snapshot packages: Packages built from cvs or subversion snapshots. These packages could be either "pre" or "post" release packages. Details can be found here: [[#NonNumericRelease|  Non-Numeric Version in Release]]


{{admon/note|Non-use of tilde "~"|rpm-4.10 and above support the Debian-style tilde character which causes a piece of the version to sort before anything else.  At the moment, using this is not permitted for these reasons:
{{admon/note|Non-use of tilde "~"|rpm-4.10 and above support the Debian-style tilde character which causes a piece of the version to sort before anything else.  At the moment, using this is not permitted for these reasons:

Revision as of 01:31, 10 November 2016

In Fedora, the package versioning scheme (which encompasses both the Version: and Release: tags, as well as Epoch:) 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.
  • 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.

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.

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 a letter. 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.
  • 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.
  • 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 pieces of information which comprise the structured Release: tag:

  • package release number
  • extra version information (basically, the non-sorting portions of the package version)
  • snapshot information

The former is always present while the others may or may not be depending on the situation. Those that are present are joined together, with periods as separators, to make the final Release: tag.

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

Unsortable versions

When upstream uses a versioning scheme that does not sort properly (generally)

Snapshots

All snapshots MUST contain a snapshot information field 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.)

Prerelease versions

In the Version: tag, use the version that upstream has determined the next release will be. If that version itself is not "simple" as defined above, then it will need to be simplified and an extra version information field will needed to be added to Release: as described below.



Old bits below which may still need to find a home

Note.png
Non-use of tilde "~"
rpm-4.10 and above support the Debian-style tilde character which causes a piece of the version to sort before anything else. At the moment, using this is not permitted for these reasons:
  • it is not necessary when the following release tag guidelines are followed properly.
  • it introduces another special character to achieve something which can be handled in other ways.

Release Tag

The release tag of packages which are not pre- or post-release or snapshots must consist of a positive integer release number and a %{?dist} tag: 42%{?dist}. When a minor change (spec file changed, patch added/removed) occurs, or a package is rebuilt to use newer headers or libraries, the release number is incremented. If a major change (new version of the software being packaged) occurs, the version number is changed to reflect the new software version, and the release number is reset to 1. It is important to follow these guidelines because automated tools will occasionally be used to increment releases and rebuild packages.

Non-Numeric Version in Release

There are three cases in which non-numeric versions occur in the Release field:

  • Snapshot packages
  • Pre-release packages
  • Post-release packages

Snapshot packages

Snapshot packages contain data about where the snapshot came from as well as ordering information for rpm. The information about the snapshot will be called %{checkout} in this section.

%{checkout} consists of the date that the snapshot is made in YYYYMMDD format, a short (2-5 characters) string identifying the type of revision control system or that this is a snapshot, and optionally, up to 13 characters (ASCII) alphanumeric characters that could be useful in finding the revision in the revision control system.

For instance, if you create a snapshot from a git repository on January 2, 2011 with git hash 9e88d7e9efb1bcd5b41a408037bb7cfd47220a64, %{checkout} string could be any of the following:

20110102snap
20110102git
20110102git9e88d7e

If the snapshot package is considered a "pre-release package", follow the guidelines listed in Pre-Release Packages for snapshot packages, using the %{checkout} that you decide on above. (For instance, in kismet-0-0.3.20040204svn, 20040204svn is the %{checkout})

If the snapshot is a "post-release package", follow the guidelines in the Post-Release Packages section. Where the %{posttag} in that section is the %{checkout} string you decided on above.

Pre-Release packages

Non-numeric versioned "pre-release" packages can be problematic so they must be treated with care. These are cases where the upstream "pre-release" version has letters rather than simple numbers in their version. Often they have tags like alpha, beta, rc, or letters like a and b denoting that it is a version before the "final" number. Unfortunately, we cannot simply put these letters into the version tag, so we'll use the Release field for this.

Release Tag for Pre-Release Packages: 0.%{X}.%{alphatag}%{?dist}

Where %{X} is the release number increment, and %{alphatag} is the string that came from the version. In this case, the period '.' is used as the delimiter between the release number increment, and the non-numeric version string. No other extra characters may appear in the Release field. This is to prevent Release values such as "3jpp_2fc.42-spotwashere%{?dist}".

Post-Release packages

Like pre-release packages, non-numeric versioned "post-release" packages can be problematic and also must be treated with care. These fall under two generic categories:

  • Properly ordered simple versions. These are usually due to quick bugfix releases, such as openssl-0.9.6b or gkrellm-2.1.7a. As new versions come out, the non-numeric tag is properly incremented (e.g. openssl-0.9.6c) or the numeric version is increased and the non-numeric tag is dropped (openssl-0.9.7). In this case, the non-numeric characters are permitted in the Version: field.
  • When upstream uses versions that attempt to have meaning to humans instead of being easy for a computer to order. For example, GA1, CR2, PR3. In this case, the non-numeric string can be put in the Release: field using the following syntax: %{X}.%{posttag}

In this syntax, %{X} is the release number increment, and %{posttag} is the string that came from the version. Here, the period '.' is used as the delimiter between the release number increment and the non-numeric version string. No other extra characters may appear in the Release field.

It is important to be careful with the post-release scheme, to ensure that package ordering is correct. It may be necessary to use Epoch to ensure that the current package is considered newer than the previous package. In such cases, the packager should try to convince upstream to be more reasonable with their post-release versioning.

Also, packagers using the post-release scheme should put a comment in their spec file with a brief description of the upstream conventions for naming/versioning that are being worked around.

The %{?dist} Tag

Use of the %{?dist} tag in the Release field is mandatory. Please refer to the Packaging:DistTag documentation for the details on the appropriate way to do this.

Minor release bumps for old branches

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

In this case, you can add an extra digit (prefixed by a period) to the very end of the release tag in the F38 branch, instead of bumping it the usual way. Example:


Release: 1%{?dist}

Release: 1%{?dist}.1

This will make a foo-1.0-1.fc38.1 package, which is still less than the foo-1.0-1.fc39 package in the F39 branch.

As necessary, the last digit (the minor release bump) can be incremented on a per-branch basis as needed. However, this must never be used in rawhide, because it is always unnecessary there. Simply increment the appropriate portion of Release: in rawhide.


BE CAREFUL WITH THIS! You always want to make sure that packages in branches can be upgraded to packages in more recent branches. Or to put it simply, F38 < FC39 < F40. There is a tool in the rpmdevtools package called rpmdev-vercmp. This tool will prompt you for two sets of Epoch, Version, and Release, then tell you which is considered newer by rpm.

Rawhide is allowed to lag

XXX Needs work. Might not be at the right place in this document.

The one time where we temporarily break the upgrade path is from released Fedora to rawhide. It is allowable to temporarily have a higher EVR in a released Fedora vs rawhide in cases where we need to get a fix out to users of the Fedora releases quickly (for instance, for a security issue) but the fixed package does not currently build in rawhide (for instance, because of a change in a dependent library that requires porting effort). The changes should be checked into Fedora's SCM for rawhide although there is not yet a build and getting a rawhide build that restores the upgrade path should be a priority.

rpm's understanding of what package is newer comes from the values of the Epoch, Version, and Release tags. The next few sections explain what values to use in those tags to ensure that the EVR consistently increases.

Old examples from introduction

In Fedora we want to ensure that there is always an upgrade path from Fedora release to Fedora release and from Fedora release to the packages in updates. To do that we need to make sure the packages in the newer Fedora releases have an equal or higher Epoch:Version-Release (EVR) than the ones in older releases. For example, Fedora-38 ships with foo-1.0-1.fc38 and Fedora-39 ships with foo-1.0-2.fc39. This example shows that the Fedora-39 package will properly upgrade the Fedora-38 package.

A more complex example. Fedora-38 ships with foo-1.0-1.fc38 and Fedora-39 ships with foo-1.0-2.fc39. Fedora-38 gets an updated foo package: foo-1.0.1-1.fc38. This update is EVR higher than the package Fedora-38 shipped with so that's good. However, it is also EVR higher than what Fedora-39 shipped with so we need to make a Fedora-39 update at the same time, likely: foo-1.0.1-1.fc39. making that update means that someone updating from Fedora-38 with updates enabled will get the correct package on Fedora-39 with updates enabled.