indexer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|