semantic_range 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40689a4a60d1676915d3c80166fa016fed599e9e
4
- data.tar.gz: a6797c03b699280fbb46196f83b6b9d29de102e3
3
+ metadata.gz: 713091878f31485514b30d0ab9e9f7281576a260
4
+ data.tar.gz: 0f6bf36a44b5e9b4a6e61c5e3f42dbd4aeb2f60c
5
5
  SHA512:
6
- metadata.gz: 227c788ef4eab62cb0458ce01d21d31e392f17d5b5eba966d9269cd14d2e8a669d5d9df99d9afad7da4c08525f10729768a13a45ee22e6d5ed30f7af68db2da1
7
- data.tar.gz: 8de84d61c1823fddc13d53ce579e5838289675c7e3f8cac392ab9ea479bdc25b16dd7d79a445e0f956be1ecb94f035ca97e074b1a4e530bf45f55c6aa33682bb
6
+ metadata.gz: 201e862b74b02896c79356d61ee4128ae31b35d7ebbd2e2548d028d0fe2294389bcb5b699fdf0e0e70630db19cc21b8f45c535ada00f3ab2bda9111f90c409aa
7
+ data.tar.gz: 1c16363476186d8d54f0d2c229f805f962af5afd43eb3cd4de8c7cc954c858b85c08612289d6fc621843124f23280d6c0e9af2d97c8d81a6c0a35ff58f197ca1
@@ -1,41 +1,22 @@
1
1
  module SemanticRange
2
2
  class Comparator
3
+ attr_reader :semver, :operator, :value
3
4
  def initialize(comp, loose)
4
- @loose = loose
5
-
6
5
  if comp.is_a?(Comparator)
7
- if comp.loose == loose
8
- return comp
9
- else
10
- @comp = comp.value
11
- end
6
+ return comp if comp.loose == loose
7
+ @comp = comp.value
12
8
  end
13
9
 
10
+ @loose = loose
14
11
  parse(comp)
15
12
 
16
- if @semver == ANY
17
- @value = ''
18
- else
19
- @value = @operator + @semver.version
20
- end
21
- end
22
-
23
- def semver
24
- @semver
25
- end
26
-
27
- def operator
28
- @operator
13
+ @value = @semver == ANY ? '' : @operator + @semver.version
29
14
  end
30
15
 
31
16
  def to_s
32
17
  @value
33
18
  end
34
19
 
35
- def value
36
- @value
37
- end
38
-
39
20
  def test(version)
40
21
  return true if @semver == ANY
41
22
  version = Version.new(version, @loose) if version.is_a?(String)
@@ -44,16 +25,12 @@ module SemanticRange
44
25
 
45
26
  def parse(comp)
46
27
  m = comp.match(@loose ? COMPARATORLOOSE : COMPARATOR)
47
- raise 'Invalid comparator: ' + comp unless m
28
+ raise "Invalid comparator: #{comp}" unless m
48
29
 
49
30
  @operator = m[1]
50
31
  @operator = '' if @operator == '='
51
32
 
52
- if !m[2]
53
- @semver = ANY
54
- else
55
- @semver = Version.new(m[2], @loose)
56
- end
33
+ @semver = !m[2] ? ANY : Version.new(m[2], @loose)
57
34
  end
58
35
  end
59
36
  end
@@ -0,0 +1,64 @@
1
+ module SemanticRange
2
+ class PreRelease
3
+ attr_reader :parts
4
+
5
+ def initialize(input)
6
+ @parts = parse(input)
7
+ end
8
+
9
+ def parse(str)
10
+ str.to_s.split('.').map { |id| convert(id) }
11
+ end
12
+
13
+ def convert(str)
14
+ str.match(/^[0-9]+$/) ? str.to_i : str
15
+ end
16
+
17
+ def length
18
+ parts.length
19
+ end
20
+
21
+ def empty?
22
+ parts.empty?
23
+ end
24
+
25
+ def to_s
26
+ parts.join '.'
27
+ end
28
+
29
+ def clear!
30
+ @parts = []
31
+ end
32
+
33
+ def zero!
34
+ @parts = [0]
35
+ end
36
+
37
+ def <=>(other)
38
+ return unless other.is_a?(self.class)
39
+
40
+ return -1 if parts.any? && !other.parts.any?
41
+ return 1 if !parts.any? && other.parts.any?
42
+ return 0 if !parts.any? && !other.parts.any?
43
+
44
+ i = 0
45
+ while true
46
+ a = parts[i]
47
+ b = other.parts[i]
48
+
49
+ if a.nil? && b.nil?
50
+ return 0
51
+ elsif b.nil?
52
+ return 1
53
+ elsif a.nil?
54
+ return -1
55
+ elsif a == b
56
+
57
+ else
58
+ return Version.compare_identifiers(a, b)
59
+ end
60
+ i += 1
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,5 +1,7 @@
1
1
  module SemanticRange
