This specification describes orderable and non-orderable product version strings for use in an Apollo Product Spec manifest.
Orderable version strings fall into one of four version types as defined by a category (release or release candidate) and whether it is a snapshot version or not (snapshot versions contain a commit hash at the end), the cross-section of which produces the following:
Copied!1 2 3 4 5 6 7
Version Type Example Format ------------ ------- ------ Release 1.0.0 ^[0-9]+\.[0-9]+\.[0-9]+$ Release Snapshot 1.0.0-1-gaaaaaaa ^[0-9]+\.[0-9]+\.[0-9]+-[0-9]+-g[a-f0-9]+$ Release candidate (rc) 1.0.0-rc1 ^[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+$ Release candidate (rc) snapshot 1.0.0-rc1-1-gaaaaaaa ^[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+-[0-9]+-g[a-f0-9]+$
In each example above, we define the "base" version as the major/minor/patch-version component. In this case, they are all the same, 1.0.0
. Each number in the version string must not exceed the maximum value of a 32-bit integer (2,147,483,647).
For any pair of orderable Product version strings, it is straightforward to define an order governing which of the product versions is newer and which one is older. The order provides guarantees that enable Apollo to:
[1.2.3, 2.0.0)
.For the four variants, the following numeric components identify a version. From left to right, the components are:
1.2.3
, 1=major, 2=minor, 3=patch)-rc3
) or a snapshot version (e.g. -5-gnm4s9ba
)-rc3-5-gnm4s9ba
).Intuitively, given the same base version, snapshot versions are bigger than non-snapshot versions, normal release versions are bigger than release candidate versions, and a normal release snapshot version is bigger than a release candidate of any kind.
The following top-down procedure determines whether v1 is bigger than v2, written v1 > v2
; comparisons like major(v1) > major(v2)
are by integer ordering (not lexicographic ordering):
major(v1) > major(v2)
, then v1 > v2
.minor(v1) > minor(v2)
, then v1 > v2
.patch(v1) > patch(v2)
, then v1 > v2
.v1 > v2
.v1 > v2
.snapshot(v1) > snapshot(v2)
, then v1 > v2
.rc(v1) > rc(v2)
, then v1 > v2
.rc()
number.v1 > v2
.rcSnapshot(v1) > rcSnapshot(v2)
, then v1 > v2
.Further, v1 is as big as v2, written v1 == v2
, iff neither v1 > v2
nor v2 > v1
. We write v1 >= v2
if v1 > v2
or v1 == v2
.
Examples, with each greater than all the previous:
1.0.0-rc1
1.0.0-rc2
1.0.0-rc2-4-gaaaaaaa
1.0.0-rc2-5-gccccccc
2.0.0
2.0.0-3-gaaaaaaa
2.0.0-4-gbbbbbbb
2.1.0-rc1
2.1.0
Examples of equality:
1.2.0 == 1.2.0
2.0.0-rc1 == 2.0.0-rc1
2.0.0-rc1-3-gaaaaaaa == 2.0.0-rc1-3-gbbbbbbb
2.0.0-5-gbbbbbbb == 2.0.0-5-gaaaaaaa1
Note that any two release and rc versions are equally big if they are syntactically equal. As the second example demonstrates, this does not hold for snapshot versions.
A version matcher is a specification of a set of release versions and defined by the regular expression:
Copied!1
`^((x\.x\.x)|([0-9]+\.x\.x)|([0-9]+\.[0-9]+\.x)|([0-9]+\.[0-9]+\.[0-9]+))$`
The serialized form of a version matcher is a string that matches this regular expression. For example, 1.x.x
, 2.0.x
, x.x.x
, and 1.2.3
are valid version matchers, whereas x.y.z
, x.0.0
, 0.x.3
, x.x.2
, 1.x
, and ^x\.[0-9]+\.[0-9]+$
are not. A matcher is said to match a release version if there are (independent) substitutions for x
that turn the matcher into the version. For example, 1.x.x
matches 1.0.0
and 1.2.3
, but it does not match 2.0.0
or 0.1.1
.
Version strings follow the non-orderable format if they match the follow regular expression:
Copied!1
^[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9-]+)?(\.dirty)?$
For example, 1.0.0.dirty
, 0.0.1-custom-description-42
, and 2.0.0-1-gaaaaaa.dirty
are valid but non-orderable version strings, whereas 5.0
, 1.1.2.3-foo
, 1.1.2.3
and 1.0.0-FOO
are not valid version strings under this spec.
There are no ordering guarantees for a pair of non-orderable versions, or between an orderable and a non-orderable version string.