Version parsing improvements #643

Closed
Seldaek opened this Issue Apr 29, 2012 · 10 comments

Comments

Projects
None yet
6 participants
@Seldaek
Owner

Seldaek commented Apr 29, 2012

A few possible additions/changes:

  • Consider <x.y.z to be <x.y.z-dev. Because in 99% of the cases that's what the intent is. Could be overriden with <x.y.z-stable.
  • ~ for "any up to next semantic version bump" e.g. ~2.3 == >=2.3, <3.0-dev, ~2.3.4 == >=2.3.4, <2.4.0-dev
  • || for OR
  • equivalent for, (i.e. AND)
@sstok

This comment has been minimized.

Show comment Hide comment
@sstok

sstok May 24, 2012

Contributor

👍

Contributor

sstok commented May 24, 2012

👍

@ezzatron

This comment has been minimized.

Show comment Hide comment
@ezzatron

ezzatron Aug 3, 2012

Regarding the semantic version operator, it would make more sense if:

~2.3.4 == >=2.3.4, <3.0.0

instead of >=2.3.4, <2.4.0

The reason for this is that the second number (minor version) in a semver only implies backwards compatible changes. If I were using this operator, I'd want the latest and greatest version that retained backwards compatibility. Hence, in the above example, that means anything with a 2 as the first number (major version), something greater than 3 as the second number (minor version), and something greater than 4 as the third number (patch number).

ezzatron commented Aug 3, 2012

Regarding the semantic version operator, it would make more sense if:

~2.3.4 == >=2.3.4, <3.0.0

instead of >=2.3.4, <2.4.0

The reason for this is that the second number (minor version) in a semver only implies backwards compatible changes. If I were using this operator, I'd want the latest and greatest version that retained backwards compatibility. Hence, in the above example, that means anything with a 2 as the first number (major version), something greater than 3 as the second number (minor version), and something greater than 4 as the third number (patch number).

@Seldaek

This comment has been minimized.

Show comment Hide comment
@Seldaek

Seldaek Aug 9, 2012

Owner

I don't agree. Minor BCs are fairly common in minor versions. What you want could be achieved with ~2.3,>=2.3.4 if you like, or just write it explicitly.

Bundler does this too: rack ~> 1.2.1 (which means >= 1.2.1 and < 1.3.0)
And NPM as well:

"~1.2.3" = ">=1.2.3 <1.3.0"
"~1.2" = ">=1.2.0 <2.0.0"
"~1" = ">=1.0.0 <2.0.0"
Owner

Seldaek commented Aug 9, 2012

I don't agree. Minor BCs are fairly common in minor versions. What you want could be achieved with ~2.3,>=2.3.4 if you like, or just write it explicitly.

Bundler does this too: rack ~> 1.2.1 (which means >= 1.2.1 and < 1.3.0)
And NPM as well:

"~1.2.3" = ">=1.2.3 <1.3.0"
"~1.2" = ">=1.2.0 <2.0.0"
"~1" = ">=1.0.0 <2.0.0"
@jmalloc

This comment has been minimized.

Show comment Hide comment
@jmalloc

jmalloc Aug 10, 2012

Contributor

I guess it depends if this operator is to be considered for use when you know a project is adhering to semver.org's specification, or just a generic "best match" operator.

From semver.org ...

Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API. It MAY include minor and patch level changes. Patch and minor version MUST be reset to 0 when major version is incremented.

That above paragraph is the reason my implementation in PR #968 behaves the way @ezzatron describes.

I think it is preferable to avoid the need to use multiple constraints when a package is semver conformant.

The behaviour you describe above can also be achieved with multiple constraints (~2.3.4,<2.4.0), which I believe would be the less common use case when using semver.

I will concede that there is some value in keeping inline with other popular package management systems, could we be so bold as to implement two operators?

Contributor

jmalloc commented Aug 10, 2012

I guess it depends if this operator is to be considered for use when you know a project is adhering to semver.org's specification, or just a generic "best match" operator.

From semver.org ...

Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API. It MAY include minor and patch level changes. Patch and minor version MUST be reset to 0 when major version is incremented.

That above paragraph is the reason my implementation in PR #968 behaves the way @ezzatron describes.

I think it is preferable to avoid the need to use multiple constraints when a package is semver conformant.

The behaviour you describe above can also be achieved with multiple constraints (~2.3.4,<2.4.0), which I believe would be the less common use case when using semver.

I will concede that there is some value in keeping inline with other popular package management systems, could we be so bold as to implement two operators?

@Seldaek

This comment has been minimized.

Show comment Hide comment
@Seldaek

Seldaek Aug 10, 2012

Owner

Heh, well the thing is.. for big frameworks like symfony, and even smaller projects with relatively high profile, bumping the major version for every minor BC break is just not realistically feasible. There are other constraints (marketing & whatnot) that make it highly impractical.

To look at it from the other side, with a purely strict application of the semver principles, you should rarely require ~2.3.4 anyway. Mostly you want ~2.3 because 2.3.0 added some features you need, but then small bugfixes shouldn't be your problem, since anyway composer will install the latest available compatible version.

So IMO the npm/bundler way is good enough for semver, and makes more sense for people that don't follow it strictly. Consistency is another benefit as you mentioned. I wouldn't add another operator until we see that the ~2.3,>2.3.4 is such a large use case).

Owner

Seldaek commented Aug 10, 2012

