versus 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.index +22 -12
- data/HISTORY.md +13 -0
- data/README.md +1 -1
- data/lib/versus/number.rb +21 -2
- data/lib/versus/resolver.rb +64 -2
- data/spec/helper.rb +5 -0
- data/spec/resolver/spec_contraints.rb +63 -0
- data/spec/resolver/spec_scenarios.rb +49 -0
- metadata +31 -7
- data/Index.yml +0 -37
data/.index
CHANGED
@@ -2,13 +2,15 @@
|
|
2
2
|
type: ruby
|
3
3
|
revision: 2013
|
4
4
|
sources:
|
5
|
-
-
|
5
|
+
- var
|
6
6
|
authors:
|
7
7
|
- name: trans
|
8
8
|
email: transfire@gmail.com
|
9
9
|
- name: postmodern
|
10
10
|
website: http://trans.github.com
|
11
|
-
organizations:
|
11
|
+
organizations:
|
12
|
+
- name: Rubyworks
|
13
|
+
website: http://rubyworks.github.com/
|
12
14
|
requirements:
|
13
15
|
- groups:
|
14
16
|
- test
|
@@ -18,14 +20,18 @@ requirements:
|
|
18
20
|
- test
|
19
21
|
development: true
|
20
22
|
name: ae
|
23
|
+
- groups:
|
24
|
+
- test
|
25
|
+
development: true
|
26
|
+
name: spectroscope
|
21
27
|
conflicts: []
|
22
28
|
alternatives: []
|
23
29
|
resources:
|
24
|
-
- type:
|
25
|
-
uri: http://
|
30
|
+
- type: home
|
31
|
+
uri: http://rubyworks.github.com/versus
|
26
32
|
label: Homepage
|
27
|
-
- type:
|
28
|
-
uri: http://github.com/
|
33
|
+
- type: code
|
34
|
+
uri: http://github.com/rubyworks/versus
|
29
35
|
label: Source Code
|
30
36
|
repositories: []
|
31
37
|
categories: []
|
@@ -36,10 +42,14 @@ copyrights:
|
|
36
42
|
- holder: Rubyworks
|
37
43
|
year: 2011
|
38
44
|
license: BSD-2-Clause
|
39
|
-
|
40
|
-
title: Versus
|
41
|
-
version: 0.1.0
|
45
|
+
created: '2006-12-10'
|
42
46
|
summary: Best-of-breed Version Class Library
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
title: Versus
|
48
|
+
version: 0.2.0
|
49
|
+
name: versus
|
50
|
+
description: ! 'The Versus gem provides a solid Version class along with supporting
|
51
|
+
|
52
|
+
functionality, such as version constratints and version dependency
|
53
|
+
|
54
|
+
resolution.'
|
55
|
+
date: '2013-01-07'
|
data/HISTORY.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# RELEASE HISTORY
|
2
2
|
|
3
|
+
## 0.2.0 / 2013-01-07
|
4
|
+
|
5
|
+
This release fixes a bug in the Resolver that can lead to inifinite recursion
|
6
|
+
if one entry requires another that in turn requires the former. Also, resolution
|
7
|
+
failures are now tracked so that a nice list of the culprits can be had, helpful
|
8
|
+
for trouble-shooting unsuccessful resolutions.
|
9
|
+
|
10
|
+
Changes:
|
11
|
+
|
12
|
+
* Prevent possible infinite recustion in Resolver#resolve.
|
13
|
+
* Keep record of resolution failures.
|
14
|
+
|
15
|
+
|
3
16
|
## 0.1.0 / 2013-01-05
|
4
17
|
|
5
18
|
While the code is beening sitting around on my hard drive for nearly
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[Homepage](http://rubyworks.github.com/versus) /
|
2
2
|
[Report Issue](http://github.com/rubyworks/versus) /
|
3
3
|
[Source Code](http://github.com/rubyworks/versus)
|
4
|
-
( )
|
4
|
+
( [![Build Status](https://travis-ci.org/rubyworks/versus.png)](https://travis-ci.org/rubyworks/versus) )
|
5
5
|
|
6
6
|
|
7
7
|
# [Versus](http://rubyworks.github.com/versus)
|
data/lib/versus/number.rb
CHANGED
@@ -287,7 +287,11 @@ module Version
|
|
287
287
|
# FIXME: Ensure it can handle trailing state.
|
288
288
|
def =~(other)
|
289
289
|
upver = other.bump(:last)
|
290
|
-
|
290
|
+
if other.size > 1
|
291
|
+
upver = other.bump(-2)
|
292
|
+
else
|
293
|
+
|
294
|
+
end
|
291
295
|
self >= other and self < upver
|
292
296
|
end
|
293
297
|
|
@@ -333,7 +337,11 @@ module Version
|
|
333
337
|
# #=> "1.3.0.rc.1"
|
334
338
|
#
|
335
339
|
def bump(which=:patch)
|
336
|
-
|
340
|
+
which = which.to_sym unless Integer === which
|
341
|
+
|
342
|
+
case which
|
343
|
+
when Integer
|
344
|
+
bump_at(which)
|
337
345
|
when :major, :first
|
338
346
|
bump_major
|
339
347
|
when :minor
|
@@ -349,6 +357,7 @@ module Version
|
|
349
357
|
when :last
|
350
358
|
bump_last
|
351
359
|
else
|
360
|
+
# TODO: why is this not an error?
|
352
361
|
self.class.new(@tuple.dup.compact)
|
353
362
|
end
|
354
363
|
end
|
@@ -368,6 +377,16 @@ module Version
|
|
368
377
|
self.class[major, minor, inc(patch)]
|
369
378
|
end
|
370
379
|
|
380
|
+
#
|
381
|
+
def bump_at(index)
|
382
|
+
i = index
|
383
|
+
if n = inc(@tuple[i])
|
384
|
+
v = @tuple[0...i] + [n] + (@tuple[i+1] ? [1] : [])
|
385
|
+
else
|
386
|
+
v = @tuple[0...i]
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
371
390
|
#
|
372
391
|
def bump_state
|
373
392
|
if i = state_index
|
data/lib/versus/resolver.rb
CHANGED
@@ -6,7 +6,10 @@ module Version
|
|
6
6
|
class Resolver
|
7
7
|
|
8
8
|
#
|
9
|
+
# Initialize new Resolver.
|
9
10
|
#
|
11
|
+
# @param [Array] available
|
12
|
+
# List of name, version and requirements for each possible library.
|
10
13
|
#
|
11
14
|
def initialize(*available)
|
12
15
|
@libraries = Hash.new{ |h,k| h[k] = {} }
|
@@ -21,9 +24,24 @@ module Version
|
|
21
24
|
#
|
22
25
|
attr :libraries
|
23
26
|
|
27
|
+
#
|
28
|
+
# List of library names and versions of failed resolutions
|
29
|
+
# subsequent to calling `#resolve`.
|
30
|
+
#
|
31
|
+
#attr :failures
|
32
|
+
|
24
33
|
#
|
25
34
|
# Add available library.
|
26
35
|
#
|
36
|
+
# @param [String] name
|
37
|
+
# The name of the library.
|
38
|
+
#
|
39
|
+
# @param [String,Version::Number] version
|
40
|
+
# Version number of library.
|
41
|
+
#
|
42
|
+
# @param [Hash] requirements
|
43
|
+
# Requirements for the library in the form of `{name=>version_constraint}`.
|
44
|
+
#
|
27
45
|
def add(name, version, requirements={})
|
28
46
|
name = name.to_s
|
29
47
|
number = Number.parse(version)
|
@@ -68,6 +86,9 @@ module Version
|
|
68
86
|
name = name.to_s
|
69
87
|
number = Number.parse(number)
|
70
88
|
|
89
|
+
@cache = {}
|
90
|
+
@failures = []
|
91
|
+
|
71
92
|
sheet = {}
|
72
93
|
|
73
94
|
result = resolve_(name, number, sheet)
|
@@ -81,18 +102,47 @@ module Version
|
|
81
102
|
result ? sheet : nil
|
82
103
|
end
|
83
104
|
|
105
|
+
#
|
106
|
+
# Returns a mapping of unresolvable requirements. The key of the Hash is the
|
107
|
+
# library that has the requirements and the value of the Hash is an Array
|
108
|
+
# of the requirements that could be not be found in the library list.
|
109
|
+
#
|
110
|
+
# @return [Hash] Unresolved requirements
|
111
|
+
#
|
112
|
+
def unresolved
|
113
|
+
list = Hash.new{ |h,k| h[k] = [] }
|
114
|
+
@failures.each do |name, number|
|
115
|
+
requirements(name, number).each do |rname, rnumber|
|
116
|
+
list[[name,number]] << [rname, rnumber] if possibilities(rname, rnumber.to_s).empty?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
list
|
120
|
+
end
|
121
|
+
|
84
122
|
private
|
85
123
|
|
86
124
|
#
|
87
125
|
#
|
88
126
|
#
|
89
127
|
def resolve_(name, number, sheet={})
|
128
|
+
# prevent infinite recursion
|
129
|
+
return sheet if @cache[[name,number]]
|
130
|
+
@cache[[name,number]] = true
|
131
|
+
|
90
132
|
return false unless settle(name, number, sheet)
|
91
133
|
|
92
|
-
|
134
|
+
requirements = requirements(name, number)
|
135
|
+
|
136
|
+
# there are no requirements to resolve
|
137
|
+
return sheet if requirements.empty?
|
138
|
+
|
139
|
+
# what possibilites exist for resolving all the requirements
|
140
|
+
potents = requirements.map do |(n, c)|
|
93
141
|
possibilities(n,c)
|
94
142
|
end
|
95
143
|
|
144
|
+
# TODO: I think this might be a mistake, if there are no possibilities then is it not
|
145
|
+
# a failed resolution? Consider adding to failures and returning false instead.
|
96
146
|
return sheet if potents.empty?
|
97
147
|
|
98
148
|
vectors = product(*potents)
|
@@ -101,9 +151,21 @@ module Version
|
|
101
151
|
resolve_vector(vector, sheet)
|
102
152
|
end
|
103
153
|
|
154
|
+
unless success
|
155
|
+
@failures << [name, number] unless @failures.include?([name, number])
|
156
|
+
end
|
157
|
+
|
104
158
|
return success
|
105
159
|
end
|
106
160
|
|
161
|
+
#
|
162
|
+
#
|
163
|
+
#
|
164
|
+
def cached(name, number, sheet)
|
165
|
+
@cache[[name, number]] = true
|
166
|
+
sheet
|
167
|
+
end
|
168
|
+
|
107
169
|
#
|
108
170
|
#
|
109
171
|
#
|
@@ -285,7 +347,7 @@ module Version
|
|
285
347
|
else
|
286
348
|
most = c
|
287
349
|
end
|
288
|
-
when '=~'
|
350
|
+
when '=~', '~>'
|
289
351
|
# TODO
|
290
352
|
end
|
291
353
|
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
describe Version::Resolver do
|
4
|
+
|
5
|
+
it "resolves greater than constraints" do
|
6
|
+
resolver = Version::Resolver.new
|
7
|
+
resolver.add('foo', '1.0.0', 'bar'=>'> 0.8')
|
8
|
+
resolver.add('bar', '0.1.0')
|
9
|
+
resolver.add('bar', '0.8.0')
|
10
|
+
resolver.add('bar', '1.0.0')
|
11
|
+
result = resolver.resolve('foo', '1.0.0')
|
12
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['1.0.0']}
|
13
|
+
end
|
14
|
+
|
15
|
+
it "resolves greater than or equal constraints" do
|
16
|
+
resolver = Version::Resolver.new
|
17
|
+
resolver.add('foo', '1.0.0', 'bar'=>'>= 0.8')
|
18
|
+
resolver.add('bar', '0.1.0')
|
19
|
+
resolver.add('bar', '0.8.0')
|
20
|
+
resolver.add('bar', '1.0.0')
|
21
|
+
result = resolver.resolve('foo', '1.0.0')
|
22
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['1.0.0']}
|
23
|
+
|
24
|
+
resolver = Version::Resolver.new
|
25
|
+
resolver.add('foo', '1.0.0', 'bar'=>'>= 0.8')
|
26
|
+
resolver.add('bar', '0.1.0')
|
27
|
+
resolver.add('bar', '0.8.0')
|
28
|
+
result = resolver.resolve('foo', '1.0.0')
|
29
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['0.8.0']}
|
30
|
+
end
|
31
|
+
|
32
|
+
it "resolves lesser than constraints" do
|
33
|
+
resolver = Version::Resolver.new
|
34
|
+
resolver.add('foo', '1.0.0', 'bar'=>'< 1.0.0')
|
35
|
+
resolver.add('bar', '0.1.0')
|
36
|
+
resolver.add('bar', '0.8.0')
|
37
|
+
resolver.add('bar', '1.0.0')
|
38
|
+
result = resolver.resolve('foo', '1.0.0')
|
39
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['0.8.0']}
|
40
|
+
end
|
41
|
+
|
42
|
+
it "resolves lesser than or equal constraints" do
|
43
|
+
resolver = Version::Resolver.new
|
44
|
+
resolver.add('foo', '1.0.0', 'bar'=>'<= 1.0.0')
|
45
|
+
resolver.add('bar', '0.1.0')
|
46
|
+
resolver.add('bar', '0.8.0')
|
47
|
+
resolver.add('bar', '1.0.0')
|
48
|
+
result = resolver.resolve('foo', '1.0.0')
|
49
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['1.0.0']}
|
50
|
+
end
|
51
|
+
|
52
|
+
it "resolves semantically equal constraints" do
|
53
|
+
resolver = Version::Resolver.new
|
54
|
+
resolver.add('foo', '1.0.0', 'bar'=>'~> 1.0.0')
|
55
|
+
resolver.add('bar', '1.0.1')
|
56
|
+
resolver.add('bar', '1.1.0')
|
57
|
+
resolver.add('bar', '2.0.0')
|
58
|
+
result = resolver.resolve('foo', '1.0.0')
|
59
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['1.1.0']}
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
describe Version::Resolver do
|
4
|
+
|
5
|
+
it "resolves complex requirements - example 1" do
|
6
|
+
resolver = Version::Resolver.new
|
7
|
+
resolver.add('foo', '1.0.0', 'bar'=>'> 1.0.0', 'baz'=>'> 2.0.0')
|
8
|
+
resolver.add('bar', '1.0.0', 'baz'=>'= 3.1.0')
|
9
|
+
resolver.add('bar', '2.0.0', 'baz'=>'= 3.1.0')
|
10
|
+
resolver.add('baz', '2.9.0')
|
11
|
+
resolver.add('baz', '3.1.0')
|
12
|
+
resolver.add('baz', '3.2.0')
|
13
|
+
result = resolver.resolve('foo', '1.0.0')
|
14
|
+
result.assert == { 'foo'=>Version['1.0.0'], 'bar'=>Version['2.0.0'], 'baz'=>Version['3.1.0'] }
|
15
|
+
end
|
16
|
+
|
17
|
+
it "resolves complex requirements - example 2" do
|
18
|
+
resolver = Version::Resolver.new
|
19
|
+
resolver.add('foo', '1.0.0', 'bar'=>'> 1.0', 'baz'=>'> 2.0')
|
20
|
+
resolver.add('bar', '1.0.0', 'baz'=>'= 3.1')
|
21
|
+
resolver.add('bar', '2.0.0', 'baz'=>'= 3.1')
|
22
|
+
resolver.add('baz', '2.9.0')
|
23
|
+
resolver.add('baz', '3.1.0')
|
24
|
+
resolver.add('baz', '3.2.0')
|
25
|
+
result = resolver.resolve('foo', '1.0.0')
|
26
|
+
result.assert == { 'foo'=>Version['1.0.0'], 'bar'=>Version['2.0.0'], 'baz'=>Version['3.1.0'] }
|
27
|
+
end
|
28
|
+
|
29
|
+
it "resolves complex requirements - example 3" do
|
30
|
+
resolver = Version::Resolver.new
|
31
|
+
resolver.add('foo', '1.0.0', 'bar'=>'> 1.0.0', 'baz'=>'> 2.0.0')
|
32
|
+
resolver.add('bar', '1.0.0', 'baz'=>'= 3.1.0')
|
33
|
+
resolver.add('bar', '2.0.0', 'baz'=>'> 3.1.0')
|
34
|
+
resolver.add('baz', '3.1.0')
|
35
|
+
resolver.add('baz', '3.2.0')
|
36
|
+
result = resolver.resolve('foo', '1.0.0')
|
37
|
+
result.assert == { 'foo'=>Version['1.0.0'], 'bar'=>Version['2.0.0'], 'baz'=>Version['3.2.0'] }
|
38
|
+
end
|
39
|
+
|
40
|
+
it "does not infinitely recurse" do
|
41
|
+
resolver = Version::Resolver.new
|
42
|
+
resolver.add('foo', '1.0.0', 'bar'=>'>= 1.0.0')
|
43
|
+
resolver.add('bar', '1.0.0', 'foo'=>'>= 1.0.0')
|
44
|
+
result = resolver.resolve('foo', '1.0.0')
|
45
|
+
result.assert == {'foo'=>Version['1.0.0'], 'bar'=>Version['1.0.0']}
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: versus
|
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:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-01-
|
13
|
+
date: 2013-01-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: qed
|
@@ -44,8 +44,27 @@ dependencies:
|
|
44
44
|
- - ! '>='
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
|
-
|
48
|
-
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: spectroscope
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
description: ! 'The Versus gem provides a solid Version class along with supporting
|
64
|
+
|
65
|
+
functionality, such as version constratints and version dependency
|
66
|
+
|
67
|
+
resolution.'
|
49
68
|
email:
|
50
69
|
- transfire@gmail.com
|
51
70
|
executables: []
|
@@ -92,11 +111,13 @@ files:
|
|
92
111
|
- lib/versus/resolver.rb
|
93
112
|
- lib/versus/core_ext.rb
|
94
113
|
- lib/versus/number.rb
|
114
|
+
- spec/helper.rb
|
115
|
+
- spec/resolver/spec_scenarios.rb
|
116
|
+
- spec/resolver/spec_contraints.rb
|
95
117
|
- LICENSE.txt
|
96
|
-
- Index.yml
|
97
118
|
- HISTORY.md
|
98
119
|
- README.md
|
99
|
-
homepage: http://
|
120
|
+
homepage: http://rubyworks.github.com/versus
|
100
121
|
licenses:
|
101
122
|
- BSD-2-Clause
|
102
123
|
post_install_message:
|
@@ -121,4 +142,7 @@ rubygems_version: 1.8.23
|
|
121
142
|
signing_key:
|
122
143
|
specification_version: 3
|
123
144
|
summary: Best-of-breed Version Class Library
|
124
|
-
test_files:
|
145
|
+
test_files:
|
146
|
+
- spec/helper.rb
|
147
|
+
- spec/resolver/spec_scenarios.rb
|
148
|
+
- spec/resolver/spec_contraints.rb
|
data/Index.yml
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name:
|
3
|
-
versus
|
4
|
-
|
5
|
-
version:
|
6
|
-
0.1.0
|
7
|
-
|
8
|
-
title:
|
9
|
-
Versus
|
10
|
-
|
11
|
-
summary:
|
12
|
-
Best-of-breed Version Class Library
|
13
|
-
|
14
|
-
description:
|
15
|
-
The Versus gem provides a solid Version class along with supporting
|
16
|
-
functionality, such as version constratints and version dependency
|
17
|
-
resolution.
|
18
|
-
|
19
|
-
requirements:
|
20
|
-
- qed (test)
|
21
|
-
- ae (test)
|
22
|
-
|
23
|
-
authors:
|
24
|
-
- name: trans
|
25
|
-
email: transfire@gmail.com
|
26
|
-
- name: postmodern
|
27
|
-
website: 'http://trans.github.com'
|
28
|
-
|
29
|
-
resources:
|
30
|
-
homepage: http://dotruby.github.com
|
31
|
-
source: http://github.com/dotruby/version
|
32
|
-
|
33
|
-
copyrights:
|
34
|
-
- year: 2011
|
35
|
-
holder: Rubyworks
|
36
|
-
license: BSD-2-Clause
|
37
|
-
|