33Pre-releasing is a very common pattern in the world of versioning. It is however
44one of the worst to take into account in a dependency system, and I highly
55recommend that if you can avoid introducing pre-releases in your package
6- manager, you should. In the context of pubgrub, pre-releases break two
7- fondamental properties of the solver.
6+ manager, you should.
87
9- 1 . Pre-releases act similar to continuous spaces.
10- 2 . Pre-releases break the mathematical properties of subsets in a space with
11- total order.
8+ In the context of pubgrub, pre-releases break the fundamental properties of the
9+ solver that there is or isn't a version between two versions "x" and "x+1", that
10+ there cannot be a version "(x+1).alpha.1" depending on whether an input version
11+ had a pre-release specifier.
1212
13- (1) Indeed, it is hard to answer what version comes after "1-alpha0". Is it
14- "1-alpha1", "1-beta0", "2"? In practice, we could say that the version that
15- comes after "1-alpha0" is "1-alpha0?" where the "?" character is chosen to be
16- the lowest character in the lexicographic order, but we clearly are on a stretch
17- here and it certainly isn't natural.
18-
19- (2) Pre-releases are often semantically linked to version constraints written by
13+ Pre-releases are often semantically linked to version constraints written by
2014humans, interpreted differently depending on context. For example, "2.0.0-beta"
21- is meant to exist previous to version "2.0.0". Yet, it is not supposed to be
22- contained in the set described by ` 1.0.0 <= v < 2.0.0 ` , and only within sets
23- where one of the bounds contains a pre-release marker such as
24- ` 2.0.0-alpha <= v < 2.0.0 ` . This poses a problem to the dependency solver
15+ is meant to exist previous to version "2.0.0". Yet, in many versioning schemes
16+ it is not supposed to be contained in the set described by ` 1.0.0 <= v < 2.0.0 ` ,
17+ and only within sets where one of the bounds contains a pre-release marker such
18+ as ` 2.0.0-alpha <= v < 2.0.0 ` . This poses a problem to the dependency solver
2519because of backtracking. Indeed, the PubGrub algorithm relies on knowledge
2620accumulated all along the propagation of the solver front. And this knowledge is
2721composed of facts, that are thus never removed even when backtracking happens.
@@ -33,12 +27,6 @@ return nothing even without checking if a pre-release exists in that range. And
3327this is one of the fundamental mechanisms of the algorithm, so we should not try
3428to alter it.
3529
36- Point (2) is probably the reason why some pubgrub implementations have issues
37- dealing with pre-releases when backtracking, as can be seen in [ an issue of the
38- dart implementation] [ dart-prerelease-issue ] .
39-
40- [ dart-prerelease-issue ] : https://github.com/dart-lang/pub/pull/3038
41-
4230## Playing again with packages?
4331
4432In the light of the "bucket" and "proxies" scheme we introduced in the section
@@ -63,18 +51,16 @@ version but not both.
6351
6452Another issue would be that the proxy and bucket scheme breaks strategies
6553depending on ordering of versions. Since we have two proxy versions, one
66- targetting the normal bucket, and one targetting the pre-release bucket, a
54+ targeting the normal bucket, and one targeting the pre-release bucket, a
6755strategy aiming at the newest versions will lean towards normal or pre-release
6856depending if the newest proxy version is the one for the normal or pre-release
6957bucket. Mitigating this issue seems complicated, but hopefully, we are also
7058exploring alternative API changes that could enable pre-releases.
7159
7260## Multi-dimensional ranges
7361
74- We are currently exploring new APIs where ` Range ` is transformed into a trait,
75- instead of a predefined struct with a single sequence of non-intersecting
76- intervals. For now, the new trait is called ` RangeSet ` and could be implemented
77- on structs with multiple dimensions for ranges.
62+ Building on top of the ` Ranges ` API, we can implement a custom ` VersionSet ` of
63+ multi-dimensional ranges:
7864
7965``` rust
8066pub struct DoubleRange <V1 : Version , V2 : Version > {
@@ -83,30 +69,24 @@ pub struct DoubleRange<V1: Version, V2: Version> {
8369}
8470```
8571
86- With multi-dimensional ranges we could match the semantics of version
87- constraints in ways that do not introduce alterations of the core of the
88- algorithm. For example, the constraint ` 2.0.0-alpha <= v < 2.0.0 ` could be
89- matched to:
72+ With multi-dimensional ranges we can match the semantics of version constraints
73+ in ways that do not introduce alterations of the core of the algorithm. For
74+ example, the constraint ` 2.0.0-alpha <= v < 2.0.0 ` can be matched to:
9075
9176``` rust
9277DoubleRange {
93- normal_range : Range :: none ,
94- prerelease_range : Range :: between (" 2.0.0-alpha" , " 2.0.0" ),
78+ normal_range : Ranges :: empty () ,
79+ prerelease_range : Ranges :: between (" 2.0.0-alpha" , " 2.0.0" ),
9580}
9681```
9782
98- And the constraint ` 2.0.0-alpha <= v < 2.1.0 ` would have the same
99- ` prerelease_range ` but would have ` 2.0.0 <= v < 2.1.0 ` for the normal range.
100- Those constraints could also be intrepreted differently since not all
101- pre-release systems work the same. But the important property is that this
102- enable a separation of the dimensions that do not behave consistently with
103- regard to the mathematical properties of the sets manipulated.
104-
105- All this is under ongoing experimentations, to try reaching a sweet spot
106- API-wise and performance-wise. If you are eager to experiment with all the
107- extensions and limitations mentionned in this section of the guide for your
108- dependency provider, don't hesitate to reach out to us in our [ zulip
109- stream] [ zulip ] or in [ GitHub issues] [ issues ] to let us know how it went!
83+ And the constraint ` 2.0.0-alpha <= v < 2.1.0 ` has the same ` prerelease_range `
84+ but has ` 2.0.0 <= v < 2.1.0 ` for the normal range. Those constraints could also
85+ be interpreted differently since not all pre-release systems work the same. But
86+ the important property is that this enables a separation of the dimensions that
87+ do not behave consistently with regard to the mathematical properties of the
88+ sets manipulated.
11089
111- [ zulip ] : https://rust-lang.zulipchat.com/#narrow/stream/260232-t-cargo.2FPubGrub
112- [ issues ] : https://github.com/pubgrub-rs/pubgrub/issues
90+ This strategy is successfully used by
91+ [ semver-pubgrub] ( https://github.com/pubgrub-rs/semver-pubgrub ) to model rust
92+ dependencies.
0 commit comments