semver_dialects 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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