2
2
  class Range
3
+ attr_reader :loose, :raw, :range, :set
4
+
3
5
  def initialize(range, loose)
4
6
  range = range.raw if range.is_a?(Range)
5
7
 
@@ -8,27 +10,13 @@ module SemanticRange
8
10
  split = range.split(/\s*\|\|\s*/)
9
11
  split = ['', ''] if range == '||'
10
12
  split = [''] if split == []
11
- @set = split.map do |range|
12
- parse_range(range.strip)
13
- end
13
+ @set = split.map {|range| parse_range(range.strip) }
14
14
 
15
- raise 'Invalid SemVer Range: ' + range if @set.empty?
15
+ raise 'Invalid SemVer Range: ' + range if @set.empty? || @set == [[]]
16
16
 
17
17
  format
18
18
  end
19
19
 
20
- def loose
21
- @loose
22
- end
23
-
24
- def raw
25
- @raw
26
- end
27
-
28
- def range
29
- @range
30
- end
31
-
32
20
  def format
33
21
  @range = @set.map do |comps|
34
22
  comps.join(' ').strip
@@ -36,23 +24,14 @@ module SemanticRange
36
24
  @range
37
25
  end
38
26
 
39
- def set
40
- @set
41
- end
42
-
43
27
  def test(version)
44
28
  return false if !version
45
29
  version = Version.new(version, @loose) if version.is_a?(String)
46
- @set.each do |s|
47
- return true if test_set(s, version)
48
- end
49
- false
30
+ @set.any?{|s| test_set(s, version) }
50
31
  end
51
32
 
52
33
  def test_set(set, version)
53
- set.each do |comp|
54
- return false if !comp.test(version)
55
- end
34
+ return false if set.any? {|comp| !comp.test(version) }
56
35
  if version.prerelease.length > 0
57
36
  set.each do |comp|
58
37
  next if comp.semver == ANY
@@ -119,14 +98,14 @@ module SemanticRange
119
98
  pr = match[4]
120
99
 
121
100
  if isX(mj)
122
- ret = ''
101
+ ''
123
102
  elsif isX(m)
124
- ret = ">=#{mj}.0.0 <#{(mj.to_i + 1)}.0.0"
103
+ ">=#{mj}.0.0 <#{(mj.to_i + 1)}.0.0"
125
104
  elsif isX(p)
126
105
  if mj == '0'
127
- ret = ">=#{mj}.#{m}.0 <#{mj}.#{(m.to_i + 1)}.0"
106
+ ">=#{mj}.#{m}.0 <#{mj}.#{(m.to_i + 1)}.0"
128
107
  else
129
- ret = ">=#{mj}.#{m}.0 <#{(mj.to_i + 1)}.0.0"
108
+ ">=#{mj}.#{m}.0 <#{(mj.to_i + 1)}.0.0"
130
109
  end
131
110
  elsif pr
132
111
  if pr[0] != '-'
@@ -134,25 +113,24 @@ module SemanticRange
134
113
  end
135
114
  if mj == '0'
136
115
  if m == '0'
137
- ret = ">=#{mj}.#{m}.#{p}#{pr} <#{mj}.#{m}.#{(p.to_i + 1)}"
116
+ ">=#{mj}.#{m}.#{p}#{pr} <#{mj}.#{m}.#{(p.to_i + 1)}"
138
117
  else
139
- ret = ">=#{mj}.#{m}.#{p}#{pr} <#{mj}.#{(m.to_i + 1)}.0"
118
+ ">=#{mj}.#{m}.#{p}#{pr} <#{mj}.#{(m.to_i + 1)}.0"
140
119
  end
141
120
  else
142
- ret = ">=#{mj}.#{m}.#{p}#{pr} <#{(mj.to_i + 1)}.0.0"
121
+ ">=#{mj}.#{m}.#{p}#{pr} <#{(mj.to_i + 1)}.0.0"
143
122
  end
144
123
  else
145
124
  if mj == '0'
146
125
  if m == '0'
147
- ret = ">=#{mj}.#{m}.#{p} <#{mj}.#{m}.#{(p.to_i + 1)}"
126
+ ">=#{mj}.#{m}.#{p} <#{mj}.#{m}.#{(p.to_i + 1)}"
148
127
  else
