indexer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.index +54 -0
  2. data/HISTORY.md +9 -0
  3. data/README.md +145 -0
  4. data/bin/index +7 -0
  5. data/data/indexer/r2013/index.kwalify +175 -0
  6. data/data/indexer/r2013/index.yes +172 -0
  7. data/data/indexer/r2013/index.yesi +67 -0
  8. data/data/indexer/r2013/ruby.txt +35 -0
  9. data/data/indexer/r2013/yaml.txt +30 -0
  10. data/lib/indexer.rb +65 -0
  11. data/lib/indexer/attributes.rb +171 -0
  12. data/lib/indexer/command.rb +260 -0
  13. data/lib/indexer/components.rb +8 -0
  14. data/lib/indexer/components/author.rb +140 -0
  15. data/lib/indexer/components/conflict.rb +78 -0
  16. data/lib/indexer/components/copyright.rb +95 -0
  17. data/lib/indexer/components/dependency.rb +18 -0
  18. data/lib/indexer/components/organization.rb +133 -0
  19. data/lib/indexer/components/repository.rb +140 -0
  20. data/lib/indexer/components/requirement.rb +360 -0
  21. data/lib/indexer/components/resource.rb +209 -0
  22. data/lib/indexer/conversion.rb +14 -0
  23. data/lib/indexer/conversion/gemfile.rb +44 -0
  24. data/lib/indexer/conversion/gemspec.rb +114 -0
  25. data/lib/indexer/conversion/gemspec_exporter.rb +304 -0
  26. data/lib/indexer/core_ext.rb +4 -0
  27. data/lib/indexer/error.rb +23 -0
  28. data/lib/indexer/gemfile.rb +75 -0
  29. data/lib/indexer/importer.rb +144 -0
  30. data/lib/indexer/importer/file.rb +94 -0
  31. data/lib/indexer/importer/gemfile.rb +27 -0
  32. data/lib/indexer/importer/gemspec.rb +43 -0
  33. data/lib/indexer/importer/html.rb +289 -0
  34. data/lib/indexer/importer/markdown.rb +45 -0
  35. data/lib/indexer/importer/ruby.rb +47 -0
  36. data/lib/indexer/importer/version.rb +38 -0
  37. data/lib/indexer/importer/yaml.rb +46 -0
  38. data/lib/indexer/loadable.rb +159 -0
  39. data/lib/indexer/metadata.rb +879 -0
  40. data/lib/indexer/model.rb +237 -0
  41. data/lib/indexer/revision.rb +43 -0
  42. data/lib/indexer/valid.rb +287 -0
  43. data/lib/indexer/validator.rb +313 -0
  44. data/lib/indexer/version/constraint.rb +124 -0
  45. data/lib/indexer/version/exceptions.rb +11 -0
  46. data/lib/indexer/version/number.rb +497 -0
  47. metadata +141 -0
