semver_dialects 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,176 @@
1
+ require_relative "semantic_version"
2
+
3
+ class VersionCut
4
+ attr_accessor :semver, :value
5
+
6
+ def initialize(value, segments = nil)
7
+ @value = value.to_s
8
+ if segments.nil?
9
+ @semver = SemanticVersion.new(@value)
10
+ else
11
+ @semver = SemanticVersion.new(@value, segments)
12
+ end
13
+ end
14
+
15
+ def to_s
16
+ @value.to_s
17
+ end
18
+
19
+ def diff(other_cut, abs = true)
20
+ if other_cut.instance_of?(BelowAll)
21
+ AboveAll.new()
22
+ elsif other_cut.instance_of?(AboveAll)
23
+ BelowAll.new()
24
+ else
25
+ diff = self.semver.diff(other_cut.semver, abs)
26
+ if diff.nil?
27
+ EmptyInterval.new()
28
+ else
29
+ VersionCut.new(diff.join("."), diff)
30
+ end
31
+ end
32
+ end
33
+
34
+ def is_successor_of?(other_cut)
35
+ return true if other_cut.instance_of?(BelowAll)
36
+ return false if other_cut.instance_of?(AboveAll)
37
+
38
+ self.semver.is_successor_of?(other_cut.semver)
39
+ end
40
+
41
+ def <(other_cut)
42
+ other_cut.instance_of?(BelowAll) ? false : other_cut.instance_of?(AboveAll) ? true : @semver < other_cut.semver
43
+ end
44
+
45
+ def >(other_cut)
46
+ other_cut.instance_of?(BelowAll) ? true : other_cut.instance_of?(AboveAll) ? false : @semver > other_cut.semver
47
+ end
48
+
49
+ def <=(other_cut)
50
+ self < other_cut || self == other_cut
51
+ end
52
+
53
+ def >=(other_cut)
54
+ self > other_cut || self == other_cut
55
+ end
56
+
57
+ def ==(other_cut)
58
+ # self cannot be BelowAll or AboveAll
59
+ if other_cut.instance_of?(BelowAll) || other_cut.instance_of?(AboveAll)
60
+ false
61
+ else
62
+ @semver == other_cut.semver
63
+ end
64
+ end
65
+
66
+ def !=(other_cut)
67
+ # self cannot be BelowAll or AboveAll
68
+ if other_cut.instance_of?(BelowAll) || other_cut.instance_of?(AboveAll)
69
+ false
70
+ else
71
+ @semver != other_cut.semver
72
+ end
73
+ end
74
+
75
+ def is_initial_version?
76
+ @semver.is_zero?
77
+ end
78
+
79
+ def major
80
+ @semver.major
81
+ end
82
+
83
+ def minor
84
+ @semver.minor
85
+ end
86
+
87
+ def patch
88
+ @semver.patch
89
+ end
90
+
91
+ def cross_total
92
+ [minor, major, patch].reject { |i| i.empty? }.map { |i| i.to_i }.inject(0) { |sum, x| sum + x }
93
+ end
94
+ end
95
+
96
+ class BelowAll < VersionCut
97
+ def initialize()
98
+ end
99
+
100
+ def to_s
101
+ "-inf"
102
+ end
103
+
104
+ def is_initial_version?
105
+ false
106
+ end
107
+
108
+ def <(other_cut)
109
+ other_cut.instance_of?(BelowAll) ? false : true
110
+ end
111
+
112
+ def >(other_cut)
113
+ false
114
+ end
115
+
116
+ def <=(other_cut)
117
+ self < other_cut || self == other_cut
118
+ end
119
+
120
+ def >=(other_cut)
121
+ self > other_cut || self == other_cut
122
+ end
123
+
124
+ def ==(other_cut)
125
+ (other_cut.instance_of? BelowAll) ? true : false
126
+ end
127
+
128
+ def !=(other_cut)
129
+ !(self == other_cut)
130
+ end
131
+
132
+ def is_successor_of?(other_cut)
133
+ false
134
+ end
135
+ end
136
+
137
+ class AboveAll < VersionCut
138
+ def initialize()
139
+ end
140
+
141
+ def to_s
142
+ "+inf"
143
+ end
144
+
145
+ def is_initial_version?
146
+ false
147
+ end
148
+
149
+ def <(other_cut)
150
+ false
151
+ end
152
+
153
+ def >(other_cut)
154
+ other_cut.instance_of?(AboveAll) ? false : true
155
+ end
156
+
157
+ def <=(other_cut)
158
+ self < other_cut || self == other_cut
159
+ end
160
+
161
+ def >=(other_cut)
162
+ self > other_cut || self == other_cut
163
+ end
164
+
165
+ def ==(other_cut)
166
+ (other_cut.instance_of? AboveAll) ? true : false
167
+ end
168
+
169
+ def !=(other_cut)
170
+ !(self == other_cut)
171
+ end
172
+
173
+ def is_successor_of?(other_cut)
174
+ !other_cut.instance_of?(AboveAll)
175
+ end
176
+ end
@@ -0,0 +1,286 @@
1
+ module IntervalType
2
+ UNKNOWN = 0
3
+ LEFT_OPEN = 1
4
+ LEFT_CLOSED = 2
5
+ RIGHT_OPEN = 4
6
+ RIGHT_CLOSED = 8
7
+ end
8
+
9
+ class VersionInterval
10
+ attr_accessor :type, :start_cut, :end_cut
11
+
12
+ def initialize(type, start_cut, end_cut)
13
+ @type = type
14
+ @start_cut = start_cut
15
+ @end_cut = end_cut
16
+ end
17
+
18
+ def intersect(other_interval)
19
+ # this look odd -- we have to use it here though, because it may be that placeholders are present inside
20
+ # the version for which > and < would yield true
21
+ return EmptyInterval.new if !(@start_cut <= other_interval.end_cut) || !(other_interval.start_cut <= @end_cut)
22
+
23
+ start_cut_new = max(@start_cut, other_interval.start_cut)
24
+ end_cut_new = min(@end_cut, other_interval.end_cut)
25
+
26
+ # compute the boundaries for the intersection
27
+ type = compute_intersection_boundary(self, other_interval, start_cut_new, end_cut_new)
28
+ interval = VersionInterval.new(type, start_cut_new, end_cut_new)
29
+ half_open = !(interval.bit_set?(IntervalType::RIGHT_CLOSED) && interval.bit_set?(IntervalType::LEFT_CLOSED))
30
+
31
+ interval.singleton? && half_open ? EmptyInterval.new : interval
32
+ end
33
+
34
+ def union(other_interval)
35
+ return EmptyInterval.new if self.intersect(other_interval).instance_of?(EmptyInterval)
36
+
37
+ start_cut_new = min(@start_cut, other_interval.start_cut)
38
+ end_cut_new = max(@end_cut, other_interval.end_cut)
39
+
40
+ # compute the boundaries for the union
41
+ type = compute_union_boundary(self, other_interval, start_cut_new, end_cut_new)
42
+ VersionInterval.new(type, start_cut_new, end_cut_new)
43
+ end
44
+
45
+ def collapse(other_interval)
46
+ return EmptyInterval.new if self.intersect(other_interval).instance_of?(EmptyInterval)
47
+
48
+ frame = [@start_cut, other_interval.start_cut, @end_cut, other_interval.end_cut].reject { |cut| special(cut) }
49
+ min_cut = frame.reduce { |smallest, current| smallest < current ? smallest : current }
50
+ max_cut = frame.reduce { |biggest, current| biggest > current ? biggest : current }
51
+
52
+ # compute the boundaries for the union
53
+ type = compute_union_boundary(self, other_interval, min_cut, max_cut)
54
+ VersionInterval.new(type, min_cut, max_cut)
55
+ end
56
+
57
+ def special(cut)
58
+ cut.instance_of?(AboveAll) || cut.instance_of?(BelowAll)
59
+ end
60
+
61
+ def to_s
62
+ s = ""
63
+ s += bit_set?(IntervalType::LEFT_CLOSED) ? "[" : ""
64
+ s += bit_set?(IntervalType::LEFT_OPEN) ? "(" : ""
65
+ s += [@start_cut, @end_cut].join(",")
66
+ s += bit_set?(IntervalType::RIGHT_CLOSED) ? "]" : ""
67
+ s += bit_set?(IntervalType::RIGHT_OPEN) ? ")" : ""
68
+ s
69
+ end
70
+
71
+ # this function returns a human-readable descriptions of the version strings
72
+ def to_description_s
73
+ s = ""
74
+ if self.distinct?
75
+ s = "version #{@start_cut.to_s}"
76
+ elsif self.universal?
77
+ s = "all versions "
78
+ else
79
+ s = "all versions "
80
+ s += start_cut.instance_of?(BelowAll) ? "" : bit_set?(IntervalType::LEFT_OPEN) ? "after #{@start_cut.to_s} " : bit_set?(IntervalType::LEFT_CLOSED) ? "starting from #{@start_cut.to_s} " : ""
81
+ s += end_cut.instance_of?(AboveAll) ? "" : bit_set?(IntervalType::RIGHT_OPEN) ? "before #{@end_cut.to_s}" : bit_set?(IntervalType::RIGHT_CLOSED) ? "up to #{@end_cut.to_s}" : ""
82
+ end
83
+ s.strip
84
+ end
85
+
86
+ def to_nuget_s
87
+ to_maven_s
88
+ end
89
+
90
+ def to_maven_s
91
+ s = ""
92
+ # special case -- distinct version
93
+ if self.distinct?
94
+ s += "[#{@start_cut.to_s}]"
95
+ else
96
+ s += start_cut.instance_of?(BelowAll) ? "(," : bit_set?(IntervalType::LEFT_OPEN) ? "[#{@start_cut.to_s}," : bit_set?(IntervalType::LEFT_CLOSED) ? "[#{@start_cut.to_s}," : ""
97
+ s += end_cut.instance_of?(AboveAll) ? ")" : bit_set?(IntervalType::RIGHT_OPEN) ? "#{@end_cut.to_s})" : bit_set?(IntervalType::RIGHT_CLOSED) ? "#{@end_cut.to_s}]" : ""
98
+ end
99
+ s
100
+ end
101
+
102
+ def distinct?
103
+ bit_set?(IntervalType::LEFT_CLOSED) && bit_set?(IntervalType::RIGHT_CLOSED) && @start_cut == @end_cut
104
+ end
105
+
106
+ def subsumes?(other)
107
+ @start_cut <= other.start_cut && @end_cut >= other.end_cut
108
+ end
109
+
110
+ def universal?
111
+ (bit_set?(IntervalType::LEFT_OPEN) && bit_set?(IntervalType::RIGHT_OPEN) && @start_cut.instance_of?(BelowAll) && @end_cut.instance_of?(AboveAll)) || @start_cut.is_initial_version? && @end_cut.instance_of?(AboveAll)
112
+ end
113
+
114
+ def to_gem_s
115
+ get_canoncial_s
116
+ end
117
+
118
+ def to_ruby_s
119
+ get_canoncial_s
120
+ end
121
+
122
+ def to_npm_s
123
+ get_canoncial_s
124
+ end
125
+
126
+ def to_conan_s
127
+ get_canoncial_s
128
+ end
129
+
130
+ def to_go_s
131
+ get_canoncial_s
132
+ end
133
+
134
+ def to_pypi_s
135
+ get_canoncial_s(',', '==')
136
+ end
137
+
138
+ def to_packagist_s
139
+ get_canoncial_s(',')
140
+ end
141
+
142
+ def empty?
143
+ self.instance_of?(EmptyInterval)
144
+ end
145
+
146
+ def singleton?
147
+ @start_cut == @end_cut && @start_cut.value == @end_cut.value
148
+ end
149
+
150
+ def diff(other_interval, abs = true)
151
+ if self.distinct? && other_interval.distinct?
152
+ self.start_cut.diff(other_interval.start_cut, abs)
153
+ else
154
+ EmptyInterval.new()
155
+ end
156
+ end
157
+
158
+ def joinable?(other_interval)
159
+ other_interval.start_cut.is_successor_of?(self.end_cut) || universal?
160
+ end
161
+
162
+ def join(other_interval)
163
+ if self.joinable?(other_interval)
164
+ _join(self, other_interval)
165
+ elsif other_interval.joinable?(self)
166
+ _join(other_interval, self)
167
+ else
168
+ EmptyInterval.new()
169
+ end
170
+ end
171
+
172
+ def cross_total
173
+ if distinct?
174
+ @start_cut.cross_total
175
+ else
176
+ @start_cut.cross_total + @end_cut.cross_total
177
+ end
178
+ end
179
+
180
+ def ==(other_interval)
181
+ @start_cut == other_interval.start_cut && @end_cut == other_interval.end_cut && @type == other_interval.type
182
+ end
183
+
184
+ # inverts the given version interval -- note that this function amy return two version intervals
185
+ # e.g., (2,10] -> (-inf, 2], (10, +inf)
186
+ # left right
187
+ def invert
188
+ intervals = []
189
+ left_type = bit_set?(IntervalType::LEFT_OPEN) ? IntervalType::RIGHT_CLOSED : IntervalType::RIGHT_OPEN
190
+ left_type = left_type | IntervalType::LEFT_OPEN
191
+ right_type = bit_set?(IntervalType::RIGHT_OPEN) ? IntervalType::LEFT_CLOSED : IntervalType::LEFT_OPEN
192
+ right_type = right_type | IntervalType::RIGHT_OPEN
193
+
194
+ intervals << VersionInterval.new(left_type, BelowAll.new, @start_cut) unless @start_cut.instance_of?(BelowAll)
195
+ intervals << VersionInterval.new(right_type, @end_cut, AboveAll.new) unless @end_cut.instance_of?(AboveAll)
196
+ intervals
197
+ end
198
+
199
+ def bit_set?(interval_type)
200
+ @type & interval_type != 0
201
+ end
202
+
203
+ protected
204
+
205
+ # computes the boundary type for union operation
206
+ def compute_union_boundary(interval_a, interval_b, start_cut_new, end_cut_new)
207
+ compute_boundary(interval_a, interval_b, start_cut_new, end_cut_new, IntervalType::LEFT_CLOSED, IntervalType::RIGHT_CLOSED)
208
+ end
209
+
210
+ def compute_intersection_boundary(interval_a, interval_b, start_cut_new, end_cut_new)
211
+ compute_boundary(interval_a, interval_b,start_cut_new, end_cut_new, IntervalType::LEFT_OPEN, IntervalType::RIGHT_OPEN)
212
+ end
213
+
214
+ def compute_boundary(interval_a, interval_b, start_cut_new, end_cut_new, left_check, right_check)
215
+ start_cut_a = interval_a.start_cut
216
+ end_cut_a = interval_a.end_cut
217
+ type_a = interval_a.type
218
+
219
+ start_cut_b = interval_b.start_cut
220
+ end_cut_b = interval_b.end_cut
221
+ type_b = interval_b.type
222
+
223
+ left_fill = left_check == IntervalType::LEFT_OPEN ? IntervalType::LEFT_CLOSED : IntervalType::LEFT_OPEN
224
+ right_fill = right_check == IntervalType::RIGHT_OPEN ? IntervalType::RIGHT_CLOSED : IntervalType::RIGHT_OPEN
225
+
226
+ # compute the boundaries for the union
227
+ if start_cut_b == start_cut_a && start_cut_b == start_cut_b
228
+ one_left_closed = left_type(type_a) == left_check || left_type(type_b) == left_check
229
+ left_type = one_left_closed ? left_check : left_fill
230
+ else
231
+ left_type = start_cut_new == start_cut_a ? left_type(type_a) : left_type(type_b)
232
+ end
233
+
234
+ if end_cut_b == end_cut_a && end_cut_b == end_cut_b
235
+ one_right_closed = right_type(type_a) == right_check || right_type(type_b) == right_check
236
+ right_type = one_right_closed ? right_check : right_fill
237
+ else
238
+ right_type = end_cut_new == end_cut_a ? right_type(type_a) : right_type(type_b)
239
+ end
240
+
241
+ left_type | right_type
242
+ end
243
+
244
+ def _join(first_interval, second_interval)
245
+ if first_interval.joinable?(second_interval)
246
+ VersionInterval.new(first_interval.type, first_interval.start_cut.dup, second_interval.end_cut.dup)
247
+ else
248
+ EmptyInterval.new()
249
+ end
250
+ end
251
+
252
+ def get_canoncial_s(delimiter = " ", eq = '=')
253
+ if self.distinct?
254
+ "#{eq}#{@start_cut.to_s}"
255
+ else
256
+ first = start_cut.instance_of?(BelowAll) ? "" : bit_set?(IntervalType::LEFT_OPEN) ? ">#{@start_cut.to_s}" : bit_set?(IntervalType::LEFT_CLOSED) ? ">=#{@start_cut.to_s}" : ""
257
+ second = end_cut.instance_of?(AboveAll) ? "" : bit_set?(IntervalType::RIGHT_OPEN) ? "<#{@end_cut.to_s}" : bit_set?(IntervalType::RIGHT_CLOSED) ? "<=#{@end_cut.to_s}" : ""
258
+ !first.empty? && !second.empty? ? "#{first}#{delimiter}#{second}" : first + second
259
+ end
260
+ end
261
+
262
+ def max(cut_a, cut_b)
263
+ cut_a > cut_b ? cut_a : cut_b
264
+ end
265
+
266
+ def min(cut_a, cut_b)
267
+ cut_a < cut_b ? cut_a : cut_b
268
+ end
269
+
270
+ def right_type(type)
271
+ (IntervalType::RIGHT_OPEN | IntervalType::RIGHT_CLOSED) & type
272
+ end
273
+
274
+ def left_type(type)
275
+ (IntervalType::LEFT_OPEN | IntervalType::LEFT_CLOSED) & type
276
+ end
277
+ end
278
+
279
+ class EmptyInterval < VersionInterval
280
+ def initialize()
281
+ end
282
+
283
+ def to_s
284
+ "empty"
285
+ end
286
+ end