149
- ret = ">=#{mj}.#{m}.#{p} <#{mj}.#{(m.to_i + 1)}.0"
128
+ ">=#{mj}.#{m}.#{p} <#{mj}.#{(m.to_i + 1)}.0"
150
129
  end
151
130
  else
152
- ret = ">=#{mj}.#{m}.#{p} <#{(mj.to_i + 1)}.0.0"
131
+ ">=#{mj}.#{m}.#{p} <#{(mj.to_i + 1)}.0.0"
153
132
  end
154
133
  end
155
- ret
156
134
  end
157
135
  end
158
136
 
@@ -171,18 +149,17 @@ module SemanticRange
171
149
  pr = match[4]
172
150
 
173
151
  if isX(mj)
174
- ret = ''
152
+ ''
175
153
  elsif isX(m)
176
- ret = ">=#{mj}.0.0 <#{(mj.to_i + 1)}.0.0"
154
+ ">=#{mj}.0.0 <#{(mj.to_i + 1)}.0.0"
177
155
  elsif isX(p)
178
- ret = ">=#{mj}.#{m}.0 <#{mj}.#{(m.to_i + 1)}.0"
156
+ ">=#{mj}.#{m}.0 <#{mj}.#{(m.to_i + 1)}.0"
179
157
  elsif pr
180
158
  pr = '-' + pr if (pr[0] != '-')
181
- ret = ">=#{mj}.#{m}.#{p}#{pr} <#{mj}.#{(m.to_i + 1)}.0"
159
+ ">=#{mj}.#{m}.#{p}#{pr} <#{mj}.#{(m.to_i + 1)}.0"
182
160
  else
183
- ret = ">=#{mj}.#{m}.#{p} <#{mj}.#{(m.to_i + 1)}.0"
161
+ ">=#{mj}.#{m}.#{p} <#{mj}.#{(m.to_i + 1)}.0"
184
162
  end
185
- ret
186
163
  end
187
164
  end
188
165
 
@@ -212,9 +189,9 @@ module SemanticRange
212
189
 
213
190
  if xM
214
191
  if gtlt == '>' || gtlt == '<'
215
- ret = '<0.0.0'
192
+ '<0.0.0'
216
193
  else
217
- ret = '*'
194
+ '*'
218
195
  end
219
196
  elsif !gtlt.nil? && gtlt != '' && anyX
220
197
  m = 0 if xm
@@ -239,14 +216,14 @@ module SemanticRange
239
216
  end
240
217
  end
241
218
 
242
- ret = "#{gtlt}#{mj}.#{m}.#{p}"
219
+ "#{gtlt}#{mj}.#{m}.#{p}"
243
220
  elsif xm
244
- ret = ">=#{mj}.0.0 <#{(mj.to_i + 1)}.0.0"
221
+ ">=#{mj}.0.0 <#{(mj.to_i + 1)}.0.0"
245
222
  elsif xp
246
- ret = ">=#{mj}.#{m}.0 <#{mj}.#{(m.to_i + 1)}.0"
223
+ ">=#{mj}.#{m}.0 <#{mj}.#{(m.to_i + 1)}.0"
224
+ else
225
+ ret
247
226
  end
248
-
249
- ret
250
227
  end
251
228
  end
252
229
 
@@ -1,77 +1,45 @@
1
1
  module SemanticRange
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
 
4
4
  class Version
5
- def initialize(version, loose)
5
+ attr_reader :major, :minor, :patch, :prerelease
6
+
7
+ def initialize(version, loose = false)
6
8
  @raw = version
7
9
  @loose = loose
8
10
 
9
- if version.is_a?(Version)
10
- @raw = version = version.raw
11
- end
11
+ @raw = version.raw if version.is_a?(Version)
12
12
 
13
- match = version.strip.match(loose ? LOOSE : FULL)
14
- # TODO error handling
13
+ match = @raw.strip.match(loose ? LOOSE : FULL)
14
+
15
+ raise NoMatchFound.new(version) if match.nil?
15
16
 
16
17
  @major = match[1] ? match[1].to_i : 0
17
18
  @minor = match[2] ? match[2].to_i : 0
18
19
  @patch = match[3] ? match[3].to_i : 0
19
20
 
20
- # TODO error handling
21
-
22
- if !match[4]
23
- @prerelease = []
24
- else
25
- @prerelease = match[4].split('.').map do |id|
26
- if /^[0-9]+$/.match(id)
27
- num = id.to_i
28
- # TODO error handling
29
- else
30
- id
31
- end
32
- end
33
- end
21
+ @prerelease = PreRelease.new match[4]
34
22
 
