From Fedora Project Wiki
(More info in introductory note.)
(Add notes and FAQ)
 
(19 intermediate revisions by the same user not shown)
Line 2: Line 2:
<div style="float: right; margin-left: 0.5em" class="toclimit-2">__TOC__</div>
<div style="float: right; margin-left: 0.5em" class="toclimit-2">__TOC__</div>


{{ admon/note |This is a a draft which uses both tilde and the [https://github.com/rpm-software-management/rpm/pull/597|proposed] caret notation for versioning.  The idea is to leverage these to the maximum amount possible in order to allow the Release: tag to be simple.}}
{{ admon/note |This is a a draft which uses both tilde and the proposed ([[https://github.com/rpm-software-management/rpm/pull/597]]) caret notation for versioning.  The idea is to leverage these to the maximum amount possible in order to extract the greatest amount of simplification.  This seems to me to be simpler, though it may be longer because I've added more explanatory text.}}


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.
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.
Line 15: Line 15:
;prerelease 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 final release of that version has not yet been made.  These we call prerelease versions.  The importance is that upstream is basically "counting down" towards some version number.  Fedora needs to indicate that, but needs to make sure that the ordering is correct so that the Fedora package will properly upgrade to that version when it is actually released.
: 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 final release of that version has not yet been made.  These we call prerelease versions.  The importance is that upstream is basically "counting down" towards some version number.  Fedora needs to indicate that, but needs to make sure that the ordering is correct so that the Fedora package will properly upgrade to that version when it is actually released.
;postrelease version
: Any version which upstream doesn't call a release which happens after a particular release but before upsteam decides to make a "prerelease". The distinction is that with a prerelease, upstream has made some decision about what to call the next version.  With a postrelease they haven't, and Fedora can't pick something for them.  Note that if tags, makes a tarball or even issues a patch file called "patchlevel1" or something like that, it's not considered a postrelease. It's just a release.


;snapshot
;snapshot
Line 39: Line 36:
In the case that you need to make a change to an older branch without rebuilding the newer branches and wish to preserve the ordering between branches, you MAY append a period and a second positive integer, beginning at 1.  This goes after the Dist tag:
In the case that you need to make a change to an older branch without rebuilding the newer branches and wish to preserve the ordering between branches, you MAY append a period and a second positive integer, beginning at 1.  This goes after the Dist tag:
<pre>
<pre>
Release: pkg=1.2-3%{?dist}.1
Release: 3%{?dist}.1
</pre>
</pre>


== Simple versioning ==
== Version: tag ==
 
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 in the <code>Version:</code> tag. Don't trim leading zeroes.
* Use a <code>Release:</code> tag that contains a positive integer, beginning with 1.
** Increment it for each change made to the package which does not change <code>Version:</code>.
** Reset to 1 when <code>Version:</code> changes.


If upstream uses a version containing dashes it usually suffices to either remove them or convert them to periods or underscores to get a simple versioning scheme.  See [[#Upstream uses invalid characters in the version]] below.
The <code>Version:</code> tag is where upsteam's chosen version information is placed.  In most cases (where you are not packaging a prerelease or a snapshot) you can just use the version information from upstream directly in <code>Version:</code> and you're done.  If upstream uses dashes, you may need to remove them or change them to either periods or underscores.  When you do want to package a prerelease or snapshot, or your upstream uses a very odd versioning scheme, you may need to modify the version information provided by upstream to make a complete version tag.


== More complex versioning ==
There are potentially three fields which comprise the structured <code>Version:</code> tag:
 
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 tag while imposing additional structure onto the <code>Version:</code> tag.  There are potentially four fields which comprise the structured <code>Version:</code> tag:


* Upstream release version (<code><upstreamrel></code>)
* Upstream release version (<code><upstreamrel></code>)
* Upstream prerelease identifier (<code><upstreamprerel></code>)
* Upstream prerelease identifier (<code><upstreamprerel></code>)
* an integer introduced to impose a sort order when necessary (<code><sort></code>)
* snapshot information (<code><snapinfo></code>)
* snapshot information (<code><snapinfo></code>)


Those items which are present are combined to construct the final <code>Version:</code>in one of the following formsThe usual convention where items in square brackets might not be present applies.
Those items which are present are combined to construct the final <code>Version:</code>in the following formSquare brackets are used to indicate that a component may not be present if it does not apply.


* <code><upstreamrel>~[<sort>.]<upsteamprerel>[^<snapinfo>]</code> (for prerelease versions, including potentially snapshots)
* <code><upstreamrel>[~<upsteamprerel>][^<snapinfo>]</code>
* <code><upstreamrel>^<snapinfo></code> (for postrelease snapshots)


A tilde ('<code>~</code>') indicates a prerelease; RPM will compare a string containing a tilde as being less (or older) than the equivalent string with the tilde and the content following it removed:
A tilde ('<code>~</code>') indicates a prerelease and a caret ('<code>^</code>') indicates a snapshot.  The tilde, if present, always comes before the caret.  These characters are special to RPM and provide for special version comparisons. See [[Package Versioning Examples]] for more information on how these work.
 
* 1.2 < 1.2.1~zyz < 1.2.1
 
A caret ('<code>^</code>') indicates a post-release snapshot.  RPM will compare a string containing a caret as being greater (or newer) than the equivalent string with the carent and following content removed, but less than (or older) than that string with anything appended:
 
* 1.2 < 1.2^xyz < 1.2.1
* 1.2 < 1.2^xyz < 1.2a


The actual values to be used for those fields are given in the sections below.  
The actual values to be used for those fields are given in the sections below.  
=== The <code><sort></code> field ===
It can rarely become necessary to insert an integer into the <code>Version:</code> in one place to ensure that RPM orders things properly.  This can happen if upstream's prerelease versions don't sort.  We want to avoid introducing <code>Epoch:</code> if at all possible, so the <code><sort></code> field is used instead.
When you need to use <code><sort></code> initially, just set it to 1 and start using it as above.  It will always be followed by a period.  <code><sort></code> will generally go away when <code><upstreamrel></code> changes, or (in the case of prereleases) <code><upstreamrel></code> is actually released.


=== Prerelease versions ===
=== Prerelease versions ===


In the <code>Version:</code> tag, use the following construction: <code><upstreamrel>~[<upstreamprerel>]</code>.  That is a literal tilde ( <code>~</code>) which instructs RPM to sort this <code>Version:</code> immediately before a package with the same version but no tilde.
When packaging a prerelease:


* <code><upstreamrel></code> should contain the version which upstream has decided this line of development will become once it has been released.
* <code><upstreamrel></code> should contain the version which upstream has decided this line of development will become once it has been released.
* <code><upstreamprerel></code> should contain a string which upstream has chosen to version the prereleases in this line of development.  Usually this will be something like "alpha3" or "pre2", and may need to be altered such that it includes no invalid characters.  (See [[#Upstream_uses_invalid_characters_in_the_version|above]].)  Note that it is possible that upstream has decided on the next release version but has not yet tagged a prerelease.  In this case you would be packaging a snapshot (see [[#Snapshots|below]]) and you would simply leave <code><upsteamprerel></code> empty.
* <code><upstreamrel></code> is followed by a tilde.
 
* <code><upstreamprerel></code> should contain a string which upstream has chosen to version the prereleases in this line of development.  Usually this will be something like "alpha3" or "pre2", and may need to be altered such that it includes no invalid characters.  (See [[#Upstream_uses_invalid_characters_in_the_version|below]].)  Note that it is possible that upstream has decided on the next release version but has not yet tagged a prerelease.  In this case you would be packaging a snapshot (see [[#Snapshots|below]]) and you would simply leave <code><upsteamprerel></code> empty '''while still including the tilde'''This ensures that everything sorts properly.
Note that values for <code><prerelease></code> must form a sortable sequenceIf you are not sure that your upstream will maintain sortability, you can form <code><prerelease></code> by prepending a positive integer: <code><integer>.<unsortable></code>.
 
=== Release and post-release versions ===
 
For the <code><pkgrel></code> field of the <code>Release:</code> tag, use an integer beginning with 1 and increasing for each revision of the package.  Release and post-release versions MUST use a <code>Release:</code> tag greater than or equal to 1.


=== Snapshots ===
=== Snapshots ===


All snapshots MUST contain a snapshot information field (<code><snapinfo></code>) in the <code>Version:</code> tag (for prerelease snapshots) or the <code>Release:</code> tag (for post-release snapshots).  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:
When packaging a snapshot <code><snapinfo></code>) 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:


* <code>YYYYMMDD.<revision></code>
* <code>YYYYMMDD.<revision></code>
Line 118: Line 74:
Where <code><scm></code> is a short string identifying the source code control system upstream uses (e.g. "git", "svn", "hg") or the string "snap".  <code><revision></code> 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.
Where <code><scm></code> is a short string identifying the source code control system upstream uses (e.g. "git", "svn", "hg") or the string "snap".  <code><revision></code> 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.


Note that if you take a snapshot which comes after a prerelease, the <code>Version:</code> MUST still include the prerelease information.  So a snapshot taken after beta1 has been released (but before beta2 or rc1 or the final release is tagged) still indicates "beta1" in the <code>Version:</code> tag.
If you need to make multiple snapshots per day, you can use a date format like YYYYMMDD.HH or YYYYMMDD.N where HH is the hour or N is a counter.  You can introduce this extra information when needed and go back to using the plain date the next day.
 
In the <code>Version:</code> tag, <code><snapinfo></code> MUST be preceded by a caret ('<code>^</code>).
 
If you take a snapshot which comes after a prerelease, the <code>Version:</code> MUST still include the prerelease information as indicated [[#Prerelease versions|above]].  So a snapshot taken after beta1 has been released (but before beta2 or rc1 or the final release is tagged) still indicates "beta1" in the <code>Version:</code> tag.  If you are packaging a prerelease snapshot where upstream has chosen the next version but not yet tagged any prerelease, the <code>Version:</code> tag '''still includes both the tilde and the caret''', as in "1.2~^20180101.abcdef".  If upstream later releases "1.2beta1" then things will sort properly if these rules are followed.


=== Upstream makes unsortable changes ===
=== 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 <code>Epoch:</code> tag, or to begin using it by adding <code>Epoch: 1</code>.  At the same time, try to work with upstream to hopefully minimize the need to involve <code>Epoch:</code> in the future.
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 <code>Epoch:</code> tag, or to begin using it by adding <code>Epoch: 1</code>.  At the same time, try to work with upstream to hopefully minimize the need to involve <code>Epoch:</code> in the future.
In the rare case that upstream uses unsortable prerelease tags, there may be an alternative to introducing <code>Epoch:</code>.  You can instead insert an integer in the <code>Version:</code> tag before the prerelease information.  So from the following sequence:
* 1.2 beta, 1.2 gamma, 1.2 delta
You can use the following vesions:
* 1.2~beta, 1.2~gamma, 1.2~1.delta
In general, if it is possible to insert an integer into a version sequence in such a way that it doesn't imply a version not actually released by upstream, then doing this is preferable to introducing <code>Epoch:</code>.


=== Upstream has never chosen a version ===
=== Upstream has never chosen a version ===


When upstream has never chosen a version, you MUST use <code>0</code> for <code><upstreamrel></code> and otherwise follow the guidelines for prerelease snapshots. "<code>0</code>" sorts lower than any other possible value that upstream might chooseAnd if upstream does choose to release "version 0.1" (or "0.0.1" or something similar) then you can immediately move to using <code>Version: 0.1</code> and <code>Release: 1%{?dist}</code> with no ordering issues.
When upstream has never chosen a version, you MUST use <code>0</code> for <code><upstreamrel></code> and otherwise follow the guidelines for prerelease snapshots. This will give  you something similar to "<code>0~^20180101.abcde</code>".  Then if upstream releases "version 0.1" (or "0.0.1" or something similar) then you can immediately move to using <code>Version: 0.1</code> and <code>Release: 1%{?dist}</code> with no ordering issues.


=== Upstream uses invalid characters in the version ===
=== Upstream uses invalid characters in the version ===
Line 133: Line 103:


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.  It is, however, often the case that a simple modification will give a scheme appropriate for [[#Simple versioning]].
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.  It is, however, often the case that a simple modification will give a scheme appropriate for [[#Simple versioning]].
== Transitioning from previous guidelines ==
These guidelines, when followed closely, should provide for proper package ordering for all reasonable upstream versioning schemes.  However, previous versions of the Fedora versioning guidelines did not permit the use of tilde, and so before applying these guidelines to an existing package it is important to ensure that the versioning does not go "backwards."
For post-release snapshots, there should be no issues.
Prereleases will generally have versioning problems, because where the old guidelines would give a version-release pair of something like "1.2-0.1.beta1" or "1.2-0.2.20180101.abcde", the new guidelines would require the use of a tilde.  As "1.2~anything" is seen by RPM as older than "1.2", you cannot switch a prerelease to these guidelines and must continue to follow the old guidelines.  (XXX Link to them.)  Once upstream has made an actual release, any later prereleases of the next version can make use of tilde.
The case where upstream has never made a release is similar, as "0~anything" is older than "0".  In this case, you can simply omit the tilde and still indicate the snapshot using the caret.  While the tilde is useful for indicating prereleases, the end result should be the same as long as upstream does not release "version 0".  If for some reason they do, you will either need to introduce <code>Epoch:</code> or fabricate a version like "0.0".


== Rawhide is allowed to lag temporarily ==
== 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.
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.
= Notes and FAQ =
These are not part of the guidelines; I just want to have a place to make notes and address questions which have been raised.
=== This is great!  Can I use it now? ===
Nope.  As of 20181122 you need a patched RPM.  The patch is in https://github.com/rpm-software-management/rpm/pull/597.  Even if you had that locally, most people won't and so you still can't use these guidelines.  If you try, you'll find that '^' is treated exactly as a dot is by current RPM versions, and so the special ordering properties simply don't work.
=== Why this bizarre thing with the tilde and caret next to each other? ===
The weirdest part of these guidelines is that prerelease snapshots which don't come after some prerelease tag like "beta1" still carry a tilde.  Here are a couple of reasons:
* Consistency.  Tilde indicates a prerelease; caret indicates a snapshot.  The snapshot information, when present, always goes in the same place (immediately following a caret, at the end of Version:).  This makes it easy to implement macros or other automation which fill in this information, since the snapshot info location doesn't change and always takes the same format.
* Ordering without inserting random counters.  It's been suggested to put prerelease snapshot information after a tilde.  And while 1.2~20190101.abcde works, it means you can't then move to 1.2~beta1.  So then 1.2~git20190101.abcde was suggested, which works but then when moving to beta1 you have to use 1.2~1.beta1.  Or the introduction of a snapshot can require an integer: 1.2~1.20190101.abcde, 1.2~2.beta1.  But with these guidelines you need none of that: 1.2~^20190101.abcde, 1.2~beta1
* If you just read tilde as "prerelease" and caret as "snapshot", it sounds right:
** 1.2~beta1 - "1.2 prerelease beta1"
** 1.2~^20190101.abcde - "1.2 prerelease snapshot from 20190101 with commit ID abcde"
I guess it's pretty common for upstream to say "we're working towards 1.2" without having tagged a prerelease, as that's how the kernel works, so this is a case that needs to be handled cleanly.
=== But you had to add that rule about inserting a counter in snapshots... ===
Yes, when making multiple snapshots per day (which should be pretty rare in itself), the existing guidelines always have you using a counter: 1.2-1.20190101.zzz, 1.2-2.20190101.aaa so you could take as many different snapshots per day as you wanted without caring about ordering.  And while we could require the use of a similar counter (1.2^1.20190101.zzz, 1.2^2.20190101.aaa), this is something everyone would had to use even though it's far from the common case.  Allowing the hour or a counter to be added to the date works (1.2^20190101.08.zzz, 1.2^20190101.13.aaa) or (1.2^20190101.zzz, 1.2^20190101.13.aaa) and doesn't complicate the usual case.  Someone who uses a lot of snapshots could always do this.  The forge macros could trivially grow a switch to add the hour information or a counter.
=== What about switching to using git describe and the like, or dropping the date from snapshot info ===
I am treating those as orthogonal issues.  Those decisions can be made and trivially dropped into these guidelines as long as the result is an ordered sequence.
If you just use the bare commit hash, a counter will be required.  A counter will, I believe, trivially come out of using git describe for a count of commits past the last tagged prerelease.  But I don't know how well git describe works before upstream has tagged any kind of prerelease since as I understand things it only gives you a distance from a tag.

Latest revision as of 02:38, 23 November 2018

This is a a draft which uses both tilde and the proposed ([[1]]) caret notation for versioning. The idea is to leverage these to the maximum amount possible in order to extract the greatest amount of simplification. This seems to me to be simpler, though it may be longer because I've added more explanatory text.

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 give a version and call "released". 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, but it doesn't include so called "prerelease versions".
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 final release of that version has not yet been made. These we call prerelease versions. The importance is that upstream is basically "counting down" towards some version number. Fedora needs to indicate that, but needs to make sure that the ordering is correct so that the Fedora package will properly upgrade to that version when it is actually released.
snapshot
An archive taken from upstream's source code control system which is not equivalent to any release 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 because to RPM they look "older".

Examples

Examples of many possible versioning scenarios and tips on making your own version comparison tests 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.

Release: tag

The Release: tag provides the least significant input to RPM's version comparison function. MUST consist of a positive integer, with the Dist tag appended. This integer MUST begin at 1 and MUST be incremented for each change made to the package that does not involve a change to the Version: tag. When a change is made that does change the Version: tag, the integer MUST be reset to 1.

In the case that you need to make a change to an older branch without rebuilding the newer branches and wish to preserve the ordering between branches, you MAY append a period and a second positive integer, beginning at 1. This goes after the Dist tag:

Release: 3%{?dist}.1

Version: tag

The Version: tag is where upsteam's chosen version information is placed. In most cases (where you are not packaging a prerelease or a snapshot) you can just use the version information from upstream directly in Version: and you're done. If upstream uses dashes, you may need to remove them or change them to either periods or underscores. When you do want to package a prerelease or snapshot, or your upstream uses a very odd versioning scheme, you may need to modify the version information provided by upstream to make a complete version tag.

There are potentially three fields which comprise the structured Version: tag:

  • Upstream release version (<upstreamrel>)
  • Upstream prerelease identifier (<upstreamprerel>)
  • snapshot information (<snapinfo>)

Those items which are present are combined to construct the final Version:in the following form. Square brackets are used to indicate that a component may not be present if it does not apply.

  • <upstreamrel>[~<upsteamprerel>][^<snapinfo>]

A tilde ('~') indicates a prerelease and a caret ('^') indicates a snapshot. The tilde, if present, always comes before the caret. These characters are special to RPM and provide for special version comparisons. See Package Versioning Examples for more information on how these work.

The actual values to be used for those fields are given in the sections below.

Prerelease versions

When packaging a prerelease:

  • <upstreamrel> should contain the version which upstream has decided this line of development will become once it has been released.
  • <upstreamrel> is followed by a tilde.
  • <upstreamprerel> should contain a string which upstream has chosen to version the prereleases in this line of development. Usually this will be something like "alpha3" or "pre2", and may need to be altered such that it includes no invalid characters. (See below.) Note that it is possible that upstream has decided on the next release version but has not yet tagged a prerelease. In this case you would be packaging a snapshot (see below) and you would simply leave <upsteamprerel> empty while still including the tilde. This ensures that everything sorts properly.

Snapshots

When packaging a snapshot <snapinfo>) 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.

If you need to make multiple snapshots per day, you can use a date format like YYYYMMDD.HH or YYYYMMDD.N where HH is the hour or N is a counter. You can introduce this extra information when needed and go back to using the plain date the next day.

In the Version: tag, <snapinfo> MUST be preceded by a caret ('^).

If you take a snapshot which comes after a prerelease, the Version: MUST still include the prerelease information as indicated above. So a snapshot taken after beta1 has been released (but before beta2 or rc1 or the final release is tagged) still indicates "beta1" in the Version: tag. If you are packaging a prerelease snapshot where upstream has chosen the next version but not yet tagged any prerelease, the Version: tag still includes both the tilde and the caret, as in "1.2~^20180101.abcdef". If upstream later releases "1.2beta1" then things will sort properly if these rules are followed.

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.

In the rare case that upstream uses unsortable prerelease tags, there may be an alternative to introducing Epoch:. You can instead insert an integer in the Version: tag before the prerelease information. So from the following sequence:

  • 1.2 beta, 1.2 gamma, 1.2 delta

You can use the following vesions:

  • 1.2~beta, 1.2~gamma, 1.2~1.delta

In general, if it is possible to insert an integer into a version sequence in such a way that it doesn't imply a version not actually released by upstream, then doing this is preferable to introducing Epoch:.

Upstream has never chosen a version

When upstream has never chosen a version, you MUST use 0 for <upstreamrel> and otherwise follow the guidelines for prerelease snapshots. This will give you something similar to "0~^20180101.abcde". Then if upstream releases "version 0.1" (or "0.0.1" or something similar) then you can immediately move to using Version: 0.1 and Release: 1%{?dist} with no ordering issues.

Upstream uses invalid characters in the version

It's possible that upstream uses characters besides digits, ASCII letters (upper and lower case), periods and underscores 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. It is common, however, to either remove dashes or replace them with underscores or periods (which RPM treats identically).

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. It is, however, often the case that a simple modification will give a scheme appropriate for #Simple versioning.

Transitioning from previous guidelines

These guidelines, when followed closely, should provide for proper package ordering for all reasonable upstream versioning schemes. However, previous versions of the Fedora versioning guidelines did not permit the use of tilde, and so before applying these guidelines to an existing package it is important to ensure that the versioning does not go "backwards."

For post-release snapshots, there should be no issues.

Prereleases will generally have versioning problems, because where the old guidelines would give a version-release pair of something like "1.2-0.1.beta1" or "1.2-0.2.20180101.abcde", the new guidelines would require the use of a tilde. As "1.2~anything" is seen by RPM as older than "1.2", you cannot switch a prerelease to these guidelines and must continue to follow the old guidelines. (XXX Link to them.) Once upstream has made an actual release, any later prereleases of the next version can make use of tilde.

The case where upstream has never made a release is similar, as "0~anything" is older than "0". In this case, you can simply omit the tilde and still indicate the snapshot using the caret. While the tilde is useful for indicating prereleases, the end result should be the same as long as upstream does not release "version 0". If for some reason they do, you will either need to introduce Epoch: or fabricate a version like "0.0".

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.

Notes and FAQ

These are not part of the guidelines; I just want to have a place to make notes and address questions which have been raised.

This is great! Can I use it now?

Nope. As of 20181122 you need a patched RPM. The patch is in https://github.com/rpm-software-management/rpm/pull/597. Even if you had that locally, most people won't and so you still can't use these guidelines. If you try, you'll find that '^' is treated exactly as a dot is by current RPM versions, and so the special ordering properties simply don't work.

Why this bizarre thing with the tilde and caret next to each other?

The weirdest part of these guidelines is that prerelease snapshots which don't come after some prerelease tag like "beta1" still carry a tilde. Here are a couple of reasons:

  • Consistency. Tilde indicates a prerelease; caret indicates a snapshot. The snapshot information, when present, always goes in the same place (immediately following a caret, at the end of Version:). This makes it easy to implement macros or other automation which fill in this information, since the snapshot info location doesn't change and always takes the same format.
  • Ordering without inserting random counters. It's been suggested to put prerelease snapshot information after a tilde. And while 1.2~20190101.abcde works, it means you can't then move to 1.2~beta1. So then 1.2~git20190101.abcde was suggested, which works but then when moving to beta1 you have to use 1.2~1.beta1. Or the introduction of a snapshot can require an integer: 1.2~1.20190101.abcde, 1.2~2.beta1. But with these guidelines you need none of that: 1.2~^20190101.abcde, 1.2~beta1
  • If you just read tilde as "prerelease" and caret as "snapshot", it sounds right:
    • 1.2~beta1 - "1.2 prerelease beta1"
    • 1.2~^20190101.abcde - "1.2 prerelease snapshot from 20190101 with commit ID abcde"

I guess it's pretty common for upstream to say "we're working towards 1.2" without having tagged a prerelease, as that's how the kernel works, so this is a case that needs to be handled cleanly.

But you had to add that rule about inserting a counter in snapshots...

Yes, when making multiple snapshots per day (which should be pretty rare in itself), the existing guidelines always have you using a counter: 1.2-1.20190101.zzz, 1.2-2.20190101.aaa so you could take as many different snapshots per day as you wanted without caring about ordering. And while we could require the use of a similar counter (1.2^1.20190101.zzz, 1.2^2.20190101.aaa), this is something everyone would had to use even though it's far from the common case. Allowing the hour or a counter to be added to the date works (1.2^20190101.08.zzz, 1.2^20190101.13.aaa) or (1.2^20190101.zzz, 1.2^20190101.13.aaa) and doesn't complicate the usual case. Someone who uses a lot of snapshots could always do this. The forge macros could trivially grow a switch to add the hour information or a counter.

What about switching to using git describe and the like, or dropping the date from snapshot info

I am treating those as orthogonal issues. Those decisions can be made and trivially dropped into these guidelines as long as the result is an ordered sequence.

If you just use the bare commit hash, a counter will be required. A counter will, I believe, trivially come out of using git describe for a count of commits past the last tagged prerelease. But I don't know how well git describe works before upstream has tagged any kind of prerelease since as I understand things it only gives you a distance from a tag.