indexer 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.
- data/.index +54 -0
- data/HISTORY.md +9 -0
- data/README.md +145 -0
- data/bin/index +7 -0
- data/data/indexer/r2013/index.kwalify +175 -0
- data/data/indexer/r2013/index.yes +172 -0
- data/data/indexer/r2013/index.yesi +67 -0
- data/data/indexer/r2013/ruby.txt +35 -0
- data/data/indexer/r2013/yaml.txt +30 -0
- data/lib/indexer.rb +65 -0
- data/lib/indexer/attributes.rb +171 -0
- data/lib/indexer/command.rb +260 -0
- data/lib/indexer/components.rb +8 -0
- data/lib/indexer/components/author.rb +140 -0
- data/lib/indexer/components/conflict.rb +78 -0
- data/lib/indexer/components/copyright.rb +95 -0
- data/lib/indexer/components/dependency.rb +18 -0
- data/lib/indexer/components/organization.rb +133 -0
- data/lib/indexer/components/repository.rb +140 -0
- data/lib/indexer/components/requirement.rb +360 -0
- data/lib/indexer/components/resource.rb +209 -0
- data/lib/indexer/conversion.rb +14 -0
- data/lib/indexer/conversion/gemfile.rb +44 -0
- data/lib/indexer/conversion/gemspec.rb +114 -0
- data/lib/indexer/conversion/gemspec_exporter.rb +304 -0
- data/lib/indexer/core_ext.rb +4 -0
- data/lib/indexer/error.rb +23 -0
- data/lib/indexer/gemfile.rb +75 -0
- data/lib/indexer/importer.rb +144 -0
- data/lib/indexer/importer/file.rb +94 -0
- data/lib/indexer/importer/gemfile.rb +27 -0
- data/lib/indexer/importer/gemspec.rb +43 -0
- data/lib/indexer/importer/html.rb +289 -0
- data/lib/indexer/importer/markdown.rb +45 -0
- data/lib/indexer/importer/ruby.rb +47 -0
- data/lib/indexer/importer/version.rb +38 -0
- data/lib/indexer/importer/yaml.rb +46 -0
- data/lib/indexer/loadable.rb +159 -0
- data/lib/indexer/metadata.rb +879 -0
- data/lib/indexer/model.rb +237 -0
- data/lib/indexer/revision.rb +43 -0
- data/lib/indexer/valid.rb +287 -0
- data/lib/indexer/validator.rb +313 -0
- data/lib/indexer/version/constraint.rb +124 -0
- data/lib/indexer/version/exceptions.rb +11 -0
- data/lib/indexer/version/number.rb +497 -0
- 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
|