versus 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.index +45 -0
  2. data/.yardopts +7 -0
  3. data/HISTORY.md +11 -0
  4. data/Index.yml +37 -0
  5. data/LICENSE.txt +23 -0
  6. data/README.md +46 -0
  7. data/demo/applique/ae.rb +5 -0
  8. data/demo/applique/main.rb +1 -0
  9. data/demo/constraint/02_initialize.md +44 -0
  10. data/demo/constraint/04_to_proc.md +11 -0
  11. data/demo/constraint/09_to_gem_version.md +10 -0
  12. data/demo/number/02_initialize.md +14 -0
  13. data/demo/number/03_parse.md +23 -0
  14. data/demo/number/04_crush.md +17 -0
  15. data/demo/number/05_build.md +23 -0
  16. data/demo/number/06_cmp.md +100 -0
  17. data/demo/number/07_segments.md +51 -0
  18. data/demo/number/08_bump.md +46 -0
  19. data/demo/number/09_stable_release.md +23 -0
  20. data/demo/number/10_prerelease.md +19 -0
  21. data/demo/number/11_release_candidate.md +15 -0
  22. data/demo/number/19_match.md +10 -0
  23. data/demo/number/20_to_str.md +13 -0
  24. data/demo/resolver/01_initialize.md +23 -0
  25. data/demo/resolver/02_add.md +11 -0
  26. data/demo/resolver/03_libraries.md +24 -0
  27. data/demo/resolver/04_requirements.md +13 -0
  28. data/demo/resolver/05_possibilities.md +13 -0
  29. data/demo/resolver/06_resolve.md +42 -0
  30. data/lib/versus.rb +5 -0
  31. data/lib/versus/constraint.rb +130 -0
  32. data/lib/versus/core_ext.rb +4 -0
  33. data/lib/versus/core_ext/array.rb +11 -0
  34. data/lib/versus/core_ext/kernel.rb +19 -0
  35. data/lib/versus/core_ext/string.rb +10 -0
  36. data/lib/versus/exceptions.rb +8 -0
  37. data/lib/versus/file.rb +157 -0
  38. data/lib/versus/file/jeweler_format.rb +49 -0
  39. data/lib/versus/file/plain_format.rb +39 -0
  40. data/lib/versus/number.rb +516 -0
  41. data/lib/versus/resolver.rb +303 -0
  42. metadata +124 -0
