semver_dialects 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/semver_dialects.rb +56 -0
- data/lib/semver_dialects/cli.rb +34 -0
- data/lib/semver_dialects/command.rb +122 -0
- data/lib/semver_dialects/commands/check_version.rb +35 -0
- data/lib/semver_dialects/semantic_version/semantic_version.rb +323 -0
- data/lib/semver_dialects/semantic_version/version_cut.rb +176 -0
- data/lib/semver_dialects/semantic_version/version_interval.rb +286 -0
- data/lib/semver_dialects/semantic_version/version_parser.rb +37 -0
- data/lib/semver_dialects/semantic_version/version_range.rb +191 -0
- data/lib/semver_dialects/semantic_version/version_translator.rb +172 -0
- data/lib/semver_dialects/version.rb +5 -0
- data/lib/utils.rb +41 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8b7d27d36822fd9137e04ea549b5b5db9304c24396d290fe9c5f543be9e15bcc
|
4
|
+
data.tar.gz: e7421f4c9b05ae145dc5913895eecf7a7f78d0adf22c161674354aa0449fee10
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e62253609623f4380235c1630a30840516b5ef9df3979bba3100d814358c74a8293912807f3ad0ffe9bc6c790d1e9be272165248af62a9dfe4d77f16df1d821f
|
7
|
+
data.tar.gz: 39230f2105ec31909f051ba193fa4c5e17783a33496ed861a8777c9ce66731d43b0a460a905411696f9ce5e651111e6448f51ae193f24d2951cad2ab43251629
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'semver_dialects/version'
|
4
|
+
require 'semver_dialects/semantic_version/version_translator'
|
5
|
+
require 'semver_dialects/semantic_version/version_parser'
|
6
|
+
require 'semver_dialects/semantic_version/version_range'
|
7
|
+
|
8
|
+
module SemverDialects
|
9
|
+
# Captures all errors that could be possibly raised
|
10
|
+
class Error < StandardError
|
11
|
+
def initialize(msg)
|
12
|
+
super(msg)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# A utiltity module that helps with version matching
|
17
|
+
module VersionChecker
|
18
|
+
def self.version_translate(typ, version_string)
|
19
|
+
case typ
|
20
|
+
when 'maven'
|
21
|
+
VersionTranslator.translate_maven(version_string)
|
22
|
+
when 'npm'
|
23
|
+
VersionTranslator.translate_npm(version_string)
|
24
|
+
when 'conan'
|
25
|
+
VersionTranslator.translate_conan(version_string)
|
26
|
+
when 'nuget'
|
27
|
+
VersionTranslator.translate_nuget(version_string)
|
28
|
+
when 'go'
|
29
|
+
VersionTranslator.translate_go(version_string)
|
30
|
+
when 'gem'
|
31
|
+
VersionTranslator.translate_gem(version_string)
|
32
|
+
when 'pypi'
|
33
|
+
VersionTranslator.translate_pypi(version_string)
|
34
|
+
when 'packagist'
|
35
|
+
VersionTranslator.translate_packagist(version_string)
|
36
|
+
else
|
37
|
+
raise SemverDialects::Error, 'unsupported package type'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.version_sat?(typ, raw_ver, raw_constraint)
|
42
|
+
version_constraint = version_translate(typ, raw_constraint)
|
43
|
+
version = VersionParser.parse('=' + raw_ver)
|
44
|
+
|
45
|
+
raise SemverDialects::Error, 'malformed constraint' if version_constraint.nil? || version_constraint.empty?
|
46
|
+
raise SemverDialects::Error, 'malformed constraint' if version.nil? || version.empty?
|
47
|
+
|
48
|
+
constraint = VersionRange.new
|
49
|
+
version_constraint.each do |version_interval_str|
|
50
|
+
constraint << VersionParser.parse(version_interval_str)
|
51
|
+
end
|
52
|
+
|
53
|
+
constraint.overlaps_with?(version)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module SemverDialects
|
6
|
+
# Handle the application command line parsing
|
7
|
+
# and the dispatch to various command objects
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
class CLI < Thor
|
11
|
+
# Error raised by this runner
|
12
|
+
Error = Class.new(StandardError)
|
13
|
+
|
14
|
+
desc 'version', 'semver_dialects version'
|
15
|
+
def version
|
16
|
+
require_relative 'version'
|
17
|
+
puts "v#{SemverDialects::VERSION}"
|
18
|
+
end
|
19
|
+
map %w[--version -v] => :version
|
20
|
+
|
21
|
+
desc 'check_version TYPE VERSION CONSTRAINT', 'Command description...'
|
22
|
+
method_option :help, aliases: '-h', type: :boolean,
|
23
|
+
desc: 'Display usage information'
|
24
|
+
def check_version(type, version, constraint)
|
25
|
+
if options[:help]
|
26
|
+
invoke :help, ['check_version']
|
27
|
+
else
|
28
|
+
require_relative 'commands/check_version'
|
29
|
+
ecode = SemverDialects::Commands::CheckVersion.new(type, version, constraint, options).execute
|
30
|
+
exit(ecode)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module SemverDialects
|
6
|
+
# A CLI command
|
7
|
+
class Command
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def_delegators :command, :run
|
11
|
+
|
12
|
+
# Execute this command
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
def execute(*)
|
16
|
+
raise(
|
17
|
+
NotImplementedError,
|
18
|
+
"#{self.class}##{__method__} must be implemented"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
# The external commands runner
|
23
|
+
#
|
24
|
+
# @see http://www.rubydoc.info/gems/tty-command
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
def command(**options)
|
28
|
+
require 'tty-command'
|
29
|
+
TTY::Command.new(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
# The cursor movement
|
33
|
+
#
|
34
|
+
# @see http://www.rubydoc.info/gems/tty-cursor
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
def cursor
|
38
|
+
require 'tty-cursor'
|
39
|
+
TTY::Cursor
|
40
|
+
end
|
41
|
+
|
42
|
+
# Open a file or text in the user's preferred editor
|
43
|
+
#
|
44
|
+
# @see http://www.rubydoc.info/gems/tty-editor
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def editor
|
48
|
+
require 'tty-editor'
|
49
|
+
TTY::Editor
|
50
|
+
end
|
51
|
+
|
52
|
+
# File manipulation utility methods
|
53
|
+
#
|
54
|
+
# @see http://www.rubydoc.info/gems/tty-file
|
55
|
+
#
|
56
|
+
# @api public
|
57
|
+
def generator
|
58
|
+
require 'tty-file'
|
59
|
+
TTY::File
|
60
|
+
end
|
61
|
+
|
62
|
+
# Terminal output paging
|
63
|
+
#
|
64
|
+
# @see http://www.rubydoc.info/gems/tty-pager
|
65
|
+
#
|
66
|
+
# @api public
|
67
|
+
def pager(**options)
|
68
|
+
require 'tty-pager'
|
69
|
+
TTY::Pager.new(options)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Terminal platform and OS properties
|
73
|
+
#
|
74
|
+
# @see http://www.rubydoc.info/gems/tty-pager
|
75
|
+
#
|
76
|
+
# @api public
|
77
|
+
def platform
|
78
|
+
require 'tty-platform'
|
79
|
+
TTY::Platform.new
|
80
|
+
end
|
81
|
+
|
82
|
+
# The interactive prompt
|
83
|
+
#
|
84
|
+
# @see http://www.rubydoc.info/gems/tty-prompt
|
85
|
+
#
|
86
|
+
# @api public
|
87
|
+
def prompt(**options)
|
88
|
+
require 'tty-prompt'
|
89
|
+
TTY::Prompt.new(options)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get terminal screen properties
|
93
|
+
#
|
94
|
+
# @see http://www.rubydoc.info/gems/tty-screen
|
95
|
+
#
|
96
|
+
# @api public
|
97
|
+
def screen
|
98
|
+
require 'tty-screen'
|
99
|
+
TTY::Screen
|
100
|
+
end
|
101
|
+
|
102
|
+
# The unix which utility
|
103
|
+
#
|
104
|
+
# @see http://www.rubydoc.info/gems/tty-which
|
105
|
+
#
|
106
|
+
# @api public
|
107
|
+
def which(*args)
|
108
|
+
require 'tty-which'
|
109
|
+
TTY::Which.which(*args)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Check if executable exists
|
113
|
+
#
|
114
|
+
# @see http://www.rubydoc.info/gems/tty-which
|
115
|
+
#
|
116
|
+
# @api public
|
117
|
+
def exec_exist?(*args)
|
118
|
+
require 'tty-which'
|
119
|
+
TTY::Which.exist?(*args)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../command'
|
4
|
+
require_relative '../../semver_dialects.rb'
|
5
|
+
require_relative '../semantic_version/version_translator.rb'
|
6
|
+
require_relative '../semantic_version/version_parser.rb'
|
7
|
+
require_relative '../semantic_version/version_range.rb'
|
8
|
+
|
9
|
+
module SemverDialects
|
10
|
+
module Commands
|
11
|
+
# The check version command implementation
|
12
|
+
class CheckVersion < SemverDialects::Command
|
13
|
+
def initialize(type, version, constraint, options)
|
14
|
+
@type = type
|
15
|
+
@version = version
|
16
|
+
@constraint = constraint
|
17
|
+
@options = options
|
18
|
+
@avail_types = %w[gem npm ruby pypi php maven go]
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute(_input: $stdin, output: $stdout)
|
22
|
+
typ = @type.downcase
|
23
|
+
raise SemverDialects::Error, 'wrong package type' unless @avail_types.include?(typ)
|
24
|
+
|
25
|
+
if VersionChecker.version_sat?(typ, @version, @constraint)
|
26
|
+
output.puts "#{@version} matches #{@constraint} for #{@type}"
|
27
|
+
0
|
28
|
+
else
|
29
|
+
output.puts "#{@version} does not match #{@constraint}"
|
30
|
+
1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,323 @@
|
|
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
|
+
def initialize(version_string, segments = nil)
|
9
|
+
@version_string = version_string
|
10
|
+
@prefix_segments = []
|
11
|
+
@suffix_segments = []
|
12
|
+
@prefix_delimiter = 0
|
13
|
+
version, _ = version_string.split('+')
|
14
|
+
if segments.nil?
|
15
|
+
@segments = split_version_string!(version)
|
16
|
+
else
|
17
|
+
@prefix_segments = segments
|
18
|
+
@prefix_delimiter = segments.size - 1
|
19
|
+
@segments = segments
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def split_version_string!(version_string)
|
24
|
+
delim_pattern = /[\.\-]/
|
25
|
+
split_array = version_string.split(delim_pattern).map {
|
26
|
+
|grp|
|
27
|
+
grp.split(/(\d+)/).reject { |cell| cell.nil? || cell.empty? }
|
28
|
+
}.flatten
|
29
|
+
|
30
|
+
# go as far to the right as possible considering numbers and placeholders
|
31
|
+
(0..split_array.size - 1).each do
|
32
|
+
|i|
|
33
|
+
if split_array[i].number? || split_array[i] == "X" || split_array[i] == "x"
|
34
|
+
@prefix_delimiter = i
|
35
|
+
else
|
36
|
+
break
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# remove redundant trailing zeros
|
41
|
+
@prefix_delimiter.downto(0).each do
|
42
|
+
|i|
|
43
|
+
if split_array[i] == "0"
|
44
|
+
split_array.delete_at(i)
|
45
|
+
@prefix_delimiter -= 1
|
46
|
+
else
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
@prefix_segments = split_array[0..@prefix_delimiter].map { |group_string| SemanticVersionSegment.new(group_string) } unless @prefix_delimiter < 0
|
52
|
+
if split_array.size - 1 >= @prefix_delimiter + 1
|
53
|
+
@suffix_segments = split_array[@prefix_delimiter + 1, split_array.size].map { |group_string| SemanticVersionSegment.new(group_string) }
|
54
|
+
end
|
55
|
+
|
56
|
+
@prefix_segments.clone().concat(@suffix_segments)
|
57
|
+
end
|
58
|
+
|
59
|
+
def _get_equalized_arrays_for(array_a, array_b)
|
60
|
+
first_array = array_a.clone()
|
61
|
+
second_array = array_b.clone()
|
62
|
+
if first_array.size < second_array.size
|
63
|
+
(second_array.size - first_array.size).times do
|
64
|
+
first_array << SemanticVersionSegment.new("0")
|
65
|
+
end
|
66
|
+
elsif first_array.size > second_array.size
|
67
|
+
(first_array.size - second_array.size).times do
|
68
|
+
second_array << SemanticVersionSegment.new("0")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
[first_array, second_array]
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_equalized_arrays_for(semver_a, semver_b)
|
75
|
+
first_array_prefix = semver_a.prefix_segments.clone()
|
76
|
+
second_array_prefix = semver_b.prefix_segments.clone()
|
77
|
+
first_array_suffix = semver_a.suffix_segments.clone()
|
78
|
+
second_array_suffix = semver_b.suffix_segments.clone()
|
79
|
+
first_array_prefix, second_array_prefix = _get_equalized_arrays_for(first_array_prefix, second_array_prefix)
|
80
|
+
first_array_suffix, second_array_suffix = _get_equalized_arrays_for(first_array_suffix, second_array_suffix)
|
81
|
+
[first_array_prefix.concat(first_array_suffix), second_array_prefix.concat(second_array_suffix)]
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_equalized_prefix_arrays_for(semver_a, semver_b)
|
85
|
+
first_array_prefix = semver_a.prefix_segments.clone()
|
86
|
+
second_array_prefix = semver_b.prefix_segments.clone()
|
87
|
+
first_array_prefix, second_array_prefix = _get_equalized_arrays_for(first_array_prefix, second_array_prefix)
|
88
|
+
[first_array_prefix, second_array_prefix]
|
89
|
+
end
|
90
|
+
|
91
|
+
def <(other_semver)
|
92
|
+
self_array, other_array = get_equalized_arrays_for(self, other_semver)
|
93
|
+
(0..self_array.size - 1).each {
|
94
|
+
|i|
|
95
|
+
if self_array[i] < other_array[i]
|
96
|
+
return true
|
97
|
+
elsif self_array[i] > other_array[i]
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
}
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
def is_zero?
|
105
|
+
@prefix_segments.empty? || @prefix_segments.all? { |segment| segment.is_zero? }
|
106
|
+
end
|
107
|
+
|
108
|
+
def pre_release?
|
109
|
+
@suffix_segments.any?(&:is_pre_release)
|
110
|
+
end
|
111
|
+
|
112
|
+
def post_release?
|
113
|
+
@suffix_segments.any?(&:is_post_release)
|
114
|
+
end
|
115
|
+
|
116
|
+
def >(other_semver)
|
117
|
+
self_array, other_array = get_equalized_arrays_for(self, other_semver)
|
118
|
+
(0..self_array.size - 1).each {
|
119
|
+
|i|
|
120
|
+
if self_array[i] > other_array[i]
|
121
|
+
return true
|
122
|
+
elsif self_array[i] < other_array[i]
|
123
|
+
return false
|
124
|
+
end
|
125
|
+
}
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
129
|
+
def >=(other_semver)
|
130
|
+
self == other_semver || self > other_semver || self == other_semver
|
131
|
+
end
|
132
|
+
|
133
|
+
def <=(other_semver)
|
134
|
+
self == other_semver || self < other_semver
|
135
|
+
end
|
136
|
+
|
137
|
+
def ==(other_semver)
|
138
|
+
segments_a = []
|
139
|
+
segments_b = []
|
140
|
+
|
141
|
+
segments_a += other_semver.segments
|
142
|
+
segments_b += @segments
|
143
|
+
|
144
|
+
if other_semver.segments.size < @segments.size
|
145
|
+
(@segments.size - other_semver.segments.size).times {|_| segments_a << SemanticVersionSegment.new("0")}
|
146
|
+
elsif other_semver.segments.size > @segments.size
|
147
|
+
(other_semver.segments.size - @segments.size).times {|_| segments_b << SemanticVersionSegment.new("0") }
|
148
|
+
end
|
149
|
+
|
150
|
+
(0..segments_a.size - 1).each {
|
151
|
+
|i|
|
152
|
+
if segments_a[i] != segments_b[i]
|
153
|
+
return false
|
154
|
+
end
|
155
|
+
}
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
159
|
+
def !=(other_semver)
|
160
|
+
return !(self == other_semver)
|
161
|
+
end
|
162
|
+
|
163
|
+
def diff(other_semver, abs = true)
|
164
|
+
diffs = []
|
165
|
+
|
166
|
+
self_array, other_array = get_equalized_prefix_arrays_for(self, other_semver)
|
167
|
+
(0..self_array.size - 1).each {
|
168
|
+
|i|
|
169
|
+
# diff semantic groups
|
170
|
+
diffs << (self_array[i].diff(other_array[i], abs))
|
171
|
+
}
|
172
|
+
diffs
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_normalized_s
|
176
|
+
@segments.map { |group| group.to_normalized_s }.join(":").to_s
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_s
|
180
|
+
@segments.map { |group| group.to_s }.join(":").to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
def minor
|
184
|
+
@prefix_segments.size >= 1 ? @prefix_segments[1].to_s : "0"
|
185
|
+
end
|
186
|
+
|
187
|
+
def major
|
188
|
+
@prefix_segments.size >= 2 ? @prefix_segments[0].to_s : "0"
|
189
|
+
end
|
190
|
+
|
191
|
+
def patch
|
192
|
+
@prefix_segments.size >= 3 ? @prefix_segments[2].to_s : "0"
|
193
|
+
end
|
194
|
+
|
195
|
+
def is_successor_of?(other_semver)
|
196
|
+
filtered_segments = self.diff(other_semver, false).reject { |i| i.to_i == 0 }
|
197
|
+
filtered_segments.size == 1 && filtered_segments.last.to_i == 1
|
198
|
+
end
|
199
|
+
|
200
|
+
def cross_total()
|
201
|
+
[self.major, self.minor, self.patch].reject { |i| i.empty? }.map { |i| i.to_i }.inject(0) { |sum, x| sum + x }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
class SemanticVersionSegment
|
206
|
+
attr_accessor :normalized_group_string, :original_group_string, :is_post_release, :is_pre_release
|
207
|
+
|
208
|
+
@@group_suffixes = {
|
209
|
+
# pre-releases
|
210
|
+
"PRE" => -16,
|
211
|
+
"PREVIEW" => -16,
|
212
|
+
"DEV" => -15,
|
213
|
+
"A" => -14,
|
214
|
+
"ALPHA" => -13,
|
215
|
+
"B" => -12,
|
216
|
+
"BETA" => -12,
|
217
|
+
"RC" => -11,
|
218
|
+
"M" => -10,
|
219
|
+
|
220
|
+
"RELEASE" => 0,
|
221
|
+
"FINAL" => 0,
|
222
|
+
# PHP specific
|
223
|
+
"STABLE" => 0,
|
224
|
+
|
225
|
+
# post-releases
|
226
|
+
"SP" => 1,
|
227
|
+
}
|
228
|
+
|
229
|
+
def initialize(group_string)
|
230
|
+
@is_post_release = false
|
231
|
+
@is_pre_release = false
|
232
|
+
|
233
|
+
@version_string = group_string
|
234
|
+
@original_group_string = group_string
|
235
|
+
# use x as unique placeholder
|
236
|
+
group_string_ucase = group_string.to_s.gsub(/\*/, "x").upcase
|
237
|
+
|
238
|
+
if @@group_suffixes.key?(group_string_ucase)
|
239
|
+
value = @@group_suffixes[group_string_ucase]
|
240
|
+
@is_post_release = value > 0
|
241
|
+
@is_pre_release = value < 0
|
242
|
+
@normalized_group_string = @@group_suffixes[group_string_ucase].to_s
|
243
|
+
else
|
244
|
+
@normalized_group_string = group_string_ucase
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def compare(semver_a, semver_b, ret_anr_bnonr, ret_anonr_bnr, comparator)
|
249
|
+
if semver_a.number? && semver_b.number?
|
250
|
+
semver_a.to_i.send(comparator, semver_b.to_i)
|
251
|
+
elsif semver_a.number? && !semver_b.number?
|
252
|
+
if semver_b == "X"
|
253
|
+
true
|
254
|
+
else
|
255
|
+
ret_anr_bnonr
|
256
|
+
end
|
257
|
+
elsif !semver_a.number? && semver_b.number?
|
258
|
+
if semver_a == "X"
|
259
|
+
true
|
260
|
+
else
|
261
|
+
ret_anonr_bnr
|
262
|
+
end
|
263
|
+
else # !semantic_version_b.group_string.is_number? && !semantic_version_agrous_string.is_number?
|
264
|
+
if semver_a == "X" || semver_b == "X"
|
265
|
+
true
|
266
|
+
else
|
267
|
+
semver_a.send(comparator, semver_b)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def <(other_semver)
|
273
|
+
compare(self.normalized_group_string, other_semver.normalized_group_string, true, false, :<)
|
274
|
+
end
|
275
|
+
|
276
|
+
def >(other_semver)
|
277
|
+
compare(self.normalized_group_string, other_semver.normalized_group_string, false, true, :>)
|
278
|
+
end
|
279
|
+
|
280
|
+
def >=(other_semver)
|
281
|
+
self == other_semver || compare(self.normalized_group_string, other_semver.normalized_group_string, false, true, :>)
|
282
|
+
end
|
283
|
+
|
284
|
+
def <=(other_semver)
|
285
|
+
self == other_semver || compare(self.normalized_group_string, other_semver.normalized_group_string, true, false, :<)
|
286
|
+
end
|
287
|
+
|
288
|
+
def ==(other_semver)
|
289
|
+
self.normalized_group_string == other_semver.normalized_group_string
|
290
|
+
end
|
291
|
+
|
292
|
+
def !=(other_semver)
|
293
|
+
return !(self == other_semver)
|
294
|
+
end
|
295
|
+
|
296
|
+
def to_normalized_s
|
297
|
+
@normalized_group_string
|
298
|
+
end
|
299
|
+
|
300
|
+
def to_s
|
301
|
+
@version_string
|
302
|
+
end
|
303
|
+
|
304
|
+
def is_number?
|
305
|
+
self.normalized_group_string.number?
|
306
|
+
end
|
307
|
+
|
308
|
+
def is_zero?
|
309
|
+
is_number? ? self.normalized_group_string.to_i == 0 : false
|
310
|
+
end
|
311
|
+
|
312
|
+
def diff(other_semver, abs = true)
|
313
|
+
|
314
|
+
if other_semver.normalized_group_string == "X" || self.normalized_group_string == "X"
|
315
|
+
"0"
|
316
|
+
elsif self.normalized_group_string.number? && other_semver.normalized_group_string.number?
|
317
|
+
ret = self.normalized_group_string.to_i - other_semver.normalized_group_string.to_i
|
318
|
+
(abs && ret < 0) ? -ret : ret
|
319
|
+
else
|
320
|
+
nil
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|