sem_version 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +7 -0
- data/README.md +146 -0
- data/lib/sem_version/core_ext.rb +8 -0
- data/lib/sem_version.rb +54 -21
- metadata +11 -6
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (C) 2012 Antony Male
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
SemVersion
|
2
|
+
==========
|
3
|
+
|
4
|
+
SemVersion is a gem to help parse, validate, modify, and compare [Semantic Versions](http://semver.org).
|
5
|
+
|
6
|
+
Parsing
|
7
|
+
-------
|
8
|
+
|
9
|
+
Parsing is easy:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
v = SemVersion.new('1.2.3-pre.4+build.5')
|
13
|
+
|
14
|
+
v.major # => 1
|
15
|
+
v.minor # => 2
|
16
|
+
v.patch # => 3
|
17
|
+
|
18
|
+
v.pre # => 'pre.4'
|
19
|
+
v.prerelease # => 'pre.4'
|
20
|
+
v.build # => 'build.5'
|
21
|
+
|
22
|
+
v.to_s # => '1.2.3-pre.4+build.5'
|
23
|
+
```
|
24
|
+
|
25
|
+
You can pass any valid semantic version string, as specified by [Semantic Versions](http://semver.org).
|
26
|
+
Invalid versions will raise an ArgumentError.
|
27
|
+
|
28
|
+
You can also create a new SemVersion from an array or a hash, and serialise back to arrays and hashes.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
v1 = SemVersion.new([1, 2, 3, 'pre.4', 'build.5'])
|
32
|
+
v1.to_s # => '1.2.3-pre.4+build.5'
|
33
|
+
v1.to_a # => [1, 2, 3, 'pre.4', 'build.5']
|
34
|
+
|
35
|
+
v2 = SemVersion.new(1, 2, 3, nil, 'build.5')
|
36
|
+
v2.to_s # => '1.2.3+build.5'
|
37
|
+
v2.to_a # => [1, 2, 3, nil, 'build.5']
|
38
|
+
|
39
|
+
v3 = SemVersion.new(:major => 1, :minor => 2, :patch => 3, :pre => 'pre.4', :build => 'build.5')
|
40
|
+
v.to_s # => '1.2.3-pre.4+build.5'
|
41
|
+
v.to_h # => {:major => 1, :minor => 2, :patch => 3, :pre => 'pre.4', :build => 'build.5'}
|
42
|
+
|
43
|
+
v4 = SemVersion.new(:major => 1, :minor => 2, :patch => 3, :build => 'build.6')
|
44
|
+
v4.to_h # => {:major => 1, :minor => 2, :patch => 3, :build => 'build.6'}
|
45
|
+
```
|
46
|
+
|
47
|
+
You can also use `SemVersion()` as an alias for `SemVersion.new()`.
|
48
|
+
|
49
|
+
|
50
|
+
Validating
|
51
|
+
----------
|
52
|
+
|
53
|
+
Validating is easier:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
SemVersion.valid?('1.2.3') # => true
|
57
|
+
SemVersion.valid?('1.2') # => false
|
58
|
+
SemVersion.valid?('1.2.3-pre.1') # => true
|
59
|
+
SemVersion.valid?('1.2.3-pre.!') # => false
|
60
|
+
```
|
61
|
+
|
62
|
+
And so on...
|
63
|
+
|
64
|
+
Modifying
|
65
|
+
---------
|
66
|
+
|
67
|
+
You can modify any part of a parsed version.
|
68
|
+
Invalid new values will raise an ArgumentError
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
v = SemVersion.new('1.2.3')
|
72
|
+
v.major = 3
|
73
|
+
v.minor = 5
|
74
|
+
v.pre = 'pre.2'
|
75
|
+
v.build = 'build.x.7'
|
76
|
+
|
77
|
+
v.to_s # => '3.5.1-pre.2+build.x.7'
|
78
|
+
|
79
|
+
v.major = -1 # => ArgumentError
|
80
|
+
v.major = 'a' # => ArgumentError
|
81
|
+
v.pre = 'a.!' # => ArgumentError
|
82
|
+
v.pre = '.a' # => ArgumentError
|
83
|
+
```
|
84
|
+
|
85
|
+
Comparing
|
86
|
+
---------
|
87
|
+
|
88
|
+
You can compare semantic versions using `<`, `>`, `<=`, `>=`, `==`, and `<=>`
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
SemVersion.new('1.2.3') < SemVersion.new('1.2.2') # => true
|
92
|
+
SemVersion.new('1.2.3-pre.1') <= SemVersion.new('1.2.3-pre') # => false
|
93
|
+
SemVersion.new('1.2.3+build.11') > SemVersion.new('1.2.3+build.2') # => true
|
94
|
+
```
|
95
|
+
|
96
|
+
Satisfying constraints
|
97
|
+
----------------------
|
98
|
+
|
99
|
+
You can see whether a semantic version satisfies a particular constraint.
|
100
|
+
Constraints are in the form `"<comparison> <version>"`, e.g. ">= 1.2.2", "= 1.3", or "~> 1.2".
|
101
|
+
|
102
|
+
When using the pessimistic operation, `~>`, versions may be specified in the form `"x.y"` or `"x.y.z"` (with `"~> x.y"` meaning `">= x.y.0" && "< x+1.0.0"`, and `"~> x.y.z"` meaning `">= x.y.z" && "< x.y+1.0"`).
|
103
|
+
|
104
|
+
When using the other operations, versions may be in the form `"x"`, `"x.y"`, or a full semantic version (including optional pre-release and build).
|
105
|
+
In the former two cases, the missing versions out of minor and patch will be filled in with 0's, and the pre-release and build ignored.
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
SemVersion.new('1.2.3').satisfies?('>= 1.2') # => true
|
109
|
+
SemVersion.new('1.2.3-pre.1').satisfies?('>= 1.2.3') # => false
|
110
|
+
SemVersion.new('0.1.0').satisfies?('> 0') # => true
|
111
|
+
SemVersion.new('2.3.0').satisfies?('~> 2.2') # => true
|
112
|
+
```
|
113
|
+
|
114
|
+
You can also see whether a given constraint is 'open' (allows a range of versions), or 'closed' (allows only one version).
|
115
|
+
|
116
|
+
For example:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
SemVersion.open_constraint?('1.2.3') # => false
|
120
|
+
SemVersion.open_constraint?('= 1.2.3') # => false
|
121
|
+
SemVersion.open_constraint?('== 1.2.3') # => false
|
122
|
+
SemVersion.open_constraint?('<= 1.2.3') # => true
|
123
|
+
SemVersion.open_constraint?('~> 1.2.3') # => true
|
124
|
+
```
|
125
|
+
|
126
|
+
It's also possible to split a constraint into its comparison and version.
|
127
|
+
If the comparison is not given, or is '==', it is normalised to '='.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
SemVersion.split_constraint('1.2.3') # => ['=', '1.2.3']
|
131
|
+
SemVersion.split_constraint('= 1.2.3') # => ['=', '1.2.3']
|
132
|
+
SemVersion.split_constraint('== 1.2.3') # => ['=', '1.2.3']
|
133
|
+
SemVersion.split_constraint('> 1.2.3') # => ['>', '1.2.3']
|
134
|
+
```
|
135
|
+
|
136
|
+
Core Extensions
|
137
|
+
===============
|
138
|
+
|
139
|
+
You can also load a set of core extensions using an optional require.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
require 'sem_version'
|
143
|
+
require 'sem_version/core_ext'
|
144
|
+
|
145
|
+
"1.2.3+pre.4-build.5".to_version
|
146
|
+
```
|
data/lib/sem_version.rb
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
class SemVersion
|
2
2
|
include Comparable
|
3
3
|
|
4
|
-
VERSION = '1.
|
4
|
+
VERSION = '1.3.0'
|
5
|
+
|
5
6
|
# Pattern allows min and patch to be skipped. We have to do extra checking if we want them
|
6
7
|
SEMVER_REGEX = /^(\d+)(?:\.(\d+)(?:\.(\d+)(?:-([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?(?:\+([\dA-Za-z\-]+(?:\.[\dA-Za-z\-]+)*))?)?)?$/
|
8
|
+
PRE_BUILD_REGEX = /^[\dA-Za-z\-]+(\.[\dA-Za-z\-]+)*$/
|
7
9
|
|
8
10
|
attr_reader :major, :minor, :patch, :pre, :build
|
9
11
|
alias_method :prerelease, :pre
|
10
12
|
|
11
13
|
# Format were raw bits are passed in is undocumented, and not validity checked
|
12
|
-
def initialize(
|
13
|
-
if args.
|
14
|
-
@major, @minor, @patch, @pre, @build = self.class.parse(
|
14
|
+
def initialize(*args)
|
15
|
+
if args.first.is_a?(String)
|
16
|
+
@major, @minor, @patch, @pre, @build = self.class.parse(args.first)
|
17
|
+
# Validation should be handled at a string level by self.parse, but validate anyway
|
18
|
+
validate
|
19
|
+
elsif args.first.is_a?(Hash)
|
20
|
+
@major, @minor, @patch, @pre, @build = args.first.values_at(:major, :minor, :patch, :pre, :build)
|
21
|
+
# Allow :prerelease as well
|
22
|
+
@pre ||= args.first[:prerelease]
|
23
|
+
validate
|
24
|
+
elsif args.first.is_a?(Array)
|
25
|
+
@major, @minor, @patch, @pre, @build = *args.first
|
26
|
+
validate
|
15
27
|
else
|
16
|
-
@major, @minor, @patch, @pre, @build =
|
28
|
+
@major, @minor, @patch, @pre, @build = *args
|
29
|
+
validate
|
17
30
|
end
|
18
31
|
end
|
19
32
|
|
@@ -59,7 +72,7 @@ class SemVersion
|
|
59
72
|
end
|
60
73
|
|
61
74
|
def satisfies?(constraint)
|
62
|
-
comparison, version =
|
75
|
+
comparison, version = self.class.split_constraint(constraint)
|
63
76
|
# Allow pessimistic operator
|
64
77
|
if comparison == '~>'
|
65
78
|
match = version.match(/^(\d+)\.(\d+)\.?(\d*)$/)
|
@@ -73,22 +86,17 @@ class SemVersion
|
|
73
86
|
upper = "#{maj}.#{min.to_i+1}.0"
|
74
87
|
end
|
75
88
|
|
76
|
-
send('>=', SemVersion.new(lower)) && send('<', SemVersion.new(upper))
|
89
|
+
send('>=', SemVersion.new(lower)) && send('<', SemVersion.new(upper))
|
77
90
|
else
|
78
|
-
# Allow '1.0.2' as '== 1.0.2'
|
79
|
-
version, comparison = comparison, '==' if version.nil?
|
80
|
-
# Allow '= 1.0.2' as '== 1.0.2'
|
81
91
|
comparison = '==' if comparison == '='
|
82
|
-
|
83
92
|
semversion = self.class.from_loose_version(version)
|
84
|
-
|
85
93
|
send(comparison, semversion)
|
86
94
|
end
|
87
95
|
end
|
88
96
|
|
89
97
|
def self.open_constraint?(constraint)
|
90
|
-
comparison,
|
91
|
-
|
98
|
+
comparison, _ = self.split_constraint(constraint)
|
99
|
+
comparison != '='
|
92
100
|
end
|
93
101
|
|
94
102
|
def self.split_constraint(constraint)
|
@@ -114,30 +122,42 @@ class SemVersion
|
|
114
122
|
end
|
115
123
|
|
116
124
|
def pre=(val)
|
117
|
-
|
118
|
-
raise ArgumentError, "#{val} is not a valid pre-release version (must be a string following http://semver.org constraints)"
|
125
|
+
unless val.nil? || (val.is_a?(String) && val =~ PRE_BUILD_REGEX)
|
126
|
+
raise ArgumentError, "#{val} is not a valid pre-release version (must be nil, or a string following http://semver.org constraints)"
|
119
127
|
end
|
120
128
|
@pre = val
|
121
129
|
end
|
122
130
|
alias_method :prerelease=, :pre=
|
123
131
|
|
124
132
|
def build=(val)
|
125
|
-
|
126
|
-
raise ArgumentError, "#{val} is not a valid
|
133
|
+
unless val.nil? || (val.is_a?(String) && val =~ PRE_BUILD_REGEX)
|
134
|
+
raise ArgumentError, "#{val} is not a valid build version (must be nil, or a string following http://semver.org constraints)"
|
127
135
|
end
|
128
136
|
@build = val
|
129
137
|
end
|
130
138
|
|
131
|
-
|
132
139
|
def to_s
|
133
|
-
r = "#{@major}.#{@minor}.#{patch}"
|
140
|
+
r = "#{@major}.#{@minor}.#{@patch}"
|
134
141
|
r << "-#{@pre}" if @pre
|
135
142
|
r << "+#{@build}" if @build
|
136
143
|
r
|
137
144
|
end
|
138
145
|
|
146
|
+
def to_a
|
147
|
+
[@major, @minor, @patch, @pre, @build]
|
148
|
+
end
|
149
|
+
|
150
|
+
def to_h
|
151
|
+
h = [:major, :minor, :patch, :pre, :build].zip(to_a)
|
152
|
+
Hash[h.reject{ |k,v| v.nil? }]
|
153
|
+
end
|
154
|
+
|
155
|
+
def inspect
|
156
|
+
"#<SemVersion: #{to_s}>"
|
157
|
+
end
|
158
|
+
|
139
159
|
private
|
140
|
-
|
160
|
+
|
141
161
|
def compare_sep(ours, theirs, nil_wins)
|
142
162
|
# Both nil? They're equal
|
143
163
|
return 0 if ours.nil? && theirs.nil?
|
@@ -162,6 +182,19 @@ class SemVersion
|
|
162
182
|
# If we got this far, either they're equal (same length) or they won
|
163
183
|
return (our_parts.length == their_parts.length) ? 0 : -1
|
164
184
|
end
|
185
|
+
|
186
|
+
def validate
|
187
|
+
# Validates the instance variables. Different approach to validating a raw string
|
188
|
+
raise ArgumentError, "Invalid version (major is not an int >= 0)" unless @major.is_a?(Fixnum) && @major >= 0
|
189
|
+
raise ArgumentError, "Invalid version (minor is not an int >= 0)" unless @minor.is_a?(Fixnum) && @minor >= 0
|
190
|
+
raise ArgumentError, "Invalid version (patch is not an int >= 0)" unless @patch.is_a?(Fixnum) && @patch >= 0
|
191
|
+
unless @pre.nil? || (@pre.is_a?(String) && @pre =~ PRE_BUILD_REGEX)
|
192
|
+
raise ArgumentError, "Invalid version (pre must be nil, or a string following http://semver.org contraints)"
|
193
|
+
end
|
194
|
+
unless @build.nil? || (@build.is_a?(String) && @build =~ PRE_BUILD_REGEX)
|
195
|
+
raise ArgumentError, "Invalid version (build must be nil, or a string following http://semver.org contraints)"
|
196
|
+
end
|
197
|
+
end
|
165
198
|
end
|
166
199
|
|
167
200
|
def SemVersion(*args)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sem_version
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,18 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-16 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
14
|
+
description: Semantic Version parsing, comparison, and constraint checking utility
|
15
|
+
(e.g. ~> 1.2), as specified by http://semver.org/
|
16
16
|
email: antony dot mail at gmail
|
17
17
|
executables: []
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
+
- lib/sem_version/core_ext.rb
|
21
22
|
- lib/sem_version.rb
|
23
|
+
- README.md
|
24
|
+
- LICENSE
|
22
25
|
homepage: https://github.com/canton7/sem_version
|
23
|
-
licenses:
|
26
|
+
licenses:
|
27
|
+
- MIT
|
24
28
|
post_install_message:
|
25
29
|
rdoc_options: []
|
26
30
|
require_paths:
|
@@ -42,5 +46,6 @@ rubyforge_project:
|
|
42
46
|
rubygems_version: 1.8.24
|
43
47
|
signing_key:
|
44
48
|
specification_version: 3
|
45
|
-
summary: ! 'SemVersion: Semantic version parsing and comparison
|
49
|
+
summary: ! 'SemVersion: Semantic version parsing and comparison, and constraint checking.
|
50
|
+
See http://semver.org/'
|
46
51
|
test_files: []
|