composer / semver

Semantic versioning utilities with the addition of version constraints parsing and checking.
MIT License
3.15k stars 76 forks source link

Add methods to constraints to retrieve the lower and upper boundaries #72

Closed naderman closed 4 years ago

naderman commented 4 years ago

A constraint should provide a way to retrieve its lower and upper boundaries.

For example ^5.1.3 should return 5.1.3.0 as the lower boundary and 5.99999.99999.99999 as the upper boundary. The exact number of 9 digits and number of version digits needs to match what Composer uses.

Need to review how suffixes like -dev1/0 or -pl99999 would need to be treated here.

alcohol commented 4 years ago

Should this be made part of the interface? Would this warrant a major version release then?

Seldaek commented 4 years ago

I guess strictly speaking yes, but I doubt there are many other implementations of these interfaces.. Anyway we can go for a major release, it doesn't hurt :)

Toflar commented 4 years ago

Gave it a first shot #75

Toflar commented 4 years ago

I fail to see how this can be implemented with reasonable amount of work. First of all, there's not just an upper and a lower bound for every constraint. E.g. the != or <> operator would cause two boundaries.

Now, from what I understood, the initial plan was to be able to compile all the required version_compare() calls to have fast checks at runtime. But I'm not sure this is even possble. Let's say you have installed two packages with the following respective requirements:

  1. "php": "<7.2 || >7.3"
  2. "php": "<7.1 || >7.2"

I know that these are nonsense constraints but I think you get the point. If there are disjunctive MultiConstraints, they cannot be simplified. So if you have 50 packages in your composer.lock and they all define some OR constraints, I think that will lead to quite a big number of version_compare() calls that are required.

Every OR MultiConstraint (disjunctive contraint) possibly causes yet another version_compare() call. I'm sure it could be optimized but it will be pretty complex...

Seldaek commented 4 years ago

The 1/2 above can be simplified down to <7.2 || >7.2 I guess seeing as >7.3 is included in >7.2 and <7.1 is included in <7.2 and then you possibly could see that this resolves to an infinite range for which no check is necessary. But indeed it might not be easy to achieve..

stof commented 4 years ago

https://github.com/Roave/SecurityAdvisoriesBuilder implemented lots of logic to simplify conflict rules written as a disjunctive constraint (one supported by composer). The case to solve here is even more complex, as we would have to simplify a constraint written as a conjunction of a series of disjunctions (and each of this disjunction being composed of conjunctions or operator-based rules). Boolean logic tells me that this case can be normalized to a disjunction (but that requires quite some work), which could then be simplified with similar logic.

Also, if we work with constraint objects directly, we might have to assume arbitrary nesting rather than only what can be represented in a composer constraint, which makes the problem even more complex.

Seldaek commented 4 years ago

Yup I think I'd aim more for a partial solution first, because 99% of php constraints are simple ^A || ^B or >=X, and that's the main use case for this stuff, so if we can handle this nicely it's a good start, as long as it fails explicitly when something can't be handled.

naderman commented 4 years ago

@Toflar This ticket was about finding an upper and a lower bound, not about finding an exact representation of the intervals. An actual exact version is what I made this ticket for: https://github.com/composer/semver/issues/71

We're not looking to do an exact match, just to limit the range. So if all we have is stuff like what Jordi said, then we can find out what the minimum and maximum supported version is, even though some specific versions in between may also not be supported. This is not about a perfect matcher, but just excluding some really wrong cases.

Toflar commented 4 years ago

I see. I'll give the boundaries thing another shot then and we'll see where it leads us to from there :)

aschempp commented 4 years ago

see https://github.com/composer/semver/pull/75