Heh, well the thing is.. for big frameworks like symfony, and even smaller projects with relatively high profile, bumping the major version for every minor BC break is just not realistically feasible. There are other constraints (marketing & whatnot) that make it highly impractical.

To look at it from the other side, with a purely strict application of the semver principles, you should rarely require ~2.3.4 anyway. Mostly you want ~2.3 because 2.3.0 added some features you need, but then small bugfixes shouldn't be your problem, since anyway composer will install the latest available compatible version.

So IMO the npm/bundler way is good enough for semver, and makes more sense for people that don't follow it strictly. Consistency is another benefit as you mentioned. I wouldn't add another operator until we see that the ~2.3,>2.3.4 is such a large use case).

@ezzatron

This comment has been minimized.

Show comment Hide comment
@ezzatron

ezzatron Aug 10, 2012

I can see your point, although in that case the ~ operator probably shouldn't be called the 'semver' operator.

What would be really amazing, and would take Composer above and beyond other package management systems, is if there were a way to say in your composer.json that you were using semver for your version numbers. Then perhaps the 'semver' operator could warn you if you specify a semver constraint for a non-semver project. Perhaps "semver": true?

I also think it's worth saying that bumping a major version number for every BC break is perfectly feasible for any library-style project, despite the fact that many projects choose not to. The whole point of the semver spec is that arbitrary numbers like the '2' at the beginning of Symfony's version number are largely useless in a semantic sense (even though they may make some psychological sense).

But certainly, practically, you're right; in that not many developers are actually using semver.

I can see your point, although in that case the ~ operator probably shouldn't be called the 'semver' operator.

What would be really amazing, and would take Composer above and beyond other package management systems, is if there were a way to say in your composer.json that you were using semver for your version numbers. Then perhaps the 'semver' operator could warn you if you specify a semver constraint for a non-semver project. Perhaps "semver": true?

I also think it's worth saying that bumping a major version number for every BC break is perfectly feasible for any library-style project, despite the fact that many projects choose not to. The whole point of the semver spec is that arbitrary numbers like the '2' at the beginning of Symfony's version number are largely useless in a semantic sense (even though they may make some psychological sense).

But certainly, practically, you're right; in that not many developers are actually using semver.

@bobthecow

This comment has been minimized.

Show comment Hide comment
@bobthecow

bobthecow Sep 13, 2012

👍 for the ~ operator.

For consistency with prior art, we should use ~> 1.0.1 instead of ~1.0.1

👍 for the ~ operator.

For consistency with prior art, we should use ~> 1.0.1 instead of ~1.0.1

@naderman

This comment has been minimized.

Show comment Hide comment
@naderman

naderman Sep 13, 2012

Owner

@bobthecow as mentioned in the first post NPM uses ~1.0.1, so there is prior art for both

Owner

naderman commented Sep 13, 2012

@bobthecow as mentioned in the first post NPM uses ~1.0.1, so there is prior art for both

@Seldaek

This comment has been minimized.

Show comment Hide comment
@Seldaek

Seldaek Sep 14, 2012

Owner

Indeed, and I'd favor npm over bundler because our users are most likely
to interact with npm given it is potentially needed for frontend packages.

Owner

Seldaek commented Sep 14, 2012

Indeed, and I'd favor npm over bundler because our users are most likely
to interact with npm given it is potentially needed for frontend packages.

@bobthecow

This comment has been minimized.

Show comment Hide comment
@bobthecow

bobthecow Sep 14, 2012

Fair enough.

Fair enough.

simensen added a commit to simensen/composer that referenced this issue Oct 6, 2012

Semantic Version Parsing: ~version
Implemented `~` according to #643 and used the following versions
as a test case as defined by @Seldaek:

 * "~1.2.3.4" = ">=1.2.3.4 <1.2.4.0-dev"
 * "~1.2.3" = ">=1.2.3 <1.3.0-dev"
 * "~1.2" = ">=1.2.0 <2.0.0-dev"
 * "~1" = ">=1.0.0 <2.0.0-dev"

Refs #643

simensen added a commit to simensen/composer that referenced this issue Oct 8, 2012

Version Parsing: Consider <x.y.z to be <x.y.z-dev
> Consider `<x.y.z` to be `<x.y.z-dev.` Because in 99%
> of the cases that's what the intent is. Could be
> overriden with `<x.y.z-stable`.

- @Seldaek

refs #643

Seldaek added a commit to Seldaek/composer that referenced this issue Apr 27, 2013

@Seldaek Seldaek closed this May 4, 2013

digitalkaoz pushed a commit to digitalkaoz/composer that referenced this issue Nov 22, 2013

Semantic Version Parsing: ~version
Implemented `~` according to #643 and used the following versions
as a test case as defined by @Seldaek:

 * "~1.2.3.4" = ">=1.2.3.4 <1.2.4.0-dev"
 * "~1.2.3" = ">=1.2.3 <1.3.0-dev"
 * "~1.2" = ">=1.2.0 <2.0.0-dev"
 * "~1" = ">=1.0.0 <2.0.0-dev"

Refs #643

digitalkaoz pushed a commit to digitalkaoz/composer that referenced this issue Nov 22, 2013

Version Parsing: Consider <x.y.z to be <x.y.z-dev
> Consider `<x.y.z` to be `<x.y.z-dev.` Because in 99%
> of the cases that's what the intent is. Could be
> overriden with `<x.y.z-stable`.

- @Seldaek

refs #643

digitalkaoz pushed a commit to digitalkaoz/composer that referenced this issue Nov 22, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment