Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support larger MAJOR version numbers #149

Merged
merged 3 commits into from Aug 30, 2023

Conversation

onethumb
Copy link
Contributor

@onethumb onethumb commented Feb 1, 2023

root@0c6964ad69d6:/var/project# COMPOSER_ROOT_VERSION=20230131.0.0 composer install

  [UnexpectedValueException]
  Invalid version string "20230131.0.0"

While we're at it, we may as well be future-proof (support & test YYYYMMDDhhmm and PHP_INT_MAX).

- We prefer to use CalVer + SemVer (YYYYMMDD as MAJOR) for versioning.
- Other software, like `npm`, supports this: https://github.com/npm/node-semver/blob/bdda212f4f6126a1b8821dc0731a17fdc2fc533f/classes/semver.js#L48
- Composer breaks with an invalid version string:

root@0c6964ad69d6:/var/project# COMPOSER_ROOT_VERSION=20230131.0.0 composer install

  [UnexpectedValueException]
  Invalid version string "20230131.0.0"
@@ -134,7 +134,7 @@ public function normalize($version, $fullVersion = null)
}

// match classical versioning
if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
if (preg_match('{^v?(\d{1,' . PHP_INT_MAX . '})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHP_INT_MAX on 64bit (9223372036854775807) is only 19 characters long so if anything it should look something like this IMO as that's the char length and not the max number:

Suggested change
if (preg_match('{^v?(\d{1,' . PHP_INT_MAX . '})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
if (preg_match('{^v?(\d{1,20})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {

The problem though is this is only meant to parse x.y.z versions <100000, and then below we have the code for datetime versions but which do already support many formats as you can see in the tests. I'm not entirely sure yet why your format isn't supported but I don't think this fix is appropriate as I believe it changes the behavior for existing formats.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point about value vs char length. Open to whatever works best... just would like to use YYYYMMDD.y.z :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If other versions can be of any size - can they really, does composer support it fully? - then this should be simply \d++ to be consistent.

@Seldaek
Copy link
Member

Seldaek commented Jul 20, 2023

Ok I took another look at this and fixed it to avoid causing any changes to existing parsed formats, because the problem is version_compare is quite picky (e.g. version_compare('202301310000.0.0.0', '202301310000.0.0', '=') is false because of one added .0 at the end, this is the reason we normalize versions)

The tests without any changes to VersionParser fail the following new formats which were not supported before:

UnexpectedValueException: Invalid version string "20230131.0.0"
UnexpectedValueException: Invalid version string "202301310000.0.0"
UnexpectedValueException: Invalid version string "20100102.1.0"
UnexpectedValueException: Invalid version string "20100102.0.3"
UnexpectedValueException: Invalid version string "2010-01-02-10-20-30.0.3"

And with the patch those 5 are now supported but no existing one changes.

So really all this does is allow date formats with <date>.x.y where as we previously only allowed <date> or <date>.x.

I think I can live with this patch now, as it appears harmless, but I'd still like confirmation from @naderman before merging.

@naderman
Copy link
Member

I think this does cause a BC break in version comparisons though?

Previously the version string "20230131" would have been normalized to "2023.01.31.0" but now it gets normalized to "20230131.0.0.0" which means that

  • before: "20230131" < "2023-02-01" normalized to "2023.01.31.0" < "2023.02.01.0"
  • after: "20230131" > "2023-02-01" normalized to "20230131.0.0.0" > "2023.02.01.0"

I don't know if this kind of comparison ever mattered to anyone in practice though as it would really just come up if you ever switched from major version date formats without separators to ones with separators or vice versa.

@naderman
Copy link
Member

Nevermind the above, the old code never inserted separators, just replaced existing separators with dots, so that issue doesn't exist. Looks all good to me then!

@Seldaek Seldaek merged commit ce46554 into composer:main Aug 30, 2023
15 checks passed
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.

None yet

4 participants