File: comparator.rb

package info (click to toggle)
ruby-semantic-range 3.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 100 kB
  • sloc: ruby: 731; makefile: 4
file content (71 lines) | stat: -rw-r--r-- 2,823 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module SemanticRange
  class Comparator
    attr_reader :semver, :operator, :value
    def initialize(comp, loose)
      comp = comp.value if comp.is_a?(Comparator)
      @loose = loose

      parse(comp)

      @value = @semver == ANY ? '' : @operator + @semver.version
    end

    def to_s
      @value
    end

    def test(version)
      return true if @semver == ANY
      version = Version.new(version, @loose) if version.is_a?(String)
      SemanticRange.cmp(version, @operator, @semver, loose: @loose)
    end

    def parse(comp)
      m = comp.match(@loose ? COMPARATORLOOSE : COMPARATOR)
      raise InvalidComparator.new(comp) unless m

      @operator = m[1]
      @operator = '' if @operator == '='

      @semver = !m[2] ? ANY : Version.new(m[2], loose: @loose)
    end

    def intersects?(comp, loose: false, platform: nil)
      comp = Comparator.new(comp, loose)

      if @operator == ''
        range_b = Range.new(comp.value, loose: loose, platform: platform)
        SemanticRange.satisfies?(@value, range_b, loose: loose, platform: platform)
      elsif comp.operator == ''
        range_a = Range.new(@value, loose: loose, platform: platform)
        SemanticRange.satisfies?(comp.semver, range_a, loose: loose, platform: platform)
      else
        same_direction_increasing      = (@operator == '>=' || @operator == '>') && (comp.operator == '>=' || comp.operator == '>')
        same_direction_decreasing      = (@operator == '<=' || @operator == '<') && (comp.operator == '<=' || comp.operator == '<')
        same_version                   = @semver.raw == comp.semver.raw
        different_directions_inclusive = (@operator == '>=' || @operator == '<=') && (comp.operator == '>=' || comp.operator == '<=')
        opposite_directions_lte        = SemanticRange.cmp(@semver, '<', comp.semver, loose: loose) &&
            ((@operator == '>=' || @operator == '>') && (comp.operator == '<=' || comp.operator == '<'))
        opposite_directions_gte        = SemanticRange.cmp(@semver, '>', comp.semver, loose: loose) &&
            ((@operator == '<=' || @operator == '<') && (comp.operator == '>=' || comp.operator == '>'))

        same_direction_increasing || same_direction_decreasing || (same_version && different_directions_inclusive) ||
            opposite_directions_lte || opposite_directions_gte
      end
    end

    def satisfies_range?(range, loose: false, platform: nil)
      range = Range.new(range, loose: loose, platform: platform)

      range.set.any? do |comparators|
        comparators.all? do |comparator|
          intersects?(comparator, loose: loose, platform: platform)
        end
      end
    end

    # Support for older non-inquisitive method versions
    alias_method :intersects, :intersects?
    alias_method :satisfies_range, :satisfies_range?
  end
end