35
23
  @build = match[5] ? match[5].split('.') : []
36
- @version = format
37
- end
38
-
39
- def version
40
- @version
41
- end
42
-
43
- def raw
44
- @raw
45
- end
46
-
47
- def major
48
- @major
49
- end
50
-
51
- def minor
52
- @minor
53
- end
54
-
55
- def patch
56
- @patch
57
- end
58
-
59
- def prerelease
60
- @prerelease
61
24
  end
62
25
 
63
26
  def format
64
27
  v = "#{@major}.#{@minor}.#{@patch}"
65
- if @prerelease.length > 0
66
- v += '-' + @prerelease.join('.')
67
- end
68
- v
28
+ prerelease.length > 0 ? "#{v}-#{prerelease}" : v
69
29
  end
70
30
 
71
31
  def to_s
72
32
  @version
73
33
  end
74
34
 
35
+ def version
36
+ format
37
+ end
38
+
39
+ def raw
40
+ version
41
+ end
42
+
75
43
  def compare(other)
76
44
  other = Version.new(other, @loose) unless other.is_a?(Version)
77
45
  res = truthy(compare_main(other)) || truthy(compare_pre(other))
@@ -80,7 +48,9 @@ module SemanticRange
80
48
 
81
49
  def compare_main(other)
82
50
  other = Version.new(other, @loose) unless other.is_a?(Version)
83
- truthy(compare_identifiers(@major, other.major)) || truthy(compare_identifiers(@minor, other.minor)) || truthy(compare_identifiers(@patch, other.patch))
51
+ truthy(self.class.compare_identifiers(@major, other.major)) ||
52
+ truthy(self.class.compare_identifiers(@minor, other.minor)) ||
53
+ truthy(self.class.compare_identifiers(@patch, other.patch))
84
54
  end
85
55
 
86
56
  def truthy(val)
@@ -89,35 +59,10 @@ module SemanticRange
89
59
  end
90
60
 
91
61
  def compare_pre(other)
92
- other = Version.new(other, @loose) unless other.is_a?(Version)
93
-
94
- return -1 if truthy(@prerelease.length) && !truthy(other.prerelease.length)
95
-
96
- return 1 if !truthy(@prerelease.length) && truthy(other.prerelease.length)
97
-
98
- return 0 if !truthy(@prerelease.length) && !truthy(other.prerelease.length)
99
-
100
- i = 0
101
- while true
102
- a = @prerelease[i]
103
- b = other.prerelease[i]
104
-
105
- if a.nil? && b.nil?
106
- return 0
107
- elsif b.nil?
108
- return 1
109
- elsif a.nil?
110
- return -1
111
- elsif a == b
112
-
113
- else
114
- return compare_identifiers(a, b)
115
- end
116
- i += 1
117
- end
62
+ prerelease <=> other.prerelease
118
63
  end
119
64
 
120
- def compare_identifiers(a,b)
65
+ def self.compare_identifiers(a,b)
121
66
  anum = /^[0-9]+$/.match(a.to_s)
122
67
  bnum = /^[0-9]+$/.match(b.to_s)
123
68
 
@@ -132,5 +77,103 @@ module SemanticRange
132
77
  a > b ? 1 :
133
78
  0;
134
79
  end
