Skip to content

Commit 6b5b2e4

Browse files
authored
Use same priority for RC and RC snapshots (#1179)
1 parent 7bb23ee commit 6b5b2e4

4 files changed

Lines changed: 75 additions & 109 deletions

File tree

readme.md

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ This specification describes _orderable_ and _non-orderable_ product version str
3636
Orderable version strings fall into one of 4 version types as defined by a category (release or release candidate)
3737
and whether it is a snapshot version or not (snapshot versions contain a commit hash at the end), the cross section
3838
of which produces the following:
39+
3940
```
4041
Version Type Example Format
4142
------------ ------- ------
@@ -58,52 +59,52 @@ decisions about forward-vs-backwards product migrations. Further, it simplifies
5859
via version ranges; for instance, a product may declare that it is compatible with a second product with a version in
5960
`[1.2.3, 2.0.0)`.
6061

61-
For any two orderable versions, v1 and v2, we can define whether v1 is a *bigger* (equivalently, *later*, *newer*, etc)
62-
than v2. For the four variants, there can be up to three numeric components identifying a version. From left to right,
63-
they are: the usual notation of the base version (e.g., for `1.2.3`, 1=major, 2=minor, 3=patch), an optional second
62+
For any two orderable versions, `v1` and `v2`, we can define whether `v1` is a *larger* (equivalently, *later*, *newer*, etc)
63+
than `v2`. For the four variants, there can be up to three numeric components identifying a version. From left to right,
64+
they are: the usual notation of the base version (e.g., for `1.2.3`, 1=major, 2=minor, 3=patch), an optional first
6465
numeric component to identify a release candidate (e.g. `-rc3`) or a snapshot version (e.g. `-5-gnm4s9ba`), and finally
65-
an optional third numeric component to identify a release candidate snapshot version (e.g. `-rc3-5-gnm4s9ba`).
66+
an optional second numeric component to identify a release candidate snapshot version (e.g. `-rc3-5-gnm4s9ba`).
67+
68+
Intuitively, the version types define an ordering of versions for a given base version:
69+
- For a given base version, release snapshot versions are larger than release versions
70+
- For a given base version, release versions are larger than release candidate and release candidate snapshot versions
71+
- For a given base and rc version, release candidate snapshot versions are larger than release candidate versions
6672

67-
Intuitively, given the same base version, snapshot versions are bigger than non-snapshot versions, normal release
68-
versions are bigger than release candidate versions, and a normal release snapshot version is bigger than a release
69-
candidate of any kind. The following top-down procedure determines whether v1 is bigger than v2, written `v1 > v2`;
73+
The following top-down procedure determines whether `v1` is larger than `v2`, written `v1 > v2`;
7074
comparisons like `major(v1) > major(v2)` are by integer ordering (not lexicographic ordering):
7175

72-
- If `major(v1) > major(v2)`, then `v1 > v2`
73-
- If `minor(v1) > minor(v2)`, then `v1 > v2`
74-
- If `patch(v1) > patch(v2)`, then `v1 > v2`
75-
- From here on, let us assume that the base versions (major/minor/patch) are the same for v1 and v2
76-
- If v1 is a normal snapshot version and v2 is a normal release, then `v1 > v2`
77-
- If v1 is a normal release version and v2 is a rc version, then `v1 > v2`
78-
- If v1 and v2 are both normal snapshot versions and `snapshot(v1) > snapshot(v2)`, then `v1 > v2`
79-
- If v1 and v2 are both rc versions and `rc(v1) > rc(v2)`, then `v1 > v2`
80-
- From here on, let us assume that v1 and v2 are both rc versions of the same `rc()` number
81-
- If v1 is a snapshot rc version and v2 is a normal rc version, then `v1 > v2`
82-
- If v1 and v2 are both snapshot rc versions and `rcSnapshot(v1) > rcSnapshot(v2)`, then `v1 > v2`
83-
84-
Further, v1 is as big as v2, written `v1 == v2`, iff neither `v1 > v2` nor `v2 > v1`.
85-
We write `v1 >= v2` if `v1 > v2` or `v1 == v2`.
76+
- We know nothing about `v1` and `v2`:
77+
- If `major(v1) > major(v2)`, then `v1 > v2`
78+
- If `minor(v1) > minor(v2)`, then `v1 > v2`
79+
- If `patch(v1) > patch(v2)`, then `v1 > v2`
80+
- From here on, we know that `v1` and `v2` have the same base version:
81+
- If both `v1` and `v2` are both release snapshot versions and `snapshot(v1) > snapshot(v2)`, then `v1 > v2`
82+
- If `v1` is a release snapshot version and `v2` is not, then `v1 > v2`
83+
- If both `v1` and `v2` are both release versions, then `v1 == v2`
84+
- If `v1` is a release version and `v2` is not, then `v1 > v2`
85+
- From here on, we know that `v1` and `v2` have the same base version and are release candidate or release candidate snapshot version:
86+
- If `rc(v1) > rc(v2)`, then `v1 > v2`
87+
- If `v1` is a release candidate snapshot version and `v2` is not, then `v1 > v2`
88+
- If `rcSnapshot(v1) > rcSnapshot(v2)`, then `v1 > v2`
8689

8790
Examples, with each greater than all the previous:
88-
- RC: `1.0.0-rc1`
89-
- Bigger RC: `1.0.0-rc2`
90-
- RC Snapshot trumps RC: `1.0.0-rc2-4-gaaaaaaa`
91-
- Bigger RC Snapshot: `1.0.0-rc2-5-gccccccc`
92-
- Base trumps RC: `2.0.0`
93-
- Snapshot trumps all: `2.0.0-3-gaaaaaaa`
94-
- Bigger Snapshot: `2.0.0-4-gbbbbbbb`
95-
- Bigger Base: `2.1.0-rc1`
96-
- Release trumps RC: `2.1.0`
91+
- `1.0.0-rc1`
92+
- `1.0.0-rc1-1-gabcedf`
93+
- `1.0.0-rc1-2-gabcedf`
94+
- `1.0.0-rc2`
95+
- `1.0.0`
96+
- `1.0.0-1-gabcedf`
97+
- `1.0.0-2-gabcedf`
98+
- `1.0.1-rc1`
99+
- `1.0.1`
100+
- `1.1.0`
101+
- `2.0.0`
97102

98103
Examples of equality:
99-
- `1.2.0 == 1.2.0`
100-
- `2.0.0-rc1 == 2.0.0-rc1`
101-
- `2.0.0-rc1-3-gaaaaaaa == 2.0.0-rc1-3-gbbbbbbb`
102-
- `2.0.0-5-gbbbbbbb == 2.0.0-5-gaaaaaaa1`
103-
104-
Note that any two release and rc versions are equally big iff they are syntactically equal. As the second example
105-
demonstrates, this does not hold for snapshot versions.
106-
104+
- `1.0.0-rc1 == 1.0.0-rc1`
105+
- `1.0.0-rc1-1-gaaaaaaa == 1.0.0-rc1-1-gbbbbbbb`
106+
- `1.0.0 == 1.0.0`
107+
- `1.0.0-1-gaaaaaaa == 1.0.0-1-gbbbbbbb`
107108

108109
#### Version matchers
109110

sls-versions/src/main/java/com/palantir/sls/versions/CompactVersion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
* 20 bits: major
4343
* </code>
4444
*
45-
* <p><b>Note</b>: the correctness of the implementation of {@link #compareTo(CompactVersion)} depends on the
45+
* <p><b>Note</b>: The correctness of the implementation of {@link #compareTo(CompactVersion)} depends on the
4646
* constituent longs holding only positive values. This is partially accomplished by using less than the full number of
4747
* bits available, and thus by avoiding twos-complement representation issues when the highest bit in the long is set.
4848
*/

sls-versions/src/main/java/com/palantir/sls/versions/SlsVersionType.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
* {@link SlsVersion} objects.
2424
*/
2525
public enum SlsVersionType {
26-
RELEASE_SNAPSHOT(RegexParser.of("^([0-9]+)\\.([0-9]+)\\.([0-9]+)-([0-9]+)-g[a-f0-9]+$"), 4),
27-
RELEASE(ReleaseVersionParser.INSTANCE, 3),
28-
RELEASE_CANDIDATE_SNAPSHOT(RegexParser.of("^([0-9]+)\\.([0-9]+)\\.([0-9]+)-rc([0-9]+)-([0-9]+)-g[a-f0-9]+$"), 2),
26+
RELEASE_SNAPSHOT(RegexParser.of("^([0-9]+)\\.([0-9]+)\\.([0-9]+)-([0-9]+)-g[a-f0-9]+$"), 3),
27+
RELEASE(ReleaseVersionParser.INSTANCE, 2),
28+
RELEASE_CANDIDATE_SNAPSHOT(RegexParser.of("^([0-9]+)\\.([0-9]+)\\.([0-9]+)-rc([0-9]+)-([0-9]+)-g[a-f0-9]+$"), 1),
2929
RELEASE_CANDIDATE(RegexParser.of("^([0-9]+)\\.([0-9]+)\\.([0-9]+)-rc([0-9]+)$"), 1),
3030
NON_ORDERABLE(RegexParser.of("^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-[a-z0-9-]+)?(\\.dirty)?$"), 0);
3131

@@ -45,6 +45,12 @@ Parser getParser() {
4545
this.priority = priority;
4646
}
4747

48+
/**
49+
* Provides a first-level ordering of versions that have the same major/minor/patch versions. Version types with a
50+
* higher priority are greater than version types with a lower priority.
51+
*
52+
* <p><b>Note</b>: RELEASE_CANDIDATE and RELEASE_CANDIDATE_SNAPSHOT have the same priority.
53+
*/
4854
public int getPriority() {
4955
return this.priority;
5056
}

sls-versions/src/main/java/com/palantir/sls/versions/VersionComparator.java

Lines changed: 26 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -16,95 +16,54 @@
1616

1717
package com.palantir.sls.versions;
1818

19-
import static com.palantir.logsafe.Preconditions.checkArgument;
20-
21-
import com.palantir.logsafe.SafeArg;
2219
import java.util.Comparator;
23-
import java.util.OptionalInt;
2420

2521
/** Compares {@link OrderableSlsVersion}s by "newness", i.e., "1.4.0" is greater/newer/later than "1.2.1", etc.. */
2622
public enum VersionComparator implements Comparator<OrderableSlsVersion> {
2723
INSTANCE;
2824

2925
@Override
30-
public int compare(OrderableSlsVersion left, OrderableSlsVersion right) {
31-
if (left.getValue().equals(right.getValue())) {
26+
@SuppressWarnings("ImmutablesReferenceEquality")
27+
public int compare(OrderableSlsVersion version1, OrderableSlsVersion version2) {
28+
if (version1 == version2) {
3229
return 0;
3330
}
3431

35-
int mainVersionComparison = compareMainVersion(left, right);
36-
if (mainVersionComparison != 0) {
37-
return mainVersionComparison;
38-
}
39-
40-
if ((left.getType() == SlsVersionType.RELEASE) || (right.getType() == SlsVersionType.RELEASE)) {
41-
// Releases always compare correctly just by type now we know base version matches.
42-
return Integer.compare(left.getType().getPriority(), right.getType().getPriority());
43-
}
44-
45-
if ((left.getType() == SlsVersionType.RELEASE_SNAPSHOT)
46-
&& (right.getType() == SlsVersionType.RELEASE_SNAPSHOT)) {
47-
// If both are snapshots, compare snapshot number.
48-
return compareFirstSequenceVersions(left, right);
32+
int result = Integer.compare(version1.getMajorVersionNumber(), version2.getMajorVersionNumber());
33+
if (result != 0) {
34+
return result;
4935
}
5036

51-
if (left.getType() == SlsVersionType.RELEASE_SNAPSHOT) {
52-
// Snapshot is larger.
53-
return 1;
37+
result = Integer.compare(version1.getMinorVersionNumber(), version2.getMinorVersionNumber());
38+
if (result != 0) {
39+
return result;
5440
}
5541

56-
if (right.getType() == SlsVersionType.RELEASE_SNAPSHOT) {
57-
// Snapshot is larger.
58-
return -1;
42+
result = Integer.compare(version1.getPatchVersionNumber(), version2.getPatchVersionNumber());
43+
if (result != 0) {
44+
return result;
5945
}
6046

61-
return compareSuffix(left, right);
62-
}
63-
64-
private int compareMainVersion(OrderableSlsVersion left, OrderableSlsVersion right) {
65-
if (left.getMajorVersionNumber() != right.getMajorVersionNumber()) {
66-
return left.getMajorVersionNumber() > right.getMajorVersionNumber() ? 1 : -1;
47+
result = Integer.compare(
48+
version1.getType().getPriority(), version2.getType().getPriority());
49+
if (result != 0) {
50+
return result;
6751
}
6852

69-
if (left.getMinorVersionNumber() != right.getMinorVersionNumber()) {
70-
return left.getMinorVersionNumber() > right.getMinorVersionNumber() ? 1 : -1;
53+
result = Integer.compare(
54+
version1.firstSequenceVersionNumber().orElse(0),
55+
version2.firstSequenceVersionNumber().orElse(0));
56+
if (result != 0) {
57+
return result;
7158
}
7259

73-
if (left.getPatchVersionNumber() != right.getPatchVersionNumber()) {
74-
return left.getPatchVersionNumber() > right.getPatchVersionNumber() ? 1 : -1;
60+
result = Integer.compare(
61+
version1.secondSequenceVersionNumber().orElse(0),
62+
version2.secondSequenceVersionNumber().orElse(0));
63+
if (result != 0) {
64+
return result;
7565
}
7666

7767
return 0;
7868
}
79-
80-
private int compareSuffix(OrderableSlsVersion left, OrderableSlsVersion right) {
81-
// We know by this point that both are RCs or RC-snapshots.
82-
// Compare RC number first.
83-
int rcCompare = compareFirstSequenceVersions(left, right);
84-
if (rcCompare != 0) {
85-
return rcCompare;
86-
}
87-
88-
// RC number is the same, compare snapshot versions.
89-
// Substitute -1 if not present because snapshots are greater than non-snapshots.
90-
OptionalInt leftInt = left.secondSequenceVersionNumber();
91-
OptionalInt rightInt = right.secondSequenceVersionNumber();
92-
return Integer.compare(leftInt.orElse(-1), rightInt.orElse(-1));
93-
}
94-
95-
private int compareFirstSequenceVersions(OrderableSlsVersion left, OrderableSlsVersion right) {
96-
OptionalInt leftInt = left.firstSequenceVersionNumber();
97-
OptionalInt rightInt = right.firstSequenceVersionNumber();
98-
99-
checkArgument(
100-
leftInt.isPresent(),
101-
"Expected to find a first sequence number for version",
102-
SafeArg.of("version", left.getValue()));
103-
checkArgument(
104-
rightInt.isPresent(),
105-
"Expected to find a first sequence number for version",
106-
SafeArg.of("version", right.getValue()));
107-
108-
return Integer.compare(leftInt.getAsInt(), rightInt.getAsInt());
109-
}
11069
}

0 commit comments

Comments
 (0)