#1073 Use tilde and caret in version field
Merged 2 years ago by ngompa. Opened 2 years ago by zbyszek.
zbyszek/packaging-committee tilde-and-caret-versioning  into  master

@@ -15,7 +15,7 @@ 

  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,

+ Some upstreams never make releases,

  instead just letting users take whatever is in the code repository at any given time.

  

  release version::
@@ -52,39 +52,28 @@ 

    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 https://fedoraproject.org/wiki/Package_Versioning_Examples[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

+ 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 be removed or decreased in any way.

+ **must never** be removed or decreased.

  

  == Simple versioning

  

  Most upstream versioning schemes are "simple";

- they generate versions like "1.2.03.007p1".

- They consist 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)

+ they generate versions like `+1.2.03.007p1+`.

+ They consist of one or more version components, separated by periods.

+ Each component is a whole number, potentially with leading zeroes.

+ The components 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")

+ 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.

+ 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.
@@ -98,7 +87,7 @@ 

    Increment the release (by 1) for each update you make.

    Reset to 1 whenever you change `+Version:+`.

  

- == More complex versioning

+ == Complex versioning

  

  There are several ways in which the simple scheme might not work

  in a particular situation:
@@ -111,14 +100,262 @@ 

    (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.

+   but then changed in a way that does not sort properly.

  * 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

+ === Handling non-sorting versions with tilde, dot, and caret

+ 

+ The tilde symbol ('`+~+`') is used before a version component which must sort *earlier* than any non-tilde component.

+ It is used for any pre-release versions which wouldn't otherwise sort appropriately.

+ 

+ For example, with upstream releases `+0.4.0+`, `+0.4.1+`, `+0.5.0-rc1+`, `+0.5.0-rc2+`, `+0.5.0+`,

+ the two "release candidates" should use `+0.5.0~rc1+` and `+0.5.0~rc2+` in the `+Version:+` field.

+ 

+ Bugfix or "patchlevel" releases that some upstream make should be handled using simple versioning.

+ The separator used by upstream may need to be replaced by a dot or dropped.

+ 

+ For example, if the same upstream released `+0.5.0-post1+` as a bugfix version,

+ this "post-release" should use `+0.5.0.post1+` in the `+Version:+` field.

+ Note that `+0.5.0.post1+` sorts lower than both `+0.5.1+` and `+0.5.0.1+`.

+ 

+ The caret symbol ('`+^+`') is used before a version component which must sort *later* than any non-caret component.

+ It is used for post-release snapshots, see next section.

+ 

+ IMPORTANT: The caret operator is not supported in RHEL7 which has rpm 4.11.

+ If you need to support RHEL7/EPEL7 from the same specfile, use

+ <<Traditional versioning with part of the upstream version information in the release field>>

+ instead.

+ 

+ === Snapshots

+ 

+ Snapshots (a version taken from the upstream source control system not associated with a release),

+ **must** contain a snapshot information field after a caret (`+^+`).

+ The first part of the field ensures proper sorting.

+ That field may either the date in eight-digit "YYYYMMDD" format,

+ which specifies the last modification of the source code,

+ or a number.

+ The packager **may** include up to 17 characters of additional information after the date,

+ specifying the version control system and commit identifier.

+ The snapshot information field is appended to version field described above,

+ possibly including the pre-release and patchlevel information.

+ 

+ One of the following formats should be used for the snapshot information field:

+ 

+ * `+<date>.<revision>+`

+ * `+<date><scm><revision>+`

+ * `+<number>.<revision>+`

+ * `+<number>.<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".

+ The `+<scm>+` string may be abbreviated to a single letter.

+ `+<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.

+ If the version control system does not provide an identifier (e.g. CVS), this part should be omitted.

+ A full hash **should not** be used for `+<revision>+`, to avoid overly long version numbers;

+ only the first 7 to 10 characters.

+ 

+ For example, if the last upstream release was `+0.4.1+`,

+ a snapshot could use `+0.4.1^20200601g01234ae+` in the `+Version:+` field.

+ Similarly, if the upstream then makes a pre-release with version `+0.5.0-rc1+`,

+ but it is buggy, and we need to actually package two post-pre-release snapshots,

+ those shapshots could use `+0.5.0~rc1^20200701gdeadf00f+` and `+0.5.0~rc1^20200702gdeadaeae+`

+ in the `+Version:+` field.

+ 

+ Alternatively, those three snapshots could be versioned as

+ `+0.4.1^1.git01234ae+`,  `+0.5.0~rc1^1.gitdeadf00f+` and `+0.5.0~rc1^2.gitdeadaeae+`.

+ 

+ Note that `+0.4.1^<something>+` sorts higher than `+0.4.1+`, but lower than both `+0.4.2+` and `+0.4.1.<anything>+`.

+ 

+ === 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.

+ If upstream does choose to release "version 0",

+ then just set `+Release:+` higher than the previous value.

+ 

+ === 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 simply inserting a tilde or caret is enough to make the string sortable.

+ 

+ For example, if upstream uses a sequence like `+1.2pre1+`, `+1.2pre2+`, `+1.2final+`,

+ then `+1.2~pre1+`, `+1.2~pre2+`, `+1.2_final+` could be used as `+Version+`.

+ The underscore ('`+_+`') is a visual separator that does not influence sort order,

+ and is used here because "final" does not form a separate version component.

+ 

+ If this is not possible, use something similar to the snapshot version information field described above,

+ with the upstream version moved to the second part of the snapshot information field:

+ `+<date>.<version>+`.

+ 

+ For example, if upstream releases versions `+I+`, `+II+`, …, `+VIII+`, `+IX+`

+ use `+20200101.I+`, `+20200201.II+`, …, `+20200801.III+`, `+20200901.IX+`

+ in the `+Version+` field.

+ 

+ === Upstream breaks version scheme

+ 

+ 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 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.

+ 

+ === Examples

+ 

+ ==== Comparing versions with `rpmdev-vercmp`

+ 

+ When in doubt, verify the sorting with `rpmdev-vercmp` from the `rpmdevtools` package:

+ 

+ ```console

+ $ rpmdev-vercmp 2~almost^post 2.0.1

+ 2~almost^post < 2.0.1

+ ```

+ 

+ ==== Simple versioning

+ 

+ [%header]

+ |===

+ |Upstream| Version field | Release field | Explanation

+ 

+ |1.0     |1.0         | 1%{?dist} | The first release.

+ 

+ |1.1     |1.1         | 1%{?dist} | An upstream update.

+ 

+ |1.1     |1.1         | 2%{?dist} | You made a change to the package but the upstream version didn't change.

+ 

+ |1.2     |1.2         | 1%{?dist} | The upstream version changed, so Release: goes back to 1.

+ 

+ |1.2.1   |1.2.1       |1%{?dist}  | Extra levels of versioning are OK…

+ 

+ |1.3     |1.3         |1%{?dist}  | …they can come and go without problems.

+ |===

+ 

+ [%header]

+ |===

+ |Upstream| Version field | Release field | Explanation

+ 

+ | 5.2    | 5.2           | 1%{?dist}     |

+ 

+ | 5.2a   | 5.2a          | 1%{?dist}     | Upstream introduced a letter to indicate a patch release. You trust upstream to use letters in alphabetical order, so it's OK to use the version as is.

+ 

+ | 5.2b   | 5.2b          | 1%{?dist}     |

+ 

+ | 5.2b.1 | 5.2b.1        | 1%{?dist}     | Even this is OK as long as the sequence increases.

+ 

+ | 5.3    | 5.3           |  1%{?dist}    |

+ |===

+ 

+ ==== Complex versioning with a reasonable upstream

+ 

+ [%header]

+ |===

+ |Upstream version | Full package NEVRA | Notes

+ 

+ | 1.0.0-rc1 | `+pkg-1.0.0~rc1-1%{?dist}+` | first prerelease

+ 

+ | 1.0.0-rc2 | `+pkg-1.0.0~rc2-1%{?dist}+` | second prerelease

+ 

+ | 1.0.0     | `+pkg-1.0.0-1%{?dist}+`     | release

+ 

+ | 1.0.1     | `+pkg-1.0.1-1%{?dist}+`     | bugfix release

+ 

+ | 1.0.1-security1 | `+pkg-1.0.1.security1-1%{?dist}+` | security bufix release

+ |===

+ 

+ ==== Complex versioning with non-sorting upstream post-release versions

+ 

+ [%header]

+ |===

+ |Upstream version | Full package NEVRA | Notes

+ 

+ | 1.1.0~BETA      | `+pkg-1.1.0~BETA-1%{?dist}+` | this is a prerelease, first beta

+ 

+ | 1.1.0~BETA1     | `+pkg-1.1.0~BETA1-1%{?dist}+` | this is a prerelease, second beta

+ 

+ | 1.1.0~BETA2     | `+pkg-1.1.0~BETA2-1%{?dist}+` | this is a prerelease, third beta

+ 

+ | 1.1.0~CR1       | `+pkg-1.1.0~CR1-1%{?dist}+` | this is a prerelease, candidate release 1

+ 

+ | 1.1.0~CR2       | `+pkg-1.1.0~CR2-1%{?dist}+` | this is a prerelease, candidate release 2

+ 

+ |                 | `+pkg-1.1.0~CR2-2%{?dist}+` | this is a prerelease, candidate release 2, second build

+ 

+ | 1.1.0-1%        | `+pkg-1.1.0-1%{?dist}+` | final release

+ 

+ | 1.1.0-GA1       | `+pkg-1.1.0.20201001.GA1-1%{?dist}+` | post release, GA1

+ 

+ | 1.1.0-CP1       | `+pkg-1.1.0.20201011.CP1-1%{?dist}+` | post release, CP1, after GA1, does not sort properly

+ 

+ | 1.1.0-CP2       | `+pkg-1.1.0.20201101.CP2-1%{?dist}+` | post release, CP2, after CP1

+ 

+ | 1.1.0-SP1       | `+pkg-1.1.0.20210101.SP1-1%{?dist}+` | post release, SP1, after CP2

+ 

+ | 1.1.0-SP1-CP1   | `+pkg-1.1.0.20210105.SP1_CP1-1%{?dist}+` | post release, SP1_CP1, after SP1

+ |===

+ 

+ 

+ ==== Complex versioning with a pre- and post-release snapshots

+ 

+ [%header]

+ |===

+ |Upstream version | Full package NEVRA | Notes

+ 

+ | 1.0.0-rc1            | `+pkg-1.0.0~rc1-1%{?dist}+` | First prerelease

+ 

+ | 1.0.0-rc2            | `+pkg-1.0.0~rc2-1%{?dist}+` | Second prerelease

+ 

+ | git commit `f00fabd` | `+pkg-1.0.0~rc2^20210101gf00fabd-1%{?dist}+` | Post-prerelease snapshot

+ 

+ | 1.0.0                | `+pkg-1.0.0-1%{?dist}+`     | A release

+ 

+ |                      | `+pkg-1.0.0-2%{?dist}+`     | A rebuild from the same sources

+ 

+ | 1.0.1                | `+pkg-1.0.1-1%{?dist}+`     | A bugfix release

+ 

+ | git commit `bbbccc0` | `+pkg-1.0.1^20210203gbbbccc0-1%{?dist}+` or `+pkg-1.0.1^1.gbbbccc0-1%{?dist}+` | A snapshot

+ 

+ | 1.0.1-security1      | `+pkg-1.0.1.security1-1%{?dist}+` | A security bufix release. From past history we know that the bugfix releases will have sortable versions. If not, we could use '`+<date>.security1+`' instead.

+ 

+ | git commit `abc0202` | `+pkg-1.0.1.security1^20210301gabc0202-1%{?dist}+` or `+pkg-1.0.1.security1^1.gabc0202-1%{?dist}+` | Another snapshot

+ |===

+ 

+ 

+ == Traditional versioning with part of the upstream version information in the release field

+ 

+ The method described in this section is deprecated, but **may** be used.

+ As mentioned in the <<Handling non-sorting versions with tilde, dot, and caret>> section above,

+ this method is recommended for packages with complex versioning when supporting RHEL7

+ and other systems with old rpm versions.

+ 

+ This method for dealing with most pre- and post-release versions and unsortable versions

+ involves potentially removing some information from the `+Version:+` tag

  while imposing additional structure onto the `+Release:+` tag.

  There are potentially four fields which comprise

  the structured `+Release:+` tag:
@@ -128,7 +365,7 @@ 

  * snapshot information (`+<snapinfo>+`)

  * minor release bump (`+<minorbump>+`)

  

- The package release number MUST always be present

+ 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
@@ -151,34 +388,9 @@ 

  including tildes.

  As this is not under the control of the packager,

  that structure is not covered here.

- The packager MUST simply include `+%{?dist}+` verbatim

+ The packager **must** simply include `+%{?dist}+` verbatim

  as indicated above.

  

- === 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,
@@ -197,11 +409,11 @@ 

  

  === Snapshots

  

- All snapshots MUST contain a snapshot information field

+ 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

+ The packager **may** include

  up to 17 characters of additional information

  after the date.

  The following formats are suggested:
@@ -221,7 +433,7 @@ 

  Obviously if CVS is used,

  no such revision information exists,

  so it would be omitted,

- but otherwise it SHOULD be included.

+ but otherwise it **should** be included.

  

  === Prerelease versions

  
@@ -231,7 +443,7 @@ 

  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

+ Prerelease versions **must** use

  a `+Release:+` tag strictly less than 1,

  as this is the sole indicator that a prerelease has been packaged.

  
@@ -240,24 +452,20 @@ 

  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

+ Release and post-release versions **must** use

  a `+Release:+` tag greater than or equal to 1.

  

- === Upstream makes unsortable changes

+ === Examples

+ 

+ Examples of many possible versioning scenarios of traditional versioning

+ are available from

+ https://fedoraproject.org/wiki/Package_Versioning_Examples[Package Versioning Examples].

  

- 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

+ 

+ 

+ 

+ == 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.
@@ -269,41 +477,17 @@ 

  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>+`

+ 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 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 construct `+Version:+` and `+Release:+` as follows:

- 

-     Version: <nextrel>~<prerel>

-     Release: <pkgrel>%{?dist}[.<minorbump>]

- 

- with `+<pkgrel>+` 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 thus 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

+ 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

This is an early draft for feedback. Please don't consider for merging yet.

Thank you for your contribution. Unfortunately your PR did not build for some reason. Does it build locally for you?
If it does you can ignore the message.

What do you mean "does not build"? asciidoctor guidelines/modules/ROOT/pages/Versioning.adoc does not complain.

Some version examples "in the wild":

 po-debconf                     1.0.21-6.nmu1.fc35                                        
pocketsphinx                   1:5-0.6.prealpha.fc35                                     
postgres-decoderbufs           1.4.0-2.Final.fc35                                        
pxz                            4.999.9-21.beta.20200421git.fc34                          
python-contextlib2             0.6.0.post1-1.fc35                                        
python-cypari2                 2.1.2-0.3.b1.fc34                                         
python-d2to1                   0.2.12-19.post1.fc34                                      
python-ffc                     2019.1.0.post0-5.fc34                                     
python-pdir2                   0.3.1.post2-10.fc34                                       
python-publicsuffix2           2.20191221-3.fc34                                         
python-pygments-markdown-lexer 0.1.0.dev39-20.fc34                                       
qt4-theme-quarticurve          0.0-0.36.beta8.fc34                                       
qt5-qtwebkit                   5.212.0-0.59.alpha4.fc35                                  
rarpd                          ss981107-58.fc34                                          
rubygem-net-irc                0.0.9-18.D20121021git4cf339fa69.fc34                      
rust-ruma-signatures           0.6.0~alpha.1-2.fc34                                      
scalpel                        2.1-0.rc1.2.47815c2.fc34.12                               
sphinxbase                     1:5-0.9.prealpha.fc34                                     
xorg-x11-drv-armada            0.0.0-6.unstable.20180829git78e7116a5.fc34                
joda-time                      2.9.9-9.tzdata2017b.fc33
hfsplus-tools.src              540.1.linux3-23.fc34
icedtea-web.src                2.0.0-pre.0.3.alpha16.patched1.1.fc35
libmp4v2.src                   2.1.0-0.23.trunkREV507.fc34
wyhash.src                     final1-1.20210311gitfinal.fc35

I didn't look at all packages, but it really seems that such packages with non-numeric versions a tiny minority.

A couple of quibbles:

  • I'd like to see the structure of snapshot versioning to be <scm>.<commitdate/snapdate>.<shorthash>. This makes the sorting easier to reason (since numbers are higher than letters in sorting). This also aligns with how openSUSE and Debian do this.
  • It'd probably be a good idea to have note that falling back to + where ^ is not available is an option (RHEL 7). Combined with the previous suggestion, it makes the post-release sorting consistent.

I'm not a fan of the double carets. I understand the use case for when it would be necessary, but it's a quite rare edge case. It also doesn't entirely solve the problem, because upstream projects could come up with other post-release labels that don't sort correctly. My suggestion would be that post-release versions must always be converted to revision snapshot notation to ensure proper sorting, i.e. ignore the label and package the revision the label references.

The same problem of incorrectly sorting labels exists with pre-release versions (is pre1 before or after beta1?). I suggest that we allow alpha*, beta*, and rc* pre-release versions (which sort correctly), and require any other pre-release labels to be converted to revision snapshot notation.

rebased onto 6a54922d64f8b1fe92a6522c323d0ca25e660ba3

2 years ago

Thank you for the reviews.

I force-pushed the branch with some minor fixups squashed into the existing commits, but actual "meaningful" changes done in two new commits, to make re-review easier.

I'm not a fan of the double carets. I understand the use case for when it would be necessary, but it's a quite rare edge case. It also doesn't entirely solve the problem, because upstream projects could come up with other post-release labels that don't sort correctly. My suggestion would be that post-release versions must always be converted to revision snapshot notation to ensure proper sorting, i.e. ignore the label and package the revision the label references.

The same problem of incorrectly sorting labels exists with pre-release versions (is pre1 before or after beta1?). I suggest that we allow alpha*, beta*, and rc* pre-release versions (which sort correctly), and require any other pre-release labels to be converted to revision snapshot notation.

I reworked this part. I realized that everything becomes simple if carets are only used for snapshots, and post-releases simply use a dot as the separator. Apart from some edge cases, a bugfix post-release is just a release.

A couple of quibbles:

  • I'd like to see the structure of snapshot versioning to be <scm>.<commitdate/snapdate>.<shorthash>. This makes the sorting easier to reason (since numbers are higher than letters in sorting). This also aligns with how openSUSE and Debian do this.

I thought about this when writing the text, because I saw that quite a few packages do this. But I don't think it is a good idea, because now we rely on <scm> for the sort order. When <date> is used as the first part, we get sortable versions in all cases. If upstream makes a bugfix release, we can label it as <date>.bugfix1. If upstream converts from mercurial to git, we can label it as <date>.<newscm><shorthash>. I agree that putting <scm> first is more readable, but it just seems to fragile to recommend.

  • It'd probably be a good idea to have note that falling back to + where ^ is not available is an option (RHEL 7). Combined with the previous suggestion, it makes the post-release sorting consistent.

Hmm, that would work , but seems easy to break:

$ rpmdev-vercmp 0.5.0^2020 0.5.0.01
0.5.0^2020 < 0.5.0.01
$ rpmdev-vercmp 0.5.0+2020 0.5.0.01
0.5.0+2020 > 0.5.0.01

If think that if caret is not available, the only realistic option is to fall back "traditional versioning". It's too easy to get wrong otherwise.

Hmm, that would work , but seems easy to break:

The reason for that is because you have the number as the prefix. Switching to a word as a prefix fixes this:

$ rpmdev-vercmp 0.5.0^snap2020 0.5.0.01
0.5.0^snap2020 < 0.5.0.01
$ rpmdev-vercmp 0.5.0+snap2020 0.5.0.01
0.5.0+snap2020 < 0.5.0.01

Perhaps we should just always suggest snap before the date, regardless of SCM?

Then it would be something like snap<commitdate/snapdate>.<scm>.<shorthash>.

We're getting into bikeshedding terriory here… but I don't think this is better.
In particular:

$ rpmdev-vercmp 0.5.0+snap2020 0.5.0.post1
0.5.0+snap2020 > 0.5.0.post1

And also, snap<commitdate/snapdate>.<scm>.<shorthash> is 24–27 characters (with a 7–10 digit hash), which is annoying.

So I think it's fine to say that "if you need to cover RHEL7, just use the old system". It's not going away and many people will keep using it anyway because they don't see a good enough reason to switch to the new one.

So I think it's fine to say that "if you need to cover RHEL7, just use the old system". It's not going away and many people will keep using it anyway because they don't see a good enough reason to switch to the new one.

:thumbsup:

then you can immediately move to using Release: 1%{?dist} with no ordering issues.

I don't understand this part. Is there some information missing, such as that we were using Release: 0.N%{?dist} release before?

2 new commits added

  • Say that RHEL<=8 should use the traditional approach
  • Adjust note about "version 0"
2 years ago

I don't understand this part. Is there some information missing, such as that we were using Release: 0.N%{?dist} release before?

Yeah, I think it's some leftover from an older convention.

I pushed two new commits:
- reword the sentence about "version 0" to fix the issue mentioned by @churchyard
- say that when supporting RHEL<9 with the same spec file, the traditional approach should be used.

--

I think this is ready for general review and/or merging. Please consider this an official pull request now. Let me know if I should submit a separate ticket somewhere.

  • say that when supporting RHEL<9 with the same spec file, the traditional approach should be used.

RHEL 8 also supports tilde and caret.

Let me know if I should submit a separate ticket somewhere.

We have two tickets that this would resolve: #904 and #937

I reworked this part. I realized that everything becomes simple if carets are only used for snapshots, and post-releases simply use a dot as the separator. Apart from some edge cases, a bugfix post-release is just a release.

Looks great now, thanks. 👍

RHEL 8 also supports tilde and caret.

mock -r epel-8-x86_64 --shell 'rpm -q rpm' gives me rpm-4.14.3-13.el8.x86_64, and ^ was added 4.15 according to https://fedoraproject.org/wiki/Changes/RPM-4.15#Detailed_Description. What am I missing?

IIRC support for ^ versioning was backported to rpm in RHEL 8. Neal will correct me if I'm wrong :)

6 new commits added

  • Say that RHEL<=7 should use the traditional approach
  • Adjust note about "version 0"
  • Versioning: allow a number as replacement for date in shapshot information
  • Stop using ^ for snapshots
  • Versioning: switch to ~ and ^ for pre- and post-release versions
  • Versioning: MAY → **may**, etc
2 years ago

Thanks. I adjusted the last commit to say RHEL7, and removed the explicit mention of rpm versions (I don't think it's useful to go into details of what was backported where).

IIRC support for ^ versioning was backported to rpm in RHEL 8. Neal will correct me if I'm wrong :)

Yes, it was backported some time ago, as I noted in #904 :wink:

If there are not more comments… can this go on the meeting agenda?

Metadata Update from @churchyard:
- Pull-request tagged with: meeting

2 years ago

Python related note: Python packages release post releases as e.g. 1.2.3post1. Up until now, I'd package that as 1.2.3^post1. Packaging as 1.2.3.post1 is possible as well, however brings all sort of trouble with it (e.g. it is not easily convertible to upstream version simply by stripping tildes and carets). Can we at least package it as 1.2.3post1 or is the dot mandatory?

I don't think anything special needs to happen for 1.2.3post1. It falls squarely into the "Simple versioning" section, like 1.4, 1.4a, 1.4b given in the example. Actually that part of the text wasn't changed, except for cosmetic updates.

This section confused me:

For example, if the same upstream released 0.5.0-post1 as a bugfix version,
this "post-release" should use 0.5.0.post1 in the Version: field.
Note that 0.5.0.post1 sorts lower than both 0.5.1 and 0.5.0.1.

Yeah, but that section is titled "Handling non-sorting versions with tilde, dot, and caret". In the example given in the text "0.5.0-post1" requires special treatment because "-" is a separator between version and release, and we cannot have it in the version field. None of this applies to 1.2.3post1. I think the text is is pretty clear. If you have some suggestion how to make the text clearer, please propose a specific change.

(Would adding a sentence about why "-" is not allowed in that place make things clear?)

Also note, that you could also use _ in place of -, though it does look kind of weird.

Also note, that you could also use _ in place of -, though it does look kind of weird.

Conceptually a dot is better: rpm thinks the dot is a component separator, so 1.2.3.post1 is a separate version with (1, 2, 3, post1). With the underscore, we get (1, 2, 3_post1). This works fine because 3_post sorts later than 3. I think that upstream meant this to be a separate component by separating this with the dash. The fact that there's a conceptual advantage is much less important than the fact that both versions work fine, so I wouldn't care too much if a packager used _, but I think it's still nicer to recommend the dot…

+1 as it is. I don't want to bike shed about details, I want this used in practice :) We can iterate later if needed.

Thanks @zbyszek

I'm 99% sure there's no difference between '_' and '.' ... rpm only cares about ASCII alphanumerics, '~' and '^' ... anything else is the same.

See:

https://github.com/rpm-software-management/rpm/blob/master/rpmio/rpmvercmp.c#L34

Also:

% rpmdev-vercmp abcd_xyz abcd.xyz
abcd_xyz == abcd.xyz

Thanks for picking this up and running with it. +1 from me, though we will need to figure out how to best keep the old document around.

rebased onto 907f13f

2 years ago

Metadata Update from @ngompa:
- Request assigned

2 years ago

This is approved in today's meeting:

 #action Use tilde and caret in version field (+1:6, 0:0, -1:0)

Thanks for this, merging!

Pull-Request has been merged by ngompa

2 years ago

I'm 99% sure there's no difference between '_' and '.' ... rpm only cares about ASCII alphanumerics, '~' and '^' ... anything else is the same.

I stand corrected. So yeah, in principle we could use _ instead of . as a replacement character. I would argue that a dot still looks better, but technically the result seems to be same.