Closed lukewagner closed 1 year ago
After doing some more digging into semver constraints/ranges/comparators I want to point out a subtlety that wasn't obvious to me around matching against pre-release versions:
By a naive application of semver's precedence rules, the range >=1.0.0 <2.0.0
would match pre-release version 2.0.0-alpha.1
, which seems surprising at best. Cargo/NPM avoid this with a subtle rule:
If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will only be allowed to satisfy req if at least one comparator with the same major.minor.patch also has a prerelease tag.
- This means, for example (checking the
typescript
package with https://semver.npmjs.com/), for a pre-release version5.0.0-dev
:- these ranges do not match:
>=4.0.0 <6.0.0
,>=4.0.0-alpha <6.0.0-zeta
- these ranges do match:
>=5.0.0-alpha <6.0.0
,>=4.0.0 <5.0.0-zeta
- Another somewhat-surprising consequence of this rule is that
*
never matches any prerelease version
I'm not sure what action to take here beyond being aware of this in tooling implementations. Maybe it would be worthwhile to add a note along the lines of "interpretation of verrange
is not specified here, but you should do what cargo/npm do wrt pre-release versions".
@lann Good to know! I see I really didn't even say anything about how to interpret the version ranges, so I added a paragraph on semver here.
Looks like no disagreement on the PR, so almost ready to merge. However, one more important use case came up recently in the context of registries (and, concretely, sharing component contents via OCI Registries) where one wants to name an implementation purely via its content hash without any additional URL or registry name (and where forcing a URL or registry name would just add a needless hoop to jump through). Thus, this commit adds a 5th implementation import case that has integrity
but no URL or registry name. This is a relatively small addition, so I'll wait for comments until the end of the week to merge.
This PR extends the binary/text grammar of import names to allow imports to name not just interfaces, but also implementations. There are a number of ways to refer to an implementation (absolute URL, relative URL, precisely-versioned hierarchical name, version-ranged hierarchical name), so to keep things explicit (and avoid ad hoc string analysis) and support good bindings generation in the relevant cases, these cases are enumerated explicitly. (In the future, other cases could be added to
importname
as they present themselves.) Putting this semantic intent directly in the component binary allows it to be reliably interpreted by a variety of tools and runtimes, allowing better tooling interoperability than if a separate file or custom section was used.This PR doesn't add the new import name cases to Wit yet because there are some interesting related workflow questions that I expect influence how this looks in Wit, suggesting this be a follow-up, once we agree on the target grammar/information. Also, the expectation is that, for the most part, folks won't need to write this in Wit, these implementation imports will be added late by the toolchain based on build-config files or import maps.
Unfortunately, there doesn't seem to be an "obvious" production we can simply reuse for describing version ranges, so, with a lot of help and ideas from @lann, a basic syntax is proposed built on semver that hopefully looks intuitive enough, but feedback welcome on this of course.