80
+
81
+ def increment!(release, identifier)
82
+ case release
83
+ when 'premajor'
84
+ @prerelease.clear!
85
+ @patch = 0
86
+ @minor = 0
87
+ @major = @major + 1
88
+ increment! 'pre', identifier
89
+ when 'preminor'
90
+ @prerelease.clear!
91
+ @patch = 0
92
+ @minor = @minor + 1
93
+ increment! 'pre', identifier
94
+ when 'prepatch'
95
+ # If this is already a prerelease, it will bump to the next version
96
+ # drop any prereleases that might already exist, since they are not
97
+ # relevant at this point.
98
+ @prerelease.clear!
99
+ increment! 'patch', identifier
100
+ increment! 'pre', identifier
101
+
102
+ # If the input is a non-prerelease version, this acts the same as
103
+ # prepatch.
104
+ when 'prerelease'
105
+ if @prerelease.empty?
106
+ increment! 'patch', identifier
107
+ end
108
+ increment! 'pre', identifier
109
+ when 'major'
110
+ # If this is a pre-major version, bump up to the same major version.
111
+ # Otherwise increment major.
112
+ # 1.0.0-5 bumps to 1.0.0
113
+ # 1.1.0 bumps to 2.0.0
114
+ if @minor != 0 || @patch != 0 || @prerelease.empty?
115
+ @major = @major + 1
116
+ end
117
+ @minor = 0
118
+ @patch = 0
119
+ @prerelease.clear!
120
+ when 'minor'
121
+ # If this is a pre-minor version, bump up to the same minor version.
122
+ # Otherwise increment minor.
123
+ # 1.2.0-5 bumps to 1.2.0
124
+ # 1.2.1 bumps to 1.3.0
125
+ if @patch != 0 || @prerelease.empty?
126
+ @minor = @minor + 1
127
+ end
128
+ @patch = 0
129
+ @prerelease.clear!
130
+ when 'patch'
131
+ # If this is not a pre-release version, it will increment the patch.
132
+ # If it is a pre-release it will bump up to the same patch version.
133
+ # 1.2.0-5 patches to 1.2.0
134
+ # 1.2.0 patches to 1.2.1
135
+ if @prerelease.empty?
136
+ @patch = @patch + 1
137
+ end
138
+ @prerelease.clear!
139
+
140
+ # This probably shouldn't be used publicly.
141
+ # 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
142
+ when 'pre'
143
+ if @prerelease.empty?
144
+ @prerelease.zero!
145
+ else
146
+ parts = @prerelease.parts
147
+ i = parts.length
148
+ while i >= 0
149
+ if parts[i].is_a?(Fixnum)
150
+ parts[i] += 1
151
+ i = -2
152
+ else
153
+ i = i-1
154
+ end
155
+ end
156
+ if i == -1 # didn't increment anything
157
+ parts << 0
158
+ end
159
+ @prerelease = PreRelease.new(parts.join("."))
160
+ end
161
+ if identifier
162
+ # 1.2.0-beta.1 bumps to 1.2.0-beta.2,
163
+ # 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
164
+ if @prerelease.parts[0] == identifier
165
+ unless @prerelease.parts[1].kind_of?(Fixnum)
166
+ @prerelease = PreRelease.new([identifier, 0].join('.'))
167
+ end
168
+ else
169
+ @prerelease = PreRelease.new([identifier, 0].join('.'))
170
+ end
171
+ end
172
+ else
173
+ raise InvalidIncrement.new release
174
+ end
175
+
176
+ self
177
+ end
135
178
  end
136
179
  end
@@ -1,4 +1,5 @@
1
1
  require "semantic_range/version"
2
+ require "semantic_range/pre_release"
2
3
  require "semantic_range/range"
3
4
  require "semantic_range/comparator"
4
5
 
@@ -44,6 +45,9 @@ module SemanticRange
44
45
 
45
46
  MAX_LENGTH = 256
46
47
 
48
+ class InvalidIncrement < StandardError; end
49
+ class NoMatchFound < StandardError; end
50
+
47
51
  def self.ltr(version, range, loose = false)
48
52
  outside(version, range, '<', loose)
49
53
  end
@@ -143,6 +147,7 @@ module SemanticRange
143
147
  end
144
148
 
145
149
  def self.satisfies(version, range, loose = false)
150
+ return false if !valid_range(range, loose)
146
151
  Range.new(range, loose).test(version)
147
152
  end
148
153
 
@@ -232,4 +237,26 @@ module SemanticRange
232
237
  nil
233
238
  end
234
239
  end
240
+
241
+ def self.increment!(version, release, loose, identifier)
242
+ if loose.is_a? String
243
+ identifier = loose
244
+ loose = false
245
+ end
246
+
247
+ Version.new(version, loose).increment!(release, identifier).version
248
+ rescue InvalidIncrement, NoMatchFound
249
+ nil
250
+ end
251
+
252
+ def self.diff(a, b)
253
+ a = Version.new(a, false) unless a.kind_of?(Version)
254
+ b = Version.new(b, false) unless b.kind_of?(Version)
255
+ pre_diff = a.prerelease.to_s != b.prerelease.to_s
256
+ pre = pre_diff ? 'pre' : ''
257
+ return "#{pre}major" if a.major != b.major
258
+ return "#{pre}minor" if a.minor != b.minor
259
+ return "#{pre}patch" if a.patch != b.patch
260
+ return "prerelease" if pre_diff
261
+ end
235
262
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semantic_range
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nesbitt
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-11-13 00:00:00.000000000 Z
11
+ date: 2015-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -72,6 +72,7 @@ files:
72
72
  - bin/setup
73
73
  - lib/semantic_range.rb
74
74
  - lib/semantic_range/comparator.rb
75
+ - lib/semantic_range/pre_release.rb
75
76
  - lib/semantic_range/range.rb
76
77
  - lib/semantic_range/version.rb
77
78
  - semantic_range.gemspec