versus 0.1.0 → 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/.index CHANGED
@@ -2,13 +2,15 @@
2
2
  type: ruby
3
3
  revision: 2013
4
4
  sources:
5
- - Index.yml
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: homepage
25
- uri: http://dotruby.github.com
30
+ - type: home
31
+ uri: http://rubyworks.github.com/versus
26
32
  label: Homepage
27
- - type: source
28
- uri: http://github.com/dotruby/version
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
- name: versus
40
- title: Versus
41
- version: 0.1.0
45
+ created: '2006-12-10'
42
46
  summary: Best-of-breed Version Class Library
43
- description: The Versus gem provides a solid Version class along with supporting functionality,
44
- such as version constratints and version dependency resolution.
45
- date: '2013-01-05'
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)
@@ -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
- #@segments >= other and @segments < upver
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
- case which.to_sym
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
@@ -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
- potents = requirements(name, number).map do |(n, c)|
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
@@ -0,0 +1,5 @@
1
+ require 'spectroscope'
2
+ require 'ae'
3
+
4
+ require 'versus'
5
+
@@ -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.1.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-05 00:00:00.000000000 Z
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
- description: The Versus gem provides a solid Version class along with supporting functionality,
48
- such as version constratints and version dependency resolution.
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://dotruby.github.com
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
-