Skip to content

Version range union containing prerelease versions does not work #55

@joshcooper

Description

@joshcooper

Describe the Bug

Semantic puppet version ranges do not handle prereleases correctly.

Expected Behavior

Given a version range '>=1.0.0 || >=2.0.0-rc0' I would expect both 1.0.0 and 2.0.0-rc0 to be included in the range. But that is not the observed behavior.

Steps to Reproduce

Apply the fix from #54

Run the following. I would expect true to be printed both times:

❯ cat test.rb 
require 'semantic_puppet'
range = SemanticPuppet::VersionRange.parse('>=1.0.0 || >=2.0.0-rc0')
puts range.include?(SemanticPuppet::Version.parse('1.0.0'))
puts range.include?(SemanticPuppet::Version.parse('2.0.0-rc0'))


❯ bundle exec ruby test.rb
true
false

SemanticPuppet generally follows the npm implementation of semver. Using that nomenclature, >=1.0.0 is a comparator set containing a single element. Same for >=2.0.0-rc0. And they are joined together using || to create a union. npm says https://github.com/npm/node-semver

A range is composed of one or more comparator sets, joined by ||. A version matches a range if and only if every comparator in at least one of the ||-separated comparator sets is satisfied by the version.

As a result, both 1.0.0 and 2.0.0-rc0 should be included in the range.

The bug is that SemanticPuppet attempts to merge ranges to reduce overlaps, for example >=1.0.0 || >=2.0.0 is redundant as the former includes the latter. So it attempts to merge the two ranges (comparator sets)

and drops the second range >=2.0.0 However, it shouldn't do that if the second range contains a prerelease >=2.0.0-rc0 This is because

If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will only be allowed to satisfy comparator sets if at least one comparator with the same [major, minor, patch] tuple also has a prerelease tag. ... prerelease versions frequently are updated very quickly, and contain many breaking changes that are (by the author's design) not yet fit for public consumption. Therefore, by default, they are excluded from range-matching semantics.

It also behaves inconsistently if the order of ranges is reversed >= 2.0.0-rc0 || >= 1.0.0

Environment

❯ bundle exec ruby -rsemantic_puppet -e "puts SemanticPuppet::VERSION"        
1.1.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions