semver_dialects 2.0.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/semver_dialects/base_version.rb +79 -0
- data/lib/semver_dialects/boundary.rb +142 -0
- data/lib/semver_dialects/commands/check_version.rb +2 -5
- data/lib/semver_dialects/interval.rb +256 -0
- data/lib/semver_dialects/interval_parser.rb +60 -0
- data/lib/semver_dialects/interval_set.rb +121 -0
- data/lib/semver_dialects/interval_set_parser.rb +205 -0
- data/lib/semver_dialects/maven.rb +197 -0
- data/lib/semver_dialects/semantic_version.rb +294 -0
- data/lib/semver_dialects/semver2.rb +159 -0
- data/lib/semver_dialects/version.rb +1 -1
- data/lib/semver_dialects.rb +152 -63
- metadata +57 -12
- data/lib/semver_dialects/semantic_version/semantic_version.rb +0 -337
- data/lib/semver_dialects/semantic_version/version_cut.rb +0 -176
- data/lib/semver_dialects/semantic_version/version_interval.rb +0 -288
- data/lib/semver_dialects/semantic_version/version_parser.rb +0 -40
- data/lib/semver_dialects/semantic_version/version_range.rb +0 -191
- data/lib/semver_dialects/semantic_version/version_translator.rb +0 -172
@@ -1,337 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../../utils.rb'
|
4
|
-
|
5
|
-
class SemanticVersion
|
6
|
-
attr_reader :version_string, :prefix_delimiter, :prefix_segments, :suffix_segments, :segments
|
7
|
-
|
8
|
-
# String to build a regexp that matches a version.
|
9
|
-
#
|
10
|
-
# A version might start with a leading "v", then it must have a digit,
|
11
|
-
# then it might have any sequence made of alphanumerical characters,
|
12
|
-
# underscores, dots, dashes, and wildcards.
|
13
|
-
VERSION_PATTERN = "v?[0-9][a-zA-Z0-9_.*+-]*"
|
14
|
-
|
15
|
-
# Regexp for a string that only contains a single version string.
|
16
|
-
VERSION_ONLY_REGEXP = Regexp.new("\\A#{VERSION_PATTERN}\\z").freeze
|
17
|
-
|
18
|
-
def initialize(version_string, segments = nil)
|
19
|
-
unless VERSION_ONLY_REGEXP.match version_string
|
20
|
-
raise SemverDialects::InvalidVersionError, version_string
|
21
|
-
end
|
22
|
-
|
23
|
-
@version_string = version_string
|
24
|
-
@prefix_segments = []
|
25
|
-
@suffix_segments = []
|
26
|
-
@prefix_delimiter = 0
|
27
|
-
version, _ = version_string.delete_prefix('v').split('+')
|
28
|
-
if segments.nil?
|
29
|
-
@segments = split_version_string!(version)
|
30
|
-
else
|
31
|
-
@prefix_segments = segments
|
32
|
-
@prefix_delimiter = segments.size - 1
|
33
|
-
@segments = segments
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def split_version_string!(version_string)
|
38
|
-
delim_pattern = /[\.\-]/
|
39
|
-
split_array = version_string.split(delim_pattern).map {
|
40
|
-
|grp|
|
41
|
-
grp.split(/(\d+)/).reject { |cell| cell.nil? || cell.empty? }
|
42
|
-
}.flatten
|
43
|
-
|
44
|
-
# go as far to the right as possible considering numbers and placeholders
|
45
|
-
(0..split_array.size - 1).each do
|
46
|
-
|i|
|
47
|
-
if split_array[i].number? || split_array[i] == "X" || split_array[i] == "x"
|
48
|
-
@prefix_delimiter = i
|
49
|
-
else
|
50
|
-
break
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# remove redundant trailing zeros
|
55
|
-
@prefix_delimiter.downto(0).each do
|
56
|
-
|i|
|
57
|
-
if split_array[i] == "0"
|
58
|
-
split_array.delete_at(i)
|
59
|
-
@prefix_delimiter -= 1
|
60
|
-
else
|
61
|
-
break
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
@prefix_segments = split_array[0..@prefix_delimiter].map { |group_string| SemanticVersionSegment.new(group_string) } unless @prefix_delimiter < 0
|
66
|
-
if split_array.size - 1 >= @prefix_delimiter + 1
|
67
|
-
@suffix_segments = split_array[@prefix_delimiter + 1, split_array.size].map { |group_string| SemanticVersionSegment.new(group_string) }
|
68
|
-
end
|
69
|
-
|
70
|
-
@prefix_segments.clone().concat(@suffix_segments)
|
71
|
-
end
|
72
|
-
|
73
|
-
def _get_equalized_arrays_for(array_a, array_b)
|
74
|
-
first_array = array_a.clone()
|
75
|
-
second_array = array_b.clone()
|
76
|
-
if first_array.size < second_array.size
|
77
|
-
(second_array.size - first_array.size).times do
|
78
|
-
first_array << SemanticVersionSegment.new("0")
|
79
|
-
end
|
80
|
-
elsif first_array.size > second_array.size
|
81
|
-
(first_array.size - second_array.size).times do
|
82
|
-
second_array << SemanticVersionSegment.new("0")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
[first_array, second_array]
|
86
|
-
end
|
87
|
-
|
88
|
-
def get_equalized_arrays_for(semver_a, semver_b)
|
89
|
-
first_array_prefix = semver_a.prefix_segments.clone()
|
90
|
-
second_array_prefix = semver_b.prefix_segments.clone()
|
91
|
-
first_array_suffix = semver_a.suffix_segments.clone()
|
92
|
-
second_array_suffix = semver_b.suffix_segments.clone()
|
93
|
-
first_array_prefix, second_array_prefix = _get_equalized_arrays_for(first_array_prefix, second_array_prefix)
|
94
|
-
first_array_suffix, second_array_suffix = _get_equalized_arrays_for(first_array_suffix, second_array_suffix)
|
95
|
-
[first_array_prefix.concat(first_array_suffix), second_array_prefix.concat(second_array_suffix)]
|
96
|
-
end
|
97
|
-
|
98
|
-
def get_equalized_prefix_arrays_for(semver_a, semver_b)
|
99
|
-
first_array_prefix = semver_a.prefix_segments.clone()
|
100
|
-
second_array_prefix = semver_b.prefix_segments.clone()
|
101
|
-
first_array_prefix, second_array_prefix = _get_equalized_arrays_for(first_array_prefix, second_array_prefix)
|
102
|
-
[first_array_prefix, second_array_prefix]
|
103
|
-
end
|
104
|
-
|
105
|
-
def <(other_semver)
|
106
|
-
self_array, other_array = get_equalized_arrays_for(self, other_semver)
|
107
|
-
(0..self_array.size - 1).each {
|
108
|
-
|i|
|
109
|
-
if self_array[i] < other_array[i]
|
110
|
-
return true
|
111
|
-
elsif self_array[i] > other_array[i]
|
112
|
-
return false
|
113
|
-
end
|
114
|
-
}
|
115
|
-
false
|
116
|
-
end
|
117
|
-
|
118
|
-
def is_zero?
|
119
|
-
@prefix_segments.empty? || @prefix_segments.all? { |segment| segment.is_zero? }
|
120
|
-
end
|
121
|
-
|
122
|
-
def pre_release?
|
123
|
-
@suffix_segments.any?(&:is_pre_release)
|
124
|
-
end
|
125
|
-
|
126
|
-
def post_release?
|
127
|
-
@suffix_segments.any?(&:is_post_release)
|
128
|
-
end
|
129
|
-
|
130
|
-
def >(other_semver)
|
131
|
-
self_array, other_array = get_equalized_arrays_for(self, other_semver)
|
132
|
-
(0..self_array.size - 1).each {
|
133
|
-
|i|
|
134
|
-
if self_array[i] > other_array[i]
|
135
|
-
return true
|
136
|
-
elsif self_array[i] < other_array[i]
|
137
|
-
return false
|
138
|
-
end
|
139
|
-
}
|
140
|
-
false
|
141
|
-
end
|
142
|
-
|
143
|
-
def >=(other_semver)
|
144
|
-
self == other_semver || self > other_semver || self == other_semver
|
145
|
-
end
|
146
|
-
|
147
|
-
def <=(other_semver)
|
148
|
-
self == other_semver || self < other_semver
|
149
|
-
end
|
150
|
-
|
151
|
-
def ==(other_semver)
|
152
|
-
segments_a = []
|
153
|
-
segments_b = []
|
154
|
-
|
155
|
-
segments_a += other_semver.segments
|
156
|
-
segments_b += @segments
|
157
|
-
|
158
|
-
if other_semver.segments.size < @segments.size
|
159
|
-
(@segments.size - other_semver.segments.size).times {|_| segments_a << SemanticVersionSegment.new("0")}
|
160
|
-
elsif other_semver.segments.size > @segments.size
|
161
|
-
(other_semver.segments.size - @segments.size).times {|_| segments_b << SemanticVersionSegment.new("0") }
|
162
|
-
end
|
163
|
-
|
164
|
-
(0..segments_a.size - 1).each {
|
165
|
-
|i|
|
166
|
-
if segments_a[i] != segments_b[i]
|
167
|
-
return false
|
168
|
-
end
|
169
|
-
}
|
170
|
-
true
|
171
|
-
end
|
172
|
-
|
173
|
-
def !=(other_semver)
|
174
|
-
return !(self == other_semver)
|
175
|
-
end
|
176
|
-
|
177
|
-
def diff(other_semver, abs = true)
|
178
|
-
diffs = []
|
179
|
-
|
180
|
-
self_array, other_array = get_equalized_prefix_arrays_for(self, other_semver)
|
181
|
-
(0..self_array.size - 1).each {
|
182
|
-
|i|
|
183
|
-
# diff semantic groups
|
184
|
-
diffs << (self_array[i].diff(other_array[i], abs))
|
185
|
-
}
|
186
|
-
diffs
|
187
|
-
end
|
188
|
-
|
189
|
-
def to_normalized_s
|
190
|
-
@segments.map { |group| group.to_normalized_s }.join(":").to_s
|
191
|
-
end
|
192
|
-
|
193
|
-
def to_s
|
194
|
-
@segments.map { |group| group.to_s }.join(":").to_s
|
195
|
-
end
|
196
|
-
|
197
|
-
def minor
|
198
|
-
@prefix_segments.size >= 1 ? @prefix_segments[1].to_s : "0"
|
199
|
-
end
|
200
|
-
|
201
|
-
def major
|
202
|
-
@prefix_segments.size >= 2 ? @prefix_segments[0].to_s : "0"
|
203
|
-
end
|
204
|
-
|
205
|
-
def patch
|
206
|
-
@prefix_segments.size >= 3 ? @prefix_segments[2].to_s : "0"
|
207
|
-
end
|
208
|
-
|
209
|
-
def is_successor_of?(other_semver)
|
210
|
-
filtered_segments = self.diff(other_semver, false).reject { |i| i.to_i == 0 }
|
211
|
-
filtered_segments.size == 1 && filtered_segments.last.to_i == 1
|
212
|
-
end
|
213
|
-
|
214
|
-
def cross_total()
|
215
|
-
[self.major, self.minor, self.patch].reject { |i| i.empty? }.map { |i| i.to_i }.inject(0) { |sum, x| sum + x }
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
class SemanticVersionSegment
|
220
|
-
attr_accessor :normalized_group_string, :original_group_string, :is_post_release, :is_pre_release
|
221
|
-
|
222
|
-
@@group_suffixes = {
|
223
|
-
# pre-releases
|
224
|
-
"PRE" => -16,
|
225
|
-
"PREVIEW" => -16,
|
226
|
-
"DEV" => -15,
|
227
|
-
"A" => -14,
|
228
|
-
"ALPHA" => -13,
|
229
|
-
"B" => -12,
|
230
|
-
"BETA" => -12,
|
231
|
-
"RC" => -11,
|
232
|
-
"M" => -10,
|
233
|
-
|
234
|
-
"RELEASE" => 0,
|
235
|
-
"FINAL" => 0,
|
236
|
-
# PHP specific
|
237
|
-
"STABLE" => 0,
|
238
|
-
|
239
|
-
# post-releases
|
240
|
-
"SP" => 1,
|
241
|
-
}
|
242
|
-
|
243
|
-
def initialize(group_string)
|
244
|
-
@is_post_release = false
|
245
|
-
@is_pre_release = false
|
246
|
-
|
247
|
-
@version_string = group_string
|
248
|
-
@original_group_string = group_string
|
249
|
-
# use x as unique placeholder
|
250
|
-
group_string_ucase = group_string.to_s.gsub(/\*/, "x").upcase
|
251
|
-
|
252
|
-
if @@group_suffixes.key?(group_string_ucase)
|
253
|
-
value = @@group_suffixes[group_string_ucase]
|
254
|
-
@is_post_release = value > 0
|
255
|
-
@is_pre_release = value < 0
|
256
|
-
@normalized_group_string = @@group_suffixes[group_string_ucase].to_s
|
257
|
-
else
|
258
|
-
@normalized_group_string = group_string_ucase
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
def compare(semver_a, semver_b, ret_anr_bnonr, ret_anonr_bnr, comparator)
|
263
|
-
if semver_a.number? && semver_b.number?
|
264
|
-
semver_a.to_i.send(comparator, semver_b.to_i)
|
265
|
-
elsif semver_a.number? && !semver_b.number?
|
266
|
-
if semver_b == "X"
|
267
|
-
true
|
268
|
-
else
|
269
|
-
ret_anr_bnonr
|
270
|
-
end
|
271
|
-
elsif !semver_a.number? && semver_b.number?
|
272
|
-
if semver_a == "X"
|
273
|
-
true
|
274
|
-
else
|
275
|
-
ret_anonr_bnr
|
276
|
-
end
|
277
|
-
else # !semantic_version_b.group_string.is_number? && !semantic_version_agrous_string.is_number?
|
278
|
-
if semver_a == "X" || semver_b == "X"
|
279
|
-
true
|
280
|
-
else
|
281
|
-
semver_a.send(comparator, semver_b)
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def <(other_semver)
|
287
|
-
compare(self.normalized_group_string, other_semver.normalized_group_string, true, false, :<)
|
288
|
-
end
|
289
|
-
|
290
|
-
def >(other_semver)
|
291
|
-
compare(self.normalized_group_string, other_semver.normalized_group_string, false, true, :>)
|
292
|
-
end
|
293
|
-
|
294
|
-
def >=(other_semver)
|
295
|
-
self == other_semver || compare(self.normalized_group_string, other_semver.normalized_group_string, false, true, :>)
|
296
|
-
end
|
297
|
-
|
298
|
-
def <=(other_semver)
|
299
|
-
self == other_semver || compare(self.normalized_group_string, other_semver.normalized_group_string, true, false, :<)
|
300
|
-
end
|
301
|
-
|
302
|
-
def ==(other_semver)
|
303
|
-
self.normalized_group_string == other_semver.normalized_group_string
|
304
|
-
end
|
305
|
-
|
306
|
-
def !=(other_semver)
|
307
|
-
return !(self == other_semver)
|
308
|
-
end
|
309
|
-
|
310
|
-
def to_normalized_s
|
311
|
-
@normalized_group_string
|
312
|
-
end
|
313
|
-
|
314
|
-
def to_s
|
315
|
-
@version_string
|
316
|
-
end
|
317
|
-
|
318
|
-
def is_number?
|
319
|
-
self.normalized_group_string.number?
|
320
|
-
end
|
321
|
-
|
322
|
-
def is_zero?
|
323
|
-
is_number? ? self.normalized_group_string.to_i == 0 : false
|
324
|
-
end
|
325
|
-
|
326
|
-
def diff(other_semver, abs = true)
|
327
|
-
|
328
|
-
if other_semver.normalized_group_string == "X" || self.normalized_group_string == "X"
|
329
|
-
"0"
|
330
|
-
elsif self.normalized_group_string.number? && other_semver.normalized_group_string.number?
|
331
|
-
ret = self.normalized_group_string.to_i - other_semver.normalized_group_string.to_i
|
332
|
-
(abs && ret < 0) ? -ret : ret
|
333
|
-
else
|
334
|
-
nil
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
@@ -1,176 +0,0 @@
|
|
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
|