Skip to content

Conversation

yoshi-monster
Copy link

@yoshi-monster yoshi-monster commented Oct 3, 2025

Extends the custom constraint/requirement parser to be able to deal with and and or version ranges as they are used by Elixir and Gleam, like >= 1.2.3 and < 2.0.0.

I first tried to use one of the discussed libraries, but they all had some differences that would've broken some existing tests; there's also some discussion on the previous attempts and the commented out tests in the other PR (#2785). If breaking those cases is acceptable then maybe switching to a library would be an option too. I did change all the places that called directly into ec_semver to go through the new rebar_semver module instead, so it should be easier to swap in the future.

This does look at the full constraint, but I figured since rebar has to loop over all available versions anyways trimming them out would be a lot of work for only a marginal performance improvement. Keeping them is likely safer and not that much slower. I've also added some tests for the version range matching, so hopefully everything stays in order.

I did not know which formatting you used here since I'm usually not an erlanger, my editor (Zed) would've done something completely different. I tried to match it manually, but if someone can point me to the formatter to use I can run that.

closes #2364

~ yoshie 💜

yoshie added 6 commits October 3, 2025 15:07
Instead of calling ec_semver directly, all version-related
calls go through this module; This makes it easy
to swap later when hex_core exposes an appropriate
replacement in the future.

It was not possible to use `verl` or other libraries
here, since rebars/erlang_commons parsing was
different in a number of edge cases:

- rebar allows version bounds with 2 components,
  like `< 1.0` or `== 1.2`.
- rebar allows approximate bounds with more than 3
  components, like `~> 1.5.6-rc.0`

To continue to support these, the new module also
uses ec_semver under the hood, but extends the custom
constraint parser to also support `and` and `or`
constraints used by Elixir or Gleam.

Constraints are modelled as a match function without
a pure data representation. This has to be assumed
to be an implementation detail that might change in
the future when a need arises.
Notable changes include:

- find_highest_matching_ now just calls resolve_version_ with a
  pessimistic constraint
- cmp* variants are gone
- is_valid get removed in favour of handling the error case after trying
  to parse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support all hex package version requirement formats

1 participant