semver_dialects 2.0.2 → 3.0.0
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.
- 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
|