1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
|
- include::{partialsdir}/versions.adoc[]
- = Versioning Guidelines
- Fedora's package versioning scheme
- encompasses both the `+Version:+`
- and `+Release:+` tags, as well as `+Epoch:+`.
- The overriding goal is to provide sequences of packages
- which are treated as updates by RPM's version comparison algorithm
- while accommodating varied and often inconsistent upstream versioning schemes.
- The `+Version:+` field contains the upstream project version,
- and the `+Release:+` field specifies the downstream release number.
- == 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.
- Some 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.
- == `+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 never** be removed or decreased.
- == `+Release+` tag
- The `+Release:+` **should** be managed automatically using the `+%autorelease+` macro:
- [source, rpm-spec]
- ----
- Release: %autorelease
- ----
- As described in
- https://docs.pagure.org/fedora-infra.rpmautospec/autorelease.html[%autorelease documentation],
- the build machinery will
- replace the macro with the number of builds since the last commit that changed the `+Version+` field,
- suffixed with the `%{?dist}` tag.
- This means that a commit that changes `+Version+` automatically gets `Release: 1%{?dist}`,
- and commits after that get `Release: 2%{?dist}`, `Release: 3%{?dist}`, and so on.
- Alternatively, the `+Release:+` field **may** be updated manually.
- See xref:Versioning.adoc#traditional-versioning[Traditional versioning
- with part of the upstream version information in the release field].
- == 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 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+`)
- 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 project version verbatim in the `+Version:+` tag.
- Don't trim leading zeroes.
- == 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 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.
- This subsection describes how to modify the upstream project version to be suitable for the `+Version+` field.
- Use of `Release: +%autorelease+` remains unchanged.
- === 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.
- (When `%autorelease` is used, this happens automatically.)
- === 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 | Version tag | Explanation
- |1.0 |1.0 | The first release.
- |1.1 |1.1 | An upstream update.
- |1.2.1 |1.2.1 | Another upstream update. Extra levels of versioning are OK…
- |1.3 |1.3 | …they can come and go without problems.
- |===
- In this case the full N-V-R could be e.g. `pkg-1.2.1-1.fc{CURRENTVER}` (immediately after an update)
- or `pkg-1.2.1-5.fc{CURRENTVER}` (after downstream rebuilds with the same upstream version).
- [%header]
- |===
- |Upstream version | Version tag | Explanation
- | 5.2 | 5.2 | Upstream release.
- | 5.2a | 5.2a | 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 | Another patch release after 5.2 — this is not a beta.
- | 5.2b.1 | 5.2b.1 | Even this is OK as long as the sequence increases.
- | 5.3 | 5.3 | Another upstream release.
- |===
- In this case the full N-V-R could be e.g. `pkg-5.2b.1-1.fc{CURRENTVER}`.
- ==== Complex versioning with a reasonable upstream
- [%header]
- |===
- |Upstream version | Version tag | Notes
- | 1.0.0-rc1 | `+1.0.0~rc1+` | first prerelease
- | 1.0.0-rc2 | `+1.0.0~rc2+` | second prerelease
- | 1.0.0 | `+1.0.0+` | release
- | 1.0.1 | `+1.0.1+` | bugfix release
- | 1.0.1-security1 | `+pkg-1.0.1.security1+` | security bufix release
- |===
- In this case the full N-V-R could be e.g. `pkg-1.0.0~rc2-42.fc{CURRENTVER}` (if many rebuilds were done).
- ==== Complex versioning with non-sorting upstream post-release versions
- [%header]
- |===
- |Upstream version | Version tag | Notes
- | 1.1.0~BETA | `+1.1.0~BETA+` | this is a prerelease, first beta
- | 1.1.0~BETA1 | `+1.1.0~BETA1+` | this is a prerelease, second beta
- | 1.1.0~BETA2 | `+1.1.0~BETA2+` | this is a prerelease, third beta
- | 1.1.0~CR1 | `+1.1.0~CR1+` | this is a prerelease, candidate release 1
- | 1.1.0~CR2 | `+1.1.0~CR2+` | this is a prerelease, candidate release 2
- | 1.1.0-1% | `+1.1.0+` | final release
- | 1.1.0-GA1 | `+1.1.0.20201001.GA1+` | post release, GA1
- | 1.1.0-CP1 | `+1.1.0.20201011.CP1+` | post release, CP1, after GA1, does not sort properly
- | 1.1.0-CP2 | `+1.1.0.20201101.CP2+` | post release, CP2, after CP1
- | 1.1.0-SP1 | `+1.1.0.20210101.SP1+` | post release, SP1, after CP2
- | 1.1.0-SP1-CP1 | `+1.1.0.20210105.SP1_CP1+` | post release, SP1_CP1, after SP1
- |===
- In this case the full N-V-R could be e.g. `pkg-1.1.0.20210105.SP1_CP1-1.fc{CURRENTVER}`.
- ==== Complex versioning with a pre- and post-release snapshots
- [%header]
- |===
- |Upstream version | Version | Notes
- | 1.0.0-rc1 | `+1.0.0~rc1+` | First prerelease
- | 1.0.0-rc2 | `+1.0.0~rc2+` | Second prerelease
- | git commit `f00fabd` | `+1.0.0~rc2^20210101gf00fabd+` | Post-prerelease snapshot
- | 1.0.0 | `+1.0.0+` | A release
- | 1.0.1 | `+1.0.1+` | A bugfix release
- | git commit `bbbccc0` | `+1.0.1^20210203gbbbccc0+` or `+pkg-1.0.1^1.gbbbccc0+` | A snapshot
- | 1.0.1-security1 | `+1.0.1.security1+` | 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` | `+1.0.1.security1^20210301gabc0202+` or `+pkg-1.0.1.security1^1.gabc0202+` | Another snapshot
- |===
- In this case the full N-V-R could be e.g. `pkg-1.0.1.security1^20210301gabc0202-1.fc{CURRENTVER}`.
- [#traditional-versioning]
- == 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 xref:_handling_non_sorting_versions_with_tilde_dot_and_caret[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.
- In this method, `+%autorelease+` is not used, and the `Release` field must be managed manually.
- 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:
- * 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.
- Note that the dist tag is supplied by other portions of the system
- and may in some circumstances contain additional structure,
- 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
- as indicated above.
- === 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 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.
- === Rebuilds in older branches using `<minorbump>`
- In the situation described in <<Only an old branch needs a change>>,
- you **may** adjust the `+Release+` by appending a number *after* the dist tag,
- creating a E-V-R for F{CURRENTVER} that still compares lower than the one in F{NEXTVER}.
- Set `+<minorbump>+` to an in integer beginning with '1'
- and increase it 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.
- === Examples
- Examples of many possible versioning scenarios of traditional versioning
- are available from
- https://fedoraproject.org/wiki/Package_Versioning_Examples[Package Versioning Examples].
- == 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.
|