@@ -0,0 +1,140 @@
1
+ module Indexer
2
+
3
+ # The Repository class models a packages SCM repository location.
4
+ # It consists of two parts, the `scm` type of repository, it's `url`.
5
+ #
6
+ class Repository < Model
7
+
8
+ # Parse `data` returning a new Repository instance.
9
+ #
10
+ # @param data [String,Array<String>,Array<Hash>,Hash]
11
+ # Repository information.
12
+ #
13
+ # @return [Repository] repository instance
14
+ #--
15
+ # TODO: Should String be allowed, and thus no `id`?
16
+ #++
17
+ def self.parse(data)
18
+ case data
19
+ when String
20
+ new('uri'=>data)
21
+ when Array
22
+ h, d = {}, data.dup # TODO: data.rekey(&:to_s)
23
+ h.update(d.pop) while Hash === d.last
24
+ h['name'] = d.shift.to_s unless d.empty?
25
+ h['uri'] = d.shift.to_s unless d.empty?
26
+ h['scm'] = d.shift.to_s unless d.empty?
27
+ new(h)
28
+ when Hash
29
+ new(data)
30
+ else
31
+ raise(ValidationError, "not a valid repository")
32
+ end
33
+ end
34
+
35
+ #
36
+ # Initialize new Repository instance.
37
+ #
38
+ def initialize(data={})
39
+ super(data)
40
+
41
+ self.scm = infer_scm(uri) unless scm
42
+ end
43
+
44
+ #
45
+ # A name that can be used to identify the purpose of a
46
+ # particular repository.
47
+ #
48
+ attr_reader :name
49
+
50
+ #
51
+ # Set the repository name. This can be any one line description but
52
+ # it generally should be a brief one-word indictor such as "origin"
53
+ # "upstream", "experimental", "joes-fork", etc.
54
+ #
55
+ def name=(name)
56
+ Valid.oneline!(name) # should be word!
57
+ @data[:name] = name.to_str
58
+ end
59
+
60
+ #
61
+ # The repository's URI.
62
+ #
63
+ attr_reader :uri
64
+
65
+ #
66
+ # Set repository URI
67
+ #
68
+ def uri=(uri)
69
+ Valid.oneline!(uri)
70
+ #Valid.uri!(uri) # TODO: any other limitations?
71
+ @data[:scm] = infer_scm(uri)
72
+ @data[:uri] = uri
73
+ end
74
+
75
+ #
76
+ #
77
+ #
78
+ attr_reader :scm
79
+
80
+ #
81
+ # Set the SCM type of repository. The type is a single downcased word.
82
+ # Generally recognized types are:
83
+ #
84
+ # * git
85
+ # * hg
86
+ # * svn
87
+ # * cvs
88
+ # * darcs
89
+ #
90
+ # But any type can be used.
91
+ #
92
+ def scm=(scm)
93
+ Valid.word!(scm)
94
+ @data[:scm] = scm.to_str.downcase
95
+ end
96
+
97
+ #
98
+ # Prefix URI that can be used to link to source code.
99
+ #
100
+ # This name is the traditional one from a time when CVS was the
101
+ # most popular SCM.
102
+ #
103
+ attr_reader :webcvs
104
+
105
+ #
106
+ #
107
+ #
108
+ def webcvs=(uri)
109
+ Valid.oneline!(uri)
110
+ Valid.uri!(uri) # TODO: any other limitations?
111
+ @data[:webcvs] = uri
112
+ end
113
+
114
+ # TODO: Should we rename Repository#webcvs to just #web ?
115
+
116
+ #
117
+ alias_method :web, :webcvs
118
+ alias_method :web=, :webcvs=
119
+
120
+ private
121
+
122
+ #
123
+ def infer_scm(uri)
124
+ case uri
125
+ when /^git:/, /\.git$/
126
+ 'git'
127
+ when /^hg:/, /\.hg$/
128
+ 'hg'
129
+ when /^svn:/
130
+ 'svn'
131
+ when /darcs/
132
+ 'darcs'
133
+ else
134
+ nil
135
+ end
136
+ end
137
+
138
+ end
139
+
140
+ end
@@ -0,0 +1,360 @@
1
+ module Indexer
2
+
3
+ # Requirement class.
4
+ #
5
+ # QUESTION: Does Requirement really need to handle multiple version constraints?
6
+ # Currently this only supports one version constraint.
7
+ #
8
+ class Requirement < Model
9
+
10
+ #
11
+ # Parse `data` into a Requirement instance.
12
+ #
13
+ # TODO: What about respond_to?(:to_str) for String, etc.
14
+ #
15
+ def self.parse(data)
16
+ case data
17
+ when String
18
+ parse_string(data)
19
+ when Array
20
+ parse_array(data)
21
+ when Hash
22
+ parse_hash(data)
23
+ else
24
+ raise(ValidationError, "requirement")
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ #
31
+ #
32
+ def self.parse_hash(data)
33
+ name = (data.delete('name') || data.delete(:name)).to_s
34
+ # make sure groups are strings
35
+ groups = []
36
+ groups << (data.delete('groups') || data.delete(:groups))
37
+ groups << (data.delete('group') || data.delete(:group))
38
+ groups = groups.flatten.compact.map{ |g| g.to_s }
39
+ data[:groups] = groups
40
+ #
41
+ new(name, data)
42
+ end
43
+
44
+ #
45
+ #
46
+ def self.parse_string(string)
47
+ case string.strip
48
+ when /^(\w.*?)\s+(.*?)\s*\((.*?)\)$/
49
+ name = $1
50
+ version = $2
51
+ groups = $3
52
+ when /^(\w.*?)\s+(.*?)$/
53
+ name = $1
54
+ version = $2
55
+ groups = nil
56
+ when /^(\w.*?)$/
57
+ name = $1
58
+ version = nil
59
+ groups = nil
60
+ else
61
+ raise(ValidationError, "requirement")
62
+ end
63
+
64
+ version = nil if version.to_s.strip.empty?
65
+ groups = groups.split(/\s*[,;]?\s+/) if groups
66
+
67
+ specifics = {}
68
+ specifics['version'] = version if version
69
+ specifics['groups'] = groups if groups
70
+
71
+ if groups && !groups.empty? && !groups.include?('runtime')
72
+ specifics['development'] = true
73
+ end
74
+
75
+ new(name, specifics)
76
+ end
77
+
78
+ #
79
+ #
80
+ #
81
+ def self.parse_array(array)
82
+ name, data = *array
83
+ case data
84
+ when Hash
85
+ groups = []
86
+ groups << (data.delete('groups') || data.delete(:groups))
87
+ groups << (data.delete('group') || data.delete(:group))
88
+ groups = groups.flatten.compact.map{ |g| g.to_s }
89
+ data[:groups] = groups
90
+
91
+ new(name.to_s, data)
92
+ when String
93
+ parse_string(name + " " + data)
94
+ else
95
+ raise(ValidationError, "requirement")
96
+ end
97
+ end
98
+
99
+ #
100
+ # Create new instance of Requirement.
101
+ #
102
+ def initialize(name, specifics={})
103
+ specifics[:name] = name
104
+ super(specifics)
105
+ end
106
+
107
+ #
108
+ def initialize_attributes
109
+ @data = {
110
+ :groups => [],
111
+ :engines => [],
112
+ :platforms => [],
113
+ :sources => []
114
+ }
115
+ end
116
+
117
+ public
118
+
119
+ #
120
+ #
121
+ attr_reader :name
122
+
123
+ #
124
+ #
125
+ def name=(name)
126
+ @data[:name] = name.to_s
127
+ end
128
+
129
+ #
130
+ # The requirement's version constraint.
131
+ #
132
+ # @return [Version::Constraint] version constraint.
133
+ #
134
+ attr_reader :version
135
+
136
+ #
137
+ # Set the version constraint.
138
+ #
139
+ # @param version [String,Array,Version::Constraint]
140
+ # Version constraint(s)
141
+ #
142
+ def version=(version)
143
+ @data[:version] = Version::Constraint.parse(version)
144
+ end
145
+
146
+ #
147
+ alias :versions= :version=
148
+
149
+ #
150
+ # Returns true if the requirement is a development requirement.
151
+ #
152
+ # @return [Boolean] development requirement?
153
+ def development?
154
+ @data[:development]
155
+ end
156
+
157
+ #
158
+ # Set the requirement's development flag.
159
+ #
160
+ # @param [Boolean] true/false development requirement
161
+ #
162
+ def development=(boolean)
163
+ @data[:development] = !!boolean
164
+ end
165
+
166
+ #
167
+ # Return `true` if requirement is a runtime requirement.
168
+ #
169
+ # @return [Boolean] runtime requirement?
170
+ def runtime?
171
+ ! @data[:development]
172
+ end
173
+
174
+ #
175
+ # The groups to which the requirement belongs.
176
+ #
177
+ # @return [Array] list of groups
178
+ #
179
+ attr_reader :groups
180
+
181
+ #
182
+ # Set the groups to which the requirement belongs.
183
+ #
184
+
185
+ # @return [Array, String] list of groups
186
+ #
187
+ def groups=(groups)
188
+ @data[:groups] = [groups].flatten
189
+ end
190
+
191
+ # Singular alias for #groups.
192
+ alias :group :groups
193
+ alias :group= :groups=
194
+
195
+ #
196
+ # Is the requirment optional? An optional requirement is recommended
197
+ # but not strictly necessary.
198
+ #
199
+ # @return [Boolean] optional requirement?
200
+ #
201
+ def optional?
202
+ @data[:optional]
203
+ end
204
+
205
+ #
206
+ # Set optional.
207
+ #
208
+ # @param [Boolean] optional requirement?
209
+ #
210
+ def optional=(boolean)
211
+ @data[:optional] = !!boolean
212
+ end
213
+
214
+ #
215
+ # Is the requirment external? An external requirement is one that is only
216
+ # available outside the expected packaging system. For a Ruby application, for example,
217
+ # this would be library not available via rubygems.org, such as a C library that is only
218
+ # avaialble via an operating system's package manager or via a direct download using the
219
+ # "make; make install" compile and installation procedure.
220
+ #
221
+ # @return [Boolean] external requirement?
222
+ #
223
+ def external?
224
+ @data[:external]
225
+ end
226
+
227
+ #
228
+ # Set external.
229
+ #
230
+ # @param [Boolean] external requirement?
231
+ #
232
+ def external=(boolean)
233
+ @data[:external] = !!boolean
234
+ end
235
+
236
+ #
237
+ # Applies only for specified Ruby engines. Each entry can be
238
+ # the `RUBY_ENGINE` value and optionally a version constraint
239
+ # on `RUBY_VERSION`.
240
+ #
241
+ # @return [Array] name and version constraint
242
+ #
243
+ attr :engines
244
+
245
+ #
246
+ # Applies only for specified Ruby engines. Each entry can be
247
+ # the `RUBY_ENGINE` value and optionally a version constraint
248
+ # on `RUBY_VERSION`.
249
+ #
250
+ # @example
251
+ #
252
+ # requirement.engines = [
253
+ # 'ruby 1.8~'
254
+ # ]
255
+ #
256
+ def engines=(engines)
257
+ @data['engines'] = Array(engines).map do |engine|
258
+ case engine
259
+ when String
260
+ name, vers = engine.strip.split(/\s+/)
261
+ vers = nil if vers.empty?
262
+ when Array
263
+ name, vers = *engine
264
+ when Hash
265
+ name = engine['name']
266
+ vers = engine['version']
267
+ end
268
+ e = {}
269
+ e['name'] = name
270
+ e['version'] = Version::Constraint.parse(vers) if vers
271
+ e
272
+ end
273
+ end
274
+
275
+ alias_method :engine, :engines
276
+ alias_method :engine=, :engines=
277
+
278
+ attr :platforms
279
+
280
+ #
281
+ # Applies only for specified platforms. The platform must be verbatim
282
+ # `RUBY_PLATFORM` value.
283
+ #
284
+ # @example
285
+ # requirement.platforms = ['x86_64-linux']
286
+ #
287
+ def platforms=(platforms)
288
+ @data[:platforms] = Array(platforms)
289
+ end
290
+
291
+ alias_method :platform, :platforms
292
+ alias_method :platform=, :platforms=
293
+
294
+ #
295
+ # The public repository resource in which the requirement source code
296
+ # can be found.
297
+ #
298
+ attr :repository
299
+
300
+ #
301
+ # Set the public repository resource in which the requirement
302
+ # source code can be found.
303
+ #
304
+ def repository=(repository)
305
+ @data[:repository] = Repository.parse(repository)
306
+ end
307
+
308
+ alias :repo :repository
309
+ alias :repo= :repository=
310
+
311
+ #
312
+ # Places from which the requirement can be obtained. Generally a source
313
+ # should be a URI, but there is no strict requirement. It can be as
314
+ # simple as a name, e.g. `rubygems` or as specific as a URL to a downloadable
315
+ # `.zip` package.
316
+ #
317
+ # @example
318
+ # requirement.sources = ['http://rubygems.org']
319
+ #
320
+ attr :sources
321
+
322
+ #
323
+ # Set sources.
324
+ #
325
+ def sources=(sources)
326
+ @data[:sources] = Array(sources)
327
+ end
328
+
329
+ #
330
+ # Convert to canonical hash.
331
+ #
332
+ def to_h
333
+ h = super
334
+
335
+ h['version'] = version.to_s if version
336
+ h['repository'] = repository.to_h if repository
337
+
338
+ h.delete('groups') if h['groups'] && h['groups'].empty?
339
+ h.delete('engines') if h['engines'] && h['engines'].empty?
340
+ h.delete('platforms') if h['platforms'] && h['platforms'].empty?
341
+ h.delete('sources') if h['sources'] && h['sources'].empty?
342
+
343
+ h
344
+ end
345
+
346
+ private
347
+
348
+ # ensure engine entries are strings
349
+ #def engines_to_h
350
+ # engines.map do |engine|
351
+ # hash = {}
352
+ # hash['name'] = engine['name']
353
+ # hash['version'] = engine['version'].to_s
354
+ # hash
355
+ # end
356
+ #end
357
+
358
+ end
359
+
360
+ end