versus 0.1.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.
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: []