/
version_constraint.rb
129 lines (104 loc) · 2.53 KB
/
version_constraint.rb
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