@@ -0,0 +1,303 @@
1
+ module Version
2
+
3
+ # Version resolution takes a requirements list and can reduce it
4
+ # to a best fit list.
5
+ #
6
+ class Resolver
7
+
8
+ #
9
+ #
10
+ #
11
+ def initialize(*available)
12
+ @libraries = Hash.new{ |h,k| h[k] = {} }
13
+
14
+ available.each do |name, version, requirements|
15
+ add(name, version, requirements || {})
16
+ end
17
+ end
18
+
19
+ #
20
+ # Map of dependencies by name and version to requirements.
21
+ #
22
+ attr :libraries
23
+
24
+ #
25
+ # Add available library.
26
+ #
27
+ def add(name, version, requirements={})
28
+ name = name.to_s
29
+ number = Number.parse(version)
30
+ requires = {}
31
+
32
+ requirements.each do |n,c|
33
+ requires[n.to_s] = Constraint.parse(c)
34
+ end
35
+
36
+ @libraries[name][number] = requires
37
+ end
38
+
39
+ #
40
+ # Look-up requirements for a given name and version.
41
+ #
42
+ def requirements(name, number)
43
+ number = Version::Number.parse(number) #unless Version::Number === number
44
+ @libraries[name][number]
45
+ end
46
+
47
+ #
48
+ # Returns possibilities sorted in descending order.
49
+ #
50
+ def possibilities(name, constraint)
51
+ name = name.to_s
52
+ constraint = Constraint.parse(constraint)
53
+
54
+ list = []
55
+ @libraries[name].each do |version, _|
56
+ if constraint.match?(version)
57
+ list << [name, version]
58
+ end
59
+ end
60
+
61
+ list.sort!{ |a,b| b[1] <=> a[1] }
62
+ end
63
+
64
+ #
65
+ # TODO: support resolution of multiple [name, versions] at once.
66
+ #
67
+ def resolve(name, number)
68
+ name = name.to_s
69
+ number = Number.parse(number)
70
+
71
+ sheet = {}
72
+
73
+ result = resolve_(name, number, sheet)
74
+
75
+ #list.each do |name, version|
76
+ # name = name.to_s
77
+ # number = Number.parse(version)
78
+ #
79
+ # resolve_(name, number, sheet)
80
+ #end
81
+ result ? sheet : nil
82
+ end
83
+
84
+ private
85
+
86
+ #
87
+ #
88
+ #
89
+ def resolve_(name, number, sheet={})
90
+ return false unless settle(name, number, sheet)
91
+
92
+ potents = requirements(name, number).map do |(n, c)|
93
+ possibilities(n,c)
94
+ end
95
+
96
+ return sheet if potents.empty?
97
+
98
+ vectors = product(*potents)
99
+
100
+ success = vectors.find do |vector|
101
+ resolve_vector(vector, sheet)
102
+ end
103
+
104
+ return success
105
+ end
106
+
107
+ #
108
+ #
109
+ #
110
+ def resolve_vector(vector, sheet)
111
+ vector.each do |(n,v)|
112
+ r = resolve_(n, v, sheet)
113
+ return false unless r
114
+ end
115
+ return sheet
116
+ end
117
+
118
+ #
119
+ #
120
+ #
121
+ def settle(name, number, sheet={})
122
+ if sheet[name]
123
+ return false if sheet[name] != number
124
+ else
125
+ sheet[name] = number
126
+ end
127
+ return true
128
+ end
129
+
130
+ #
131
+ #
132
+ #
133
+ def product(*list)
134
+ return [] if list.empty?
135
+ head, *rest = *list
136
+ head.product(*rest)
137
+ end
138
+
139
+ =begin
140
+ #
141
+ #
142
+ #
143
+ def collect_possibilites
144
+ possibilites = Hash.new{ |h,k| h[k] = Hash.new{|h2,k2| h2[k2] = [] } }
145
+ constrained_versions = collect_constraints
146
+ libraries.each do |name, version, requirements|
147
+ requirements.each do |(n,c)|
148
+ possibilites[[name, version]][n] << constrained_versions[[n,c]]
149
+ end
150
+ end
151
+ possibilites
152
+ end
153
+
154
+ #
155
+ # Iterate over all requirements and collect all possible versions
156
+ # that fit their constraints.
157
+ #
158
+ def collect_constraints
159
+ constraints = {}
160
+ @libraries.each do |name, version, requirements|
161
+ requirements.each do |n,c|
162
+ next if constraints[[n,c]]
163
+ constraints[[n,c]] = matching_versions(n,c)
164
+ end
165
+ end
166
+ constraints
167
+ end
168
+
169
+ #
170
+ #
171
+ #
172
+ def matching_versions(name, constraint)
173
+ vers = @versions[name].select{ |v| constraint.fits?(v) }.sort
174
+ vers.map{ |v| [name, v] }
175
+ end
176
+ =end
177
+
178
+
179
+
180
+ =begin
181
+ # Resolve dependencies for given list of name-version.
182
+ #
183
+ # @param [Array] list
184
+ #
185
+ def resolve(list)
186
+ requirements = collect_requirements(list)
187
+
188
+ # time to do some backtracking
189
+ first, *rest = *requirements.values
190
+ first.product(*rest).find |possibility|
191
+ valid?(possibility)
192
+ end
193
+ end
194
+
195
+ #
196
+ # Collect requirements for given set of desired entries.
197
+ #
198
+ # TODO: Reduce requirements for same names
199
+ #
200
+ def collect_requirements(list)
201
+ requirements = {}
202
+ list.each do |(name, version)|
203
+ if @requirements.key?([name,version])
204
+ @requirements[[name,version]].each do |(n,c)|
205
+ next if requirements[[n,c]]
206
+ requirements[[n,c]] = matching_versions(n,c)
207
+ end
208
+ else
209
+ raise "no resolution - no available entry for #{name}-#{verison}"
210
+ end
211
+ end
212
+ requirements
213
+ end
214
+
215
+ #
216
+ #
217
+ #
218
+ def resolve_
219
+ reqs = {}
220
+ constraints.each do |name, *cons|
221
+ reqs[name] = reduce(*cons)
222
+ end
223
+ reqs
224
+ end
225
+
226
+ #
227
+ #
228
+ #
229
+ def constraints(list)
230
+ cons = {}
231
+ list.each do |(name, constraint)|
232
+ cons[name.to_s] ||= []
233
+ cons[name.to_s] << Constraint.parse(constraint)
234
+ end
235
+ cons
236
+ end
237
+ =end
238
+
239
+ #
240
+ #
241
+ #
242
+ def reduce(*constraints)
243
+ exact, least, most = nil , nil, nil
244
+
245
+ constraints.each do |c|
246
+ case c.op
247
+ when '==', '='
248
+ if exact
249
+ if exact != c.number
250
+ exact, least, most = nil, nil, nil
251
+ break
252
+ end
253
+ else
254
+ exact = c
255
+ end
256
+ when '<'
257
+ if least
258
+ if c.number <= least.number
259
+ least = c
260
+ end
261
+ else
262
+ least = c
263
+ end
264
+ when '>'
265
+ if most
266
+ if c.number >= most.number
267
+ most = c
268
+ end
269
+ else
270
+ most = c
271
+ end
272
+ when '<='
273
+ if least
274
+ if c.number < least.number
275
+ least = c
276
+ end
277
+ else
278
+ least = c
279
+ end
280
+ when '>='
281
+ if most
282
+ if c.number > most.number
283
+ most = c
284
+ end
285
+ else
286
+ most = c
287
+ end
288
+ when '=~'
289
+ # TODO
290
+ end
291
+ end
292
+
293
+ # there be only one!
294
+ return nil if exact && least
295
+ return nil if exact && most
296
+ return nil if least && most
297
+
298
+ exact || least || most
299
+ end
300
+
301
+ end
302
+
303
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: versus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - trans
9
+ - postmodern
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-01-05 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: qed
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: ae
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
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.
49
+ email:
50
+ - transfire@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files:
54
+ - LICENSE.txt
55
+ - HISTORY.md
56
+ - README.md
57
+ files:
58
+ - .index
59
+ - .yardopts
60
+ - demo/number/04_crush.md
61
+ - demo/number/02_initialize.md
62
+ - demo/number/09_stable_release.md
63
+ - demo/number/03_parse.md
64
+ - demo/number/20_to_str.md
65
+ - demo/number/10_prerelease.md
66
+ - demo/number/05_build.md
67
+ - demo/number/19_match.md
68
+ - demo/number/06_cmp.md
69
+ - demo/number/08_bump.md
70
+ - demo/number/07_segments.md
71
+ - demo/number/11_release_candidate.md
72
+ - demo/applique/main.rb
73
+ - demo/applique/ae.rb
74
+ - demo/resolver/06_resolve.md
75
+ - demo/resolver/04_requirements.md
76
+ - demo/resolver/02_add.md
77
+ - demo/resolver/03_libraries.md
78
+ - demo/resolver/05_possibilities.md
79
+ - demo/resolver/01_initialize.md
80
+ - demo/constraint/04_to_proc.md
81
+ - demo/constraint/02_initialize.md
82
+ - demo/constraint/09_to_gem_version.md
83
+ - lib/versus.rb
84
+ - lib/versus/file.rb
85
+ - lib/versus/exceptions.rb
86
+ - lib/versus/constraint.rb
87
+ - lib/versus/core_ext/array.rb
88
+ - lib/versus/core_ext/kernel.rb
89
+ - lib/versus/core_ext/string.rb
90
+ - lib/versus/file/jeweler_format.rb
91
+ - lib/versus/file/plain_format.rb
92
+ - lib/versus/resolver.rb
93
+ - lib/versus/core_ext.rb
94
+ - lib/versus/number.rb
95
+ - LICENSE.txt
96
+ - Index.yml
97
+ - HISTORY.md
98
+ - README.md
99
+ homepage: http://dotruby.github.com
100
+ licenses:
101
+ - BSD-2-Clause
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.23
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Best-of-breed Version Class Library
124
+ test_files: []