semver_stringer 0.1.1 → 0.2.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.
- data/README.md +13 -1
- data/lib/semver_stringer/semver.rb +160 -74
- data/lib/semver_stringer/version.rb +1 -1
- data/spec/semver_spec.rb +143 -0
- metadata +4 -4
data/README.md
CHANGED
@@ -19,7 +19,19 @@ Gives you a little help with your [semver](http://semver.org/) strings.
|
|
19
19
|
semver = SemverStringer::Semver.new version_info
|
20
20
|
semver.to_s # => "2.1.13-alpha.1+2134"
|
21
21
|
|
22
|
+
### SemVer comparisons
|
23
|
+
|
24
|
+
`Semver` implements the comparable module, so it's easy to compare
|
25
|
+
one Semver with another. The rules for comparisons are taken from
|
26
|
+
the spec at semver.org. Example:
|
27
|
+
|
28
|
+
version1 = SemverStringer::Semver.new :major=>1, :minor=>0, :patch=>0
|
29
|
+
version2alpha = SemverStringer::Semver.new :major=>2, :minor=0, :patch=>0, :pre=>"alpha"
|
30
|
+
version2 = SemverStringer::Semver.new :major=>2, :minor=0, :patch=>0
|
31
|
+
|
32
|
+
version1 < version2alpha #=> true
|
33
|
+
version2alpha < version2 #=> true
|
34
|
+
|
22
35
|
## TODO
|
23
36
|
|
24
|
-
* Comparison operators to implement the ordering as laid out in the semver spec.
|
25
37
|
* Constructor taking string parameter for parsing and initialization
|
@@ -1,5 +1,56 @@
|
|
1
1
|
module SemverStringer
|
2
|
-
|
2
|
+
|
3
|
+
class Semver
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
class Substring
|
7
|
+
include Comparable
|
8
|
+
|
9
|
+
def initialize(s)
|
10
|
+
@str = s
|
11
|
+
end
|
12
|
+
|
13
|
+
def <=>(other)
|
14
|
+
other_str = other.instance_variable_get('@str')
|
15
|
+
return Substring::compareVersionStrings @str, other_str
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.compareVersionStrings(first, second)
|
19
|
+
first_components = first.split('.')
|
20
|
+
second_components = second.split('.')
|
21
|
+
|
22
|
+
first_head = first_components.shift
|
23
|
+
second_head = second_components.shift
|
24
|
+
|
25
|
+
head_comparison = compare_version_atoms first_head, second_head
|
26
|
+
if head_comparison == 0
|
27
|
+
if first_components.length > 0 or second_components.length > 0
|
28
|
+
return Substring::compareVersionStrings first_components.join('.'), second_components.join('.')
|
29
|
+
else
|
30
|
+
return 0
|
31
|
+
end
|
32
|
+
else
|
33
|
+
return head_comparison
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.compare_version_atoms(first, second)
|
38
|
+
if first == nil and second == nil
|
39
|
+
return nil
|
40
|
+
elsif first != nil and second == nil
|
41
|
+
return 1
|
42
|
+
elsif first == nil and second != nil
|
43
|
+
return -1
|
44
|
+
else
|
45
|
+
unless first.match /[^0-9]/ or second.match /[^0-9]/
|
46
|
+
return first.to_i <=> second.to_i
|
47
|
+
else
|
48
|
+
return first <=> second
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
3
54
|
|
4
55
|
# Creates a new Semver instance.
|
5
56
|
#
|
@@ -9,11 +60,53 @@ module SemverStringer
|
|
9
60
|
# @option params [Integer] :patch Patch version number
|
10
61
|
# @option params [String, Integer, Array<String, Integer>] :pre Pre-release identifier(s)
|
11
62
|
# @option params [String, Integer, Array<String, Integer>] :build Build number identifier(s)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
63
|
+
def initialize(params={})
|
64
|
+
@major, @minor, @patch = get_version_numbers_from params
|
65
|
+
@build = get_build_string_from params
|
66
|
+
@pre = get_pre_string_from params
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# All the semver.org comparison rules are expressed by this operator
|
71
|
+
def <=>(other)
|
72
|
+
|
73
|
+
versionComparison = Substring.new(get_version_string) <=> Substring.new(other.get_version_string)
|
74
|
+
(return versionComparison) if versionComparison != 0
|
75
|
+
|
76
|
+
other_pre = other.instance_variable_get('@pre')
|
77
|
+
if @pre != nil and other_pre == nil
|
78
|
+
return -1
|
79
|
+
elsif @pre == nil and other_pre != nil
|
80
|
+
return 1
|
81
|
+
elsif @pre != nil and other_pre != nil
|
82
|
+
pre_comparison = Substring.new(@pre) <=> Substring.new(other_pre)
|
83
|
+
(return pre_comparison) if pre_comparison != 0
|
84
|
+
end
|
85
|
+
|
86
|
+
other_build = other.instance_variable_get('@build')
|
87
|
+
if @build == nil and other_build != nil
|
88
|
+
return -1
|
89
|
+
elsif @build != nil and other_build == nil
|
90
|
+
return 1
|
91
|
+
elsif @build != nil and other_build != nil
|
92
|
+
build_comparison = Substring.new(@build) <=> Substring.new(other_build)
|
93
|
+
(return build_comparison) if build_comparison != 0
|
94
|
+
end
|
95
|
+
|
96
|
+
return 0
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_version_string
|
100
|
+
"#{@major}.#{@minor}.#{@patch}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_pre_string
|
104
|
+
@pre
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_build_string
|
108
|
+
@build
|
109
|
+
end
|
17
110
|
|
18
111
|
# Returns a string representation of the SemVer
|
19
112
|
#
|
@@ -21,72 +114,65 @@ module SemverStringer
|
|
21
114
|
# SemverStringer::Semver.new(:major=>2, :pre=>"alpha").to_s #=> "2.0.0-alpha"
|
22
115
|
#
|
23
116
|
# @return [String]
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
[major, minor, patch]
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
def get_pre_string_from(params)
|
61
|
-
return get_optional_string_from params, :pre
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
def get_build_string_from(params)
|
66
|
-
return get_optional_string_from params, :build
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
def get_optional_string_from(params, type)
|
71
|
-
disallowed_chars = /[^0-9A-Za-z-]/
|
72
|
-
|
73
|
-
if params.has_key? type
|
74
|
-
identifiers = scalar_to_array params[type]
|
75
|
-
|
76
|
-
identifiers.each do |param|
|
77
|
-
raise ArgumentError.new("Characters in #{type} ID are not allowed") if disallowed_chars.match param.to_s
|
78
|
-
end
|
79
|
-
|
80
|
-
return identifiers.join "."
|
81
|
-
else
|
82
|
-
return nil
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
def scalar_to_array(scalar)
|
88
|
-
(scalar.is_a? Array) ? scalar : Array.new(1, scalar)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
117
|
+
def to_s
|
118
|
+
version = get_version_string
|
119
|
+
version << "-#{get_pre_string}" unless @pre == nil
|
120
|
+
version << "+#{get_build_string}" unless @build == nil
|
121
|
+
version
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
def raise_if_invalid_version_number(hash, key)
|
126
|
+
if hash.has_key? key
|
127
|
+
raise ArgumentError.new("Positive integers only") if hash[key] < 0
|
128
|
+
raise ArgumentError.new("Integral numbers only") if ! hash[key].integer?
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_valid_version_number(hash, key)
|
133
|
+
raise_if_invalid_version_number(hash, key)
|
134
|
+
(hash.has_key? key) ? hash[key] : 0
|
135
|
+
end
|
136
|
+
|
137
|
+
def get_version_numbers_from(params)
|
138
|
+
if (params.has_key? :major) || (params.has_key? :minor) || (params.has_key? :patch)
|
139
|
+
major = get_valid_version_number(params, :major)
|
140
|
+
minor = get_valid_version_number(params, :minor)
|
141
|
+
patch = get_valid_version_number(params, :patch)
|
142
|
+
else
|
143
|
+
major = minor = 0
|
144
|
+
patch = 1
|
145
|
+
end
|
146
|
+
|
147
|
+
[major, minor, patch]
|
148
|
+
end
|
92
149
|
|
150
|
+
def get_pre_string_from(params)
|
151
|
+
return get_optional_string_from params, :pre
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_build_string_from(params)
|
155
|
+
return get_optional_string_from params, :build
|
156
|
+
end
|
157
|
+
|
158
|
+
def get_optional_string_from(params, type)
|
159
|
+
disallowed_chars = /[^0-9A-Za-z-]/
|
160
|
+
|
161
|
+
if params.has_key? type
|
162
|
+
identifiers = scalar_to_array params[type]
|
163
|
+
|
164
|
+
identifiers.each do |param|
|
165
|
+
raise ArgumentError.new("Characters in #{type} ID are not allowed") if disallowed_chars.match param.to_s
|
166
|
+
end
|
167
|
+
|
168
|
+
return identifiers.join "."
|
169
|
+
else
|
170
|
+
return nil
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def scalar_to_array(scalar)
|
175
|
+
(scalar.is_a? Array) ? scalar : Array.new(1, scalar)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
data/spec/semver_spec.rb
CHANGED
@@ -103,4 +103,147 @@ describe SemverStringer::Semver do
|
|
103
103
|
semver.to_s.should == "1.2.303-beta+build.1234"
|
104
104
|
end
|
105
105
|
end
|
106
|
+
|
107
|
+
describe "semver comparson operator" do
|
108
|
+
|
109
|
+
RSpec::Matchers.define :be_higher_than do |lower|
|
110
|
+
match do |higher|
|
111
|
+
(higher <=> lower) == 1 and
|
112
|
+
(higher < lower) == false and
|
113
|
+
(higher == lower) == false and
|
114
|
+
(higher > lower) == true and
|
115
|
+
(lower <=> higher) == -1 and
|
116
|
+
(lower < higher) == true and
|
117
|
+
(lower == higher) == false and
|
118
|
+
(lower > higher) == false
|
119
|
+
end
|
120
|
+
|
121
|
+
failure_message_for_should do |higher|
|
122
|
+
"expected that #{higher} would be higher than #{lower} (<=> got #{higher<=>lower})"
|
123
|
+
end
|
124
|
+
|
125
|
+
failure_message_for_should_not do |higher|
|
126
|
+
"expected that #{higher} would not be higher than #{lower} (<=> got #{higher<=>lower})"
|
127
|
+
end
|
128
|
+
|
129
|
+
description do
|
130
|
+
"be higher than #{lower}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "is equal if version numbers are all identical" do
|
135
|
+
semver1 = SemverStringer::Semver.new :major=>2, :minor=>5, :patch=>9
|
136
|
+
semver2 = SemverStringer::Semver.new :major=>2, :minor=>5, :patch=>9
|
137
|
+
|
138
|
+
(semver1 <=> semver2).should == 0
|
139
|
+
(semver1 < semver2).should == false
|
140
|
+
(semver1 == semver2).should == true
|
141
|
+
(semver1 > semver2).should == false
|
142
|
+
|
143
|
+
(semver2 <=> semver1).should == 0
|
144
|
+
(semver2 < semver1).should == false
|
145
|
+
(semver2 == semver1).should == true
|
146
|
+
(semver2 > semver1).should == false
|
147
|
+
end
|
148
|
+
|
149
|
+
it "gives highest precedence to major" do
|
150
|
+
higher = SemverStringer::Semver.new :major=>3, :minor=>1, :patch=>1
|
151
|
+
lower = SemverStringer::Semver.new :major=>2, :minor=>50, :patch=>50
|
152
|
+
|
153
|
+
higher.should be_higher_than lower
|
154
|
+
end
|
155
|
+
|
156
|
+
it "gives second precedence to minor" do
|
157
|
+
higher = SemverStringer::Semver.new :major=>2, :minor=>6, :patch=>1
|
158
|
+
lower = SemverStringer::Semver.new :major=>2, :minor=>2, :patch=>900
|
159
|
+
|
160
|
+
higher.should be_higher_than lower
|
161
|
+
end
|
162
|
+
|
163
|
+
it "considers pre-release semvers lower than non-pre-release semvers" do
|
164
|
+
higher = SemverStringer::Semver.new
|
165
|
+
lower = SemverStringer::Semver.new :pre=>1
|
166
|
+
|
167
|
+
higher.should be_higher_than lower
|
168
|
+
end
|
169
|
+
|
170
|
+
it "compares pre numbers as integers" do
|
171
|
+
higher = SemverStringer::Semver.new :pre=>11
|
172
|
+
lower = SemverStringer::Semver.new :pre=>"2"
|
173
|
+
|
174
|
+
higher.should be_higher_than lower
|
175
|
+
end
|
176
|
+
|
177
|
+
it "compares pre numbers with chars or - as strings" do
|
178
|
+
higher = SemverStringer::Semver.new :pre=>"a"
|
179
|
+
lower = SemverStringer::Semver.new :pre=>1
|
180
|
+
|
181
|
+
higher.should be_higher_than lower
|
182
|
+
end
|
183
|
+
|
184
|
+
it "considers build-numbered semvers higher than non-build numbered semvers" do
|
185
|
+
higher = SemverStringer::Semver.new :build=>1
|
186
|
+
lower = SemverStringer::Semver.new
|
187
|
+
|
188
|
+
higher.should be_higher_than lower
|
189
|
+
end
|
190
|
+
|
191
|
+
it "ignores build numbers if the main versions are different" do
|
192
|
+
higher = SemverStringer::Semver.new :major=>2, :minor=>6, :patch=>1
|
193
|
+
lower = SemverStringer::Semver.new :major=>2, :minor=>5, :patch=>1, :build=>9
|
194
|
+
|
195
|
+
higher.should be_higher_than lower
|
196
|
+
end
|
197
|
+
|
198
|
+
it "compares integer build numbers as integers" do
|
199
|
+
higher = SemverStringer::Semver.new :build=>11
|
200
|
+
lower = SemverStringer::Semver.new :build=>"2"
|
201
|
+
|
202
|
+
higher.should be_higher_than lower
|
203
|
+
end
|
204
|
+
|
205
|
+
it "compares build numbers with chars or - as strings" do
|
206
|
+
higher = SemverStringer::Semver.new :build=>"a"
|
207
|
+
lower = SemverStringer::Semver.new :build=>1
|
208
|
+
|
209
|
+
higher.should be_higher_than lower
|
210
|
+
end
|
211
|
+
|
212
|
+
describe "Semver::Substring comparator" do
|
213
|
+
it "compares equal numbers as integers" do
|
214
|
+
first = SemverStringer::Semver::Substring.new "4"
|
215
|
+
second = SemverStringer::Semver::Substring.new "4"
|
216
|
+
|
217
|
+
(first <=> second).should be 0
|
218
|
+
end
|
219
|
+
|
220
|
+
it "compares numbers as integers" do
|
221
|
+
higher = SemverStringer::Semver::Substring.new "12"
|
222
|
+
lower = SemverStringer::Semver::Substring.new "4"
|
223
|
+
|
224
|
+
higher.should be_higher_than lower
|
225
|
+
end
|
226
|
+
|
227
|
+
it "compares period-delimeted sub-numbers with each other" do
|
228
|
+
first = SemverStringer::Semver::Substring.new "a.b.2"
|
229
|
+
second = SemverStringer::Semver::Substring.new "a.b.2"
|
230
|
+
(first <=> second).should be 0
|
231
|
+
|
232
|
+
higher = SemverStringer::Semver::Substring.new "4.beta"
|
233
|
+
lower = SemverStringer::Semver::Substring.new "4.alpha"
|
234
|
+
higher.should be_higher_than lower
|
235
|
+
|
236
|
+
higher = SemverStringer::Semver::Substring.new "alpha.11"
|
237
|
+
lower = SemverStringer::Semver::Substring.new "alpha.2"
|
238
|
+
higher.should be_higher_than lower
|
239
|
+
end
|
240
|
+
|
241
|
+
it "compares a number with an extra segment higher than one without" do
|
242
|
+
higher = SemverStringer::Semver::Substring.new "alpha.2.a"
|
243
|
+
lower = SemverStringer::Semver::Substring.new "alpha.2"
|
244
|
+
higher.should be_higher_than lower
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
106
249
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semver_stringer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70277379840900 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '2.8'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70277379840900
|
25
25
|
description: See semver.org for the rules, or https://github.com/iantruslove/SemverStringer#readme
|
26
26
|
for a little documentation.
|
27
27
|
email:
|