Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the Gemfile semantic versioning operator (~>) produce inconsistent results with one number?

The gemspec semantic versioning operator ~> (aka twiddle-wakka, aka pessimistic operator) allows a gem version to be constrained yet allow some upgrades.

I have often seen that it can be read as:

 "~> 3.1"   => "Any version 3.x, but at least 3.1"
 "~> 3.1.1" => "Any version 3.1.x, but at least 3.1.1"

But with one number, this rule breaks down:

 "~> 3"     => "Any version x, but at least 3"   *NOT TRUE!*
 "~> 3"     => "Any version 3.x"                 *True. But why?*

If I wanted "Any version 3.x", I could just use "~> 3.0", which is consistent. As it stands, this change of operation at one number is inconsistent and undocumented.

Moreover, if I wanted to say "Any version higher than or equal to 3" (so 3.x, 4.x etc...) I am tempted to use the ">=" operator, which we are told is evil.

Is there a reason for this behaviour?

EDIT:

I'm giving this to David for finding the culprit file in rubygems. There is a "feature" that silently expands "3" to "3.0" (Line 148 in version.rb: "single-digit versions are automatically extended with a zero to give a sensible result.")

I must say I disagree that the result is sensible, as it breaks the expected sequence, and prevents being able to say "Any version x, but at least 3" with that operator. Thus, we are forced onto >= which guides.rubygems.org warns us not to use. Anyway. Maybe this post will serve as the documentation I'd been looking for...

like image 389
hlascelles Avatar asked Jun 09 '14 14:06

hlascelles


1 Answers

By peeking into rubygems sources (esp. requirement.rb, version.rb) the pessimistic operator needs at least two versioning segments.

It also does make a sense. As ~> v.r is just a syntactic sugar for inequality

v.r <= current_version.current_release < (v+1).0

what would be the upper bound if there is only one version number ? Yep, ∞ (infinity), so there is no point why it should work. You can simply write it as >= v .

like image 87
David Unric Avatar answered Sep 20 '22 12:09

David Unric