summaryrefslogtreecommitdiff
path: root/lib/bundler/vendor/pub_grub/lib/pub_grub/version_constraint.rb
blob: b71f3eaf53b44f93c6c003b4202d4b14705b9ec8 (plain)
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
require_relative 'version_range'

module Bundler::PubGrub
  class VersionConstraint
    attr_reader :package, :range

    # @param package [Bundler::PubGrub::Package]
    # @param range [Bundler::PubGrub::VersionRange]
    def initialize(package, range: nil)
      @package = package
      @range = range
    end

    def hash
      package.hash ^ range.hash
    end

    def ==(other)
      package == other.package &&
        range == other.range
    end

    def eql?(other)
      package.eql?(other.package) &&
        range.eql?(other.range)
    end

    class << self
      def exact(package, version)
        range = VersionRange.new(min: version, max: version, include_min: true, include_max: true)
        new(package, range: range)
      end

      def any(package)
        new(package, range: VersionRange.any)
      end

      def empty(package)
        new(package, range: VersionRange.empty)
      end
    end

    def intersect(other)
      unless package == other.package
        raise ArgumentError, "Can only intersect between VersionConstraint of the same package"
      end

      self.class.new(package, range: range.intersect(other.range))
    end

    def union(other)
      unless package == other.package
        raise ArgumentError, "Can only intersect between VersionConstraint of the same package"
      end

      self.class.new(package, range: range.union(other.range))
    end

    def invert
      new_range = range.invert
      self.class.new(package, range: new_range)
    end

    def difference(other)
      intersect(other.invert)
    end

    def allows_all?(other)
      range.allows_all?(other.range)
    end

    def allows_any?(other)
      range.intersects?(other.range)
    end

    def subset?(other)
      other.allows_all?(self)
    end

    def overlap?(other)
      other.allows_any?(self)
    end

    def disjoint?(other)
      !overlap?(other)
    end

    def relation(other)
      if subset?(other)
        :subset
      elsif overlap?(other)
        :overlap
      else
        :disjoint
      end
    end

    def to_s(allow_every: false)
      if Package.root?(package)
        package.to_s
      elsif allow_every && any?
        "every version of #{package}"
      else
        "#{package} #{constraint_string}"
      end
    end

    def constraint_string
      if any?
        ">= 0"
      else
        range.to_s
      end
    end

    def empty?
      range.empty?
    end

    # Does this match every version of the package
    def any?
      range.any?
    end

    def inspect
      "#<#{self.class} #{self}>"
